Snap for 8426163 from 678a3d564813c41376a7ed56ac4e63acf4043346 to mainline-tzdata2-release

Change-Id: I44a728fa343eaf8f7c8cae20bc914145768678eb
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index 328d4b1..0000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,214 +0,0 @@
-name: CI
-
-on:
-  push:
-    branches:
-      - master
-  pull_request:
-
-jobs:
-  bazel-test:
-    name: 'Bazel tests'
-    runs-on: ubuntu-latest
-    steps:
-      - name: 'Check out repository'
-        uses: actions/checkout@v2
-      - name: 'Cache local Maven repository'
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.m2/repository
-            !~/.m2/repository/com/google/dagger
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: 'Cache Bazel files'
-        uses: actions/cache@v2
-        with:
-          path: ~/.cache/bazel
-          key: ${{ runner.os }}-bazel-${{ github.sha }}
-          restore-keys: |
-            ${{ runner.os }}-bazel-
-      - name: 'Cache Gradle files'
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.gradle/caches
-            ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
-          restore-keys: |
-            ${{ runner.os }}-gradle-
-      - name: 'Run Bazel tests'
-        run: bazel test --test_output=errors //...
-        shell: bash
-      - name: 'Install local snapshot'
-        run: ./util/install-local-snapshot.sh
-        shell: bash
-      - name: 'Upload local snapshot for tests'
-        uses: actions/upload-artifact@v2
-        with:
-          name: local-snapshot
-          path: ~/.m2/repository/com/google/dagger
-  artifact-java-local-tests:
-    name: 'Artifact Java local tests'
-    needs: bazel-test
-    runs-on: ubuntu-latest
-    steps:
-    - name: 'Check out repository'
-      uses: actions/checkout@v2
-    - name: 'Cache Gradle files'
-      uses: actions/cache@v2
-      with:
-        path: |
-          ~/.gradle/caches
-          ~/.gradle/wrapper
-        key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
-        restore-keys: |
-          ${{ runner.os }}-gradle-
-    - name: 'Download local snapshot for tests'
-      uses: actions/download-artifact@v2
-      with:
-        name: local-snapshot
-        path: ~/.m2/repository/com/google/dagger
-    - name: 'Gradle Java local tests'
-      run: ./util/run-local-gradle-tests.sh
-      shell: bash
-  artifact-android-local-tests:
-    name: 'Artifact Android local tests (AGP ${{ matrix.agp }})'
-    needs: bazel-test
-    runs-on: ubuntu-latest
-    strategy:
-      matrix:
-        agp: ['4.1.0', '4.2.0-beta04']
-    steps:
-      - name: 'Check out repository'
-        uses: actions/checkout@v2
-      - name: 'Cache Gradle files'
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.gradle/caches
-            ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
-          restore-keys: |
-            ${{ runner.os }}-gradle-
-      - name: 'Download local snapshot for tests'
-        uses: actions/download-artifact@v2
-        with:
-          name: local-snapshot
-          path: ~/.m2/repository/com/google/dagger
-      - name: 'Gradle Android local tests (AGP ${{ matrix.agp }})'
-        run: ./util/run-local-gradle-android-tests.sh "${{ matrix.agp }}"
-        shell: bash
-  artifact-android-emulator-tests:
-    name: 'Artifact Android emulator tests (API 30)'
-    needs: bazel-test
-    # It's recommended to run emulator tests on macOS
-    # See https://github.com/marketplace/actions/android-emulator-runner
-    runs-on: macos-latest
-    steps:
-      - name: 'Check out repository'
-        uses: actions/checkout@v2
-      - name: 'Cache Gradle files'
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.gradle/caches
-            ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
-          restore-keys: |
-            ${{ runner.os }}-gradle-
-      - name: 'Download local snapshot for tests'
-        uses: actions/download-artifact@v2
-        with:
-          name: local-snapshot
-          path: ~/.m2/repository/com/google/dagger
-      - name: 'Gradle Android emulator tests (API 30)'
-        uses: reactivecircus/android-emulator-runner@v2
-        timeout-minutes: 25
-        with:
-          api-level: 30
-          target: google_apis
-          script: ./util/run-local-emulator-tests.sh
-  publish-snapshot:
-    name: 'Publish snapshot'
-    # TODO(bcorso): Consider also waiting on artifact-android-emulator-tests
-    # and artifact-android-emulator-legacy-api-tests after checking flakiness.
-    needs: [bazel-test, artifact-java-local-tests, artifact-android-local-tests]
-    if: github.event_name == 'push' && github.repository == 'google/dagger' && github.ref == 'refs/heads/master'
-    runs-on: ubuntu-latest
-    steps:
-      - name: 'Check out repository'
-        uses: actions/checkout@v2
-      - name: 'Cache local Maven repository'
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.m2/repository
-            !~/.m2/repository/com/google/dagger
-          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
-          restore-keys: |
-            ${{ runner.os }}-maven-
-      - name: 'Cache Bazel files'
-        uses: actions/cache@v2
-        with:
-          path: ~/.cache/bazel
-          key: ${{ runner.os }}-bazel-${{ github.sha }}
-          restore-keys: |
-            ${{ runner.os }}-bazel-
-      - name: 'Cache Gradle files'
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.gradle/caches
-            ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
-          restore-keys: |
-            ${{ runner.os }}-gradle-
-      - name: 'Publish latest docs'
-        run: ./util/generate-latest-docs.sh
-        shell: bash
-        env:
-          GH_TOKEN: ${{ github.token }}
-      - name: 'Publish latest snapshot'
-        run: ./util/publish-snapshot-on-commit.sh
-        shell: bash
-        env:
-          CI_DEPLOY_USERNAME: ${{ secrets.CI_DEPLOY_USERNAME }}
-          CI_DEPLOY_PASSWORD: ${{ secrets.CI_DEPLOY_PASSWORD }}
-  artifact-android-emulator-legacy-api-tests:
-    name: 'Artifact Android emulator tests (API ${{ matrix.api-level }})'
-    # We only run this on master push (essentially a postsubmit) since these
-    # can take a while to run
-    if: github.event_name == 'push' && github.repository == 'google/dagger' && github.ref == 'refs/heads/master'
-    needs: bazel-test
-    # It's recommended to run emulator tests on macOS
-    # See https://github.com/marketplace/actions/android-emulator-runner
-    runs-on: macos-latest
-    strategy:
-      matrix:
-        api-level: [16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 29]
-    steps:
-      - name: 'Check out repository'
-        uses: actions/checkout@v2
-      - name: 'Cache Gradle files'
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.gradle/caches
-            ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
-          restore-keys: |
-            ${{ runner.os }}-gradle-
-      - name: 'Download local snapshot for tests'
-        uses: actions/download-artifact@v2
-        with:
-          name: local-snapshot
-          path: ~/.m2/repository/com/google/dagger
-      - name: 'Gradle Android emulator tests (API ${{ matrix.api-level }})'
-        uses: reactivecircus/android-emulator-runner@v2
-        timeout-minutes: 25
-        with:
-          api-level: ${{ matrix.api-level }}
-          target: google_apis
-          script: ./util/run-local-emulator-tests.sh
diff --git a/.gitignore b/.gitignore
index 1f7ead8..fabb38f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,8 +30,6 @@
 
 gen-external-apklibs
 
-bazel-*
+/bazel-*
 
 *.pyc
-
-.gradle
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..9015f2e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,65 @@
+language: android
+
+os: linux
+dist: trusty
+sudo: required
+addons:
+  apt:
+    sources:
+      - ubuntu-toolchain-r-test
+    packages:
+      - libstdc++-4.9-dev # https://github.com/nodegit/nodegit/issues/853
+      - gcc-4.8
+      - g++-4.8
+
+jdk:
+  - &jdk_for_publishing oraclejdk8
+
+android:
+  components:
+    - tools
+    - tools # Duplicated as per https://github.com/travis-ci/travis-ci/issues/6040#issuecomment-219367943
+    - build-tools-26.0.2
+    - android-26
+    - platform-tools
+    - extra-android-m2repository
+
+before_install:
+  - wget https://github.com/bazelbuild/bazel/releases/download/"${BAZEL_VERSION}"/bazel_"${BAZEL_VERSION}"-linux-x86_64.deb
+  - sudo dpkg -i bazel_"${BAZEL_VERSION}"-linux-x86_64.deb
+  - sudo rm -f /etc/mavenrc
+  - wget http://www.us.apache.org/dist/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.tar.gz
+  - tar -zxf apache-maven-3.1.1-bin.tar.gz
+  - export PATH="$PWD/apache-maven-3.1.1/bin:$PATH"
+  - mkdir travis_bin
+  - ln -s $(which gcc-4.8) travis_bin/gcc
+  - ln -s $(which g++-4.8) travis_bin/g++
+  - export PATH="${PWD}/travis_bin:${PATH}"
+
+script:
+  - bazel test --test_output errors //...
+  - pushd examples && mvn compile && popd
+
+env:
+  global:
+    # Encrypted credentials for deploying snapshots.
+    - secure: eGc3LHBRIPmTnXLM1YoIqG1do9BkpFI2pJm3fz5Cd8UaXtf7Oefa+Ts3rcn4ipee5A+lf8kEouPshSoaQs81KZ2/qf8rSTCIqeFjHR8hzmOVYo/0zRfS/VSUT0yqN+jeRhuNk3+A49RTPlcfJqPv3tyddtrM1vF7axhCJPQIRJM=
+    - secure: LTzrlqcSNeZTOV52D3ibY9RBdxY4Yu8dUOYhAonrWLE+eDTzuoyCzcPw8pEcYVNUi1rG6Q7v3QBDTnBztsPoCbcN5tEGjw5cQEbfEzSTkWaNCFjncWn36cLwx9lgbF+5Db/L0mYJ36unDKUpKVC8AgOtxQibfv/ffugfxxj8ohY=
+
+    # Encrypted GitHub access token to allow util/generate-latest-docs.sh to
+    # push Javadoc to gh-pages.
+    # This uses an access token created by cgdecker and will need to be updated
+    # (see util/generate-latest-docs.sh for a link) if he no longer has
+    # permission to push to the repo.
+    - secure: "UpTUhCQzAGbr5JetRg2GZxp/dPDep/7Il3yGeyDECopciWdx41OPk/QNqAXBhNtKuEaMVsmASyoteuhgaTryQdV4qUIGVOMhES6kbOlYy3nwK44VdsNeeepwVospyDyZbxMtXq5LuHWuTADmAl1mdjNPNoziXc523zjnUzUx/EQ="
+    - JDK_FOR_PUBLISHING: *jdk_for_publishing
+    - BAZEL_VERSION="0.24.1"
+
+after_success:
+  - util/generate-latest-docs.sh
+  - util/publish-snapshot-on-commit.sh
+
+branches:
+  only:
+    - master
+    - /^release.*$/
diff --git a/Android.bp b/Android.bp
index 1bdbd1b..27a05c5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,46 +12,87 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package {
-    default_visibility: [":__subpackages__"],
-    default_applicable_licenses: ["external_dagger2_license"],
+java_import_host {
+    name: "dagger2-auto-common",
+    jars: ["lib/auto-common-0.10.jar"],
 }
 
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-//
-// large-scale-change included anything that looked like it might be a license
-// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.
-//
-// Please consider removing redundant or irrelevant files from 'license_text:'.
-// See: http://go/android-license-faq
-license {
-    name: "external_dagger2_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-Apache-2.0",
-        "legacy_not_a_contribution",
-    ],
-    license_text: [
-        "LICENSE.txt",
-        "NOTICE",
+java_import_host {
+    name: "dagger2-auto-factory-jar",
+    jars: ["lib/auto-factory-1.0-beta6.jar"],
+}
+
+java_plugin {
+    name: "dagger2-auto-factory",
+    processor_class: "com.google.auto.factory.processor.AutoFactoryProcessor",
+    static_libs: [
+        "dagger2-auto-factory-jar",
+        "dagger2-auto-common",
+        "guava",
+        "javapoet",
+        "dagger2-google-java-format",
     ],
 }
 
 java_import_host {
+    name: "dagger2-auto-service-jar",
+    jars: ["lib/auto-service-1.0-rc5.jar"],
+}
+
+java_import_host {
+    name: "dagger2-auto-service-annotations",
+    jars: ["lib/auto-service-annotations-1.0-rc5.jar"],
+}
+
+java_plugin {
+    name: "dagger2-auto-service",
+    processor_class: "com.google.auto.service.processor.AutoServiceProcessor",
+    static_libs: [
+        "dagger2-auto-common",
+        "dagger2-auto-service-jar",
+        "dagger2-auto-service-annotations",
+        "guava",
+    ],
+}
+
+java_import_host {
+    name: "dagger2-auto-value-jar",
+    jars: ["lib/auto-value-1.6.5.jar"],
+}
+
+java_import_host {
+    name: "dagger2-auto-value-annotations",
+    jars: ["lib/auto-value-annotations-1.6.5.jar"],
+}
+
+java_plugin {
+    name: "dagger2-auto-value",
+    processor_class: "com.google.auto.value.processor.AutoValueProcessor",
+    static_libs: [
+        "dagger2-auto-value-jar",
+        "dagger2-auto-value-annotations",
+    ],
+}
+
+java_plugin {
+    name: "dagger2-auto-annotation",
+    processor_class: "com.google.auto.value.processor.AutoAnnotationProcessor",
+    static_libs: ["dagger2-auto-value-jar"],
+}
+
+java_import_host {
+    name: "dagger2-google-java-format",
+    jars: ["lib/google-java-format-1.7-all-deps.jar"],
+}
+
+java_import_host {
+    name: "dagger2-inject",
+    jars: ["lib/javax.inject-1.jar"],
+}
+
+java_import_host {
     name: "dagger2-bootstrap-compiler-jar",
-    jars: ["java/dagger/internal/codegen/bootstrap/bootstrap_compiler_deploy.jar"],
+    jars: ["java/dagger/internal/codegen/bootstrap_compiler_deploy.jar"],
 }
 
 java_plugin {
@@ -59,42 +100,36 @@
     processor_class: "dagger.internal.codegen.ComponentProcessor",
     generates_api: true,
     static_libs: ["dagger2-bootstrap-compiler-jar"],
-    jarjar_rules: "jarjar-rules.txt",
 }
 
-java_library {
+java_library_host {
     name: "dagger2",
-    visibility: ["//visibility:public"],
-    host_supported: true,
 
     srcs: [
         "java/dagger/*.java",
-        "java/dagger/assisted/*.java",
         "java/dagger/internal/*.java",
         "java/dagger/multibindings/*.java",
         "java/dagger/releasablereferences/*.java",
     ],
     exclude_srcs: ["java/dagger/android/**/*.java"],
 
-    libs: [
-        "guava",
-        "jsr330",
-    ],
+    static_libs: ["dagger2-inject"],
+
+    libs: ["guava"],
 
     java_version: "1.8",
-    sdk_version: "core_current",
 }
 
 // build dagger2 producers library
 // ============================================================
 
-java_library {
+java_library_host {
     name: "dagger2-producers",
-    host_supported: true,
 
     srcs: ["java/dagger/producers/**/*.java"],
 
     static_libs: [
+        "dagger2-inject",
         "error_prone_annotations",
     ],
 
@@ -102,11 +137,9 @@
         "dagger2",
         "dagger2-android-annotation-stubs",
         "guava",
-        "jsr330",
     ],
 
     java_version: "1.8",
-    sdk_version: "core_current",
 }
 
 // build dagger2 compiler plugin
@@ -114,16 +147,8 @@
 
 java_plugin {
     name: "dagger2-compiler",
-    visibility: ["//visibility:public"],
     processor_class: "dagger.internal.codegen.ComponentProcessor",
     generates_api: true,
-    static_libs: ["dagger2-compiler-lib"],
-    // shade guava to avoid conflicts with guava embedded in Error Prone.
-    jarjar_rules: "jarjar-rules.txt",
-}
-
-java_library_host {
-    name: "dagger2-compiler-lib",
     use_tools_jar: true,
 
     srcs: [
@@ -136,7 +161,7 @@
 
     exclude_srcs: [
         "java/dagger/internal/codegen/BindingGraphStatisticsCollector.java",
-        "java/dagger/internal/codegen/kythe/DaggerKythePlugin.java",
+        "java/dagger/internal/codegen/DaggerKythePlugin.java",
     ],
 
     // Manually include META-INF/services/javax.annotation.processing.Processor
@@ -144,32 +169,30 @@
     java_resource_dirs: ["resources"],
 
     static_libs: [
-        "auto_common",
         "dagger2",
+        "dagger2-auto-common",
+        "dagger2-auto-factory",
+        "dagger2-auto-service",
+        "dagger2-auto-value",
+        "dagger2-google-java-format",
+        "dagger2-inject",
         "dagger2-producers",
-        "google_java_format",
         "guava",
         "javapoet",
-        "jsr330",
-        "kotlin-stdlib",
-        "kotlinx_metadata_jvm",
     ],
 
+    // shade guava to avoid conflicts with guava embedded in Error Prone.
+    jarjar_rules: "jarjar-rules.txt",
 
     libs: [
-        "auto_factory_annotations",
-        "auto_service_annotations",
-        "auto_value_annotations",
-        "auto_value_memoized_extension_annotations",
         "dagger2-android-annotation-stubs",
     ],
 
     plugins: [
-        "auto_factory_plugin",
-        "auto_service_plugin",
-        "auto_value_plugin",
-        "auto_value_memoized_extension_plugin",
-        "auto_annotation_plugin",
+        "dagger2-auto-factory",
+        "dagger2-auto-service",
+        "dagger2-auto-value",
+        "dagger2-auto-annotation",
         "dagger2-bootstrap-compiler",
     ],
 
@@ -189,233 +212,3 @@
     sdk_version: "core_current",
     srcs: ["android-annotation-stubs/src/**/*.java"],
 }
-
-// build core hilt library
-
-java_library {
-    name: "hilt_core",
-    srcs: [
-        "java/dagger/hilt/*.java",
-        "java/dagger/hilt/codegen/*.java",
-        "java/dagger/hilt/components/*.java",
-        "java/dagger/hilt/internal/*.java",
-        "java/dagger/hilt/internal/aliasof/*.java",
-        "java/dagger/hilt/internal/definecomponent/*.java",
-        "java/dagger/hilt/internal/generatesrootinput/*.java",
-        "java/dagger/hilt/migration/*.java",
-        "java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDeps.java",
-    ],
-    static_libs: [
-        "jsr305",
-        "jsr330",
-        "dagger2",
-    ],
-    sdk_version: "core_current",
-    plugins: [
-        "hilt_define_component_processor",
-        "hilt_generates_root_input_processor",
-    ],
-}
-
-// Build the android hilt library.  Depending on this will enable the Hilt annotation processors.
-
-android_library {
-    name: "hilt_android",
-    visibility: ["//visibility:public"],
-
-    srcs: [
-        "java/dagger/hilt/android/*.java",
-        "java/dagger/hilt/android/components/*.java",
-        "java/dagger/hilt/android/migration/*.java",
-        "java/dagger/hilt/android/qualifiers/*.java",
-        "java/dagger/hilt/android/scopes/*.java",
-        "java/dagger/hilt/android/internal/*.java",
-        "java/dagger/hilt/android/internal/builders/*.java",
-        "java/dagger/hilt/android/internal/lifecycle/*.java",
-        "java/dagger/hilt/android/internal/managers/*.java",
-        "java/dagger/hilt/android/internal/migration/*.java",
-        "java/dagger/hilt/android/internal/modules/*.java",
-        "java/dagger/hilt/android/lifecycle/*.java",
-    ],
-    manifest: "java/dagger/hilt/android/AndroidManifest.xml",
-    static_libs: [
-        "androidx.annotation_annotation",
-        "androidx.fragment_fragment",
-        "jsr305",
-        "jsr330",
-        "dagger2",
-        "hilt_core",
-    ],
-    sdk_version: "current",
-    min_sdk_version: "14",
-    plugins: [
-        "dagger2-compiler",
-        "hilt_android_entry_point_processor",
-        "hilt_aggregated_deps_processor",
-        "hilt_define_component_processor",
-        "hilt_generates_root_input_processor",
-        "hilt_originating_element_processor",
-        "hilt_root_processor",
-    ],
-    exported_plugins: [
-        "dagger2-compiler",
-        "hilt_android_entry_point_processor",
-        "hilt_aggregated_deps_processor",
-        "hilt_alias_of_processor",
-        "hilt_define_component_processor",
-        "hilt_generates_root_input_processor",
-        "hilt_originating_element_processor",
-        "hilt_root_processor",
-        "hilt_viewmodel_processor",
-    ],
-}
-
-android_library {
-    name: "hilt_android_testing",
-    visibility: ["//visibility:public"],
-
-    srcs: [
-        "java/dagger/hilt/android/internal/testing/*.java",
-        "java/dagger/hilt/android/testing/*.java",
-    ],
-    manifest: "java/dagger/hilt/android/testing/AndroidManifest.xml",
-    static_libs: [
-        "auto_value_annotations",
-        "androidx.annotation_annotation",
-        "androidx.fragment_fragment",
-        "androidx.annotation_annotation",
-        "androidx.fragment_fragment",
-        "androidx.test.core",
-        "android-support-multidex",
-        "jsr305",
-        "dagger2",
-        "hilt_core",
-        "junit",
-    ],
-    sdk_version: "current",
-    min_sdk_version: "14",
-    plugins: [
-        "auto_value_plugin",
-        "dagger2-compiler",
-        "hilt_generates_root_input_processor",
-    ],
-    exported_plugins: [
-        "dagger2-compiler",
-        "hilt_android_entry_point_processor",
-        "hilt_aggregated_deps_processor",
-        "hilt_define_component_processor",
-        "hilt_generates_root_input_processor",
-        "hilt_originating_element_processor",
-        "hilt_root_processor",
-	"hilt_viewmodel_processor",
-        "hilt_custom_test_application_processor",
-        "hilt_bindvalue_processor",
-        "hilt_uninstall_modules_processor",
-    ],
-}
-
-// Hilt has many annotation processors.  To reduce compilation and runtime cost, they are all compiled
-// into hilt_android_processors.  A java_plugin can only expose a single processor class, so each has
-// to be defined separately.  Since they are not visible outside this package and will always be
-// exported together, only the first actually contains the annotation processor classes.
-java_plugin {
-    name: "hilt_generates_root_input_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.processor.internal.generatesrootinput.GeneratesRootInputProcessor",
-    static_libs: ["hilt_android_processors"],
-}
-
-java_plugin {
-    name: "hilt_android_entry_point_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.android.processor.internal.androidentrypoint.AndroidEntryPointProcessor",
-}
-
-java_plugin {
-    name: "hilt_aggregated_deps_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.processor.internal.aggregateddeps.AggregatedDepsProcessor",
-}
-
-java_plugin {
-    name: "hilt_alias_of_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.processor.internal.aliasof.AliasOfProcessor",
-}
-
-java_plugin {
-    name: "hilt_define_component_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.processor.internal.definecomponent.DefineComponentProcessor",
-}
-
-java_plugin {
-    name: "hilt_originating_element_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.processor.internal.originatingelement.OriginatingElementProcessor",
-}
-
-java_plugin {
-    name: "hilt_root_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.processor.internal.root.RootProcessor",
-}
-
-java_plugin {
-    name: "hilt_viewmodel_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.android.processor.internal.viewmodel.ViewModelProcessor",
-}
-
-// Hilt testing processors
-java_plugin {
-    name: "hilt_custom_test_application_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.android.processor.internal.customtestapplication.CustomTestApplicationProcessor",
-}
-
-java_plugin {
-    name: "hilt_bindvalue_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.android.processor.internal.bindvalue.BindValueProcessor",
-}
-
-java_plugin {
-    name: "hilt_uninstall_modules_processor",
-    generates_api: true,
-    processor_class: "dagger.hilt.android.processor.internal.uninstallmodules.UninstallModulesProcessor",
-}
-
-java_library_host {
-    name: "hilt_android_processors",
-    use_tools_jar: true,
-    srcs: [
-        "java/dagger/hilt/android/processor/**/*.java",
-        "java/dagger/hilt/android/processor/**/*.kt",
-        "java/dagger/hilt/codegen/*.java",
-        "java/dagger/hilt/processor/internal/**/*.java",
-    ],
-    plugins: [
-        "auto_service_plugin",
-        "auto_value_plugin",
-        "auto_value_memoized_extension_plugin",
-        "dagger2-compiler",
-    ],
-    static_libs: [
-        "auto_common",
-        "auto_service_annotations",
-        "auto_value_annotations",
-        "auto_value_memoized_extension_annotations",
-        "guava",
-        "jsr305",
-        "dagger2-compiler-lib",
-        "dagger2",
-        "javapoet",
-        "jsr330",
-        "kotlin-stdlib",
-        "kotlinx_metadata_jvm",
-        "dagger2-android-annotation-stubs",
-    ],
-    // shade guava to avoid conflicts with guava embedded in Error Prone.
-    jarjar_rules: "jarjar-rules.txt",
-}
diff --git a/BUILD b/BUILD
index 015e849..8becb3e 100644
--- a/BUILD
+++ b/BUILD
@@ -12,25 +12,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("@rules_java//java:defs.bzl", "java_library")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-load("@google_bazel_common//tools/jarjar:jarjar.bzl", "jarjar_library")
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "define_kt_toolchain")
-
 package(default_visibility = ["//visibility:public"])
 
-define_kt_toolchain(
-    name = "kotlin_toolchain",
-    api_version = "1.4",
-    jvm_target = "1.8",
-    language_version = "1.4",
-)
-
 package_group(
     name = "src",
     packages = ["//..."],
 )
 
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+
 java_library(
     name = "dagger_with_compiler",
     exported_plugins = ["//java/dagger/internal/codegen:component-codegen"],
@@ -45,22 +35,6 @@
     ],
 )
 
-java_library(
-    name = "spi",
-    exports = ["//java/dagger/spi"],
-)
-
-java_library(
-    name = "compiler_internals",
-    exports = [
-        "//java/dagger/internal/codegen:processor",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/validation",
-        "//java/dagger/internal/codegen/writing",
-    ],
-)
-
 android_library(
     name = "android",
     exported_plugins = ["//java/dagger/android/processor:plugin"],
@@ -75,48 +49,118 @@
     ],
 )
 
+load("@google_bazel_common//tools/jarjar:jarjar.bzl", "jarjar_library")
+
+SHADE_RULES = ["rule com.google.auto.common.** dagger.shaded.auto.common.@1"]
+
+jarjar_library(
+    name = "shaded_compiler",
+    jars = [
+        "//java/dagger/internal/codegen:base",
+        "//java/dagger/internal/codegen:binding",
+        "//java/dagger/internal/codegen:binding_graph_validation",
+        "//java/dagger/internal/codegen:jdk-and-guava-extras",
+        "//java/dagger/internal/codegen:processor",
+        "//java/dagger/internal/codegen:validation",
+        "//java/dagger/internal/codegen:writing",
+        "//java/dagger/internal/codegen/javapoet",
+        "//java/dagger/internal/codegen/langmodel",
+        "//java/dagger/internal/codegen/serialization",
+        "//java/dagger/model:internal-proxies",
+        "//java/dagger/errorprone",
+        "@com_google_auto_auto_common//jar",
+    ],
+    rules = SHADE_RULES,
+)
+
+jarjar_library(
+    name = "shaded_compiler_src",
+    jars = [
+        "//java/dagger/internal/codegen:libbase-src.jar",
+        "//java/dagger/internal/codegen:libbinding-src.jar",
+        "//java/dagger/internal/codegen:libbinding_graph_validation-src.jar",
+        "//java/dagger/internal/codegen:libjdk-and-guava-extras-src.jar",
+        "//java/dagger/internal/codegen:libprocessor-src.jar",
+        "//java/dagger/internal/codegen:libvalidation-src.jar",
+        "//java/dagger/internal/codegen:libwriting-src.jar",
+        "//java/dagger/internal/codegen/javapoet:libjavapoet-src.jar",
+        "//java/dagger/internal/codegen/langmodel:liblangmodel-src.jar",
+        # TODO(ronshapiro): is there a generated src.jar for protos in Bazel?
+        "//java/dagger/errorprone:liberrorprone-src.jar",
+    ],
+)
+
+jarjar_library(
+    name = "shaded_spi",
+    jars = [
+        "//java/dagger/internal/codegen:jdk-and-guava-extras",
+        "//java/dagger/model",
+        "//java/dagger/spi",
+        "@com_google_auto_auto_common//jar",
+    ],
+    rules = SHADE_RULES,
+)
+
+jarjar_library(
+    name = "shaded_spi_src",
+    jars = [
+        "//java/dagger/internal/codegen:libjdk-and-guava-extras-src.jar",
+        "//java/dagger/model:libmodel-src.jar",
+        "//java/dagger/spi:libspi-src.jar",
+    ],
+)
+
+javadoc_library(
+    name = "spi-javadoc",
+    srcs = [
+        "//java/dagger/model:model-srcs",
+        "//java/dagger/spi:spi-srcs",
+    ],
+    root_packages = [
+        "dagger.model",
+        "dagger.spi",
+    ],
+    deps = [
+        "//java/dagger/model",
+        "//java/dagger/spi",
+    ],
+)
+
 jarjar_library(
     name = "shaded_android_processor",
     jars = [
         "//java/dagger/android/processor",
-        "@maven//:com_google_auto_auto_common",
+        "@com_google_auto_auto_common//jar",
     ],
-    rules = [
-        "rule com.google.auto.common.** dagger.android.shaded.auto.common.@1",
-    ],
+    rules = SHADE_RULES,
 )
 
 jarjar_library(
     name = "shaded_grpc_server_processor",
     jars = [
         "//java/dagger/grpc/server/processor",
-        "@maven//:com_google_auto_auto_common",
+        "@com_google_auto_auto_common//jar",
     ],
-    rules = [
-        "rule com.google.auto.common.** dagger.grpc.shaded.auto.common.@1",
-    ],
+    rules = SHADE_RULES,
 )
 
 # coalesced javadocs used for the gh-pages site
 javadoc_library(
     name = "user-docs",
-    testonly = 1,
     srcs = [
         "//java/dagger:javadoc-srcs",
         "//java/dagger/android:android-srcs",
         "//java/dagger/android/support:support-srcs",
         "//java/dagger/grpc/server:javadoc-srcs",
         "//java/dagger/grpc/server/processor:javadoc-srcs",
-        "//java/dagger/hilt:javadoc-srcs",
+        "//java/dagger/model:model-srcs",
         "//java/dagger/producers:producers-srcs",
         "//java/dagger/spi:spi-srcs",
     ],
-    android_api_level = 30,
+    android_api_level = 26,
     # TODO(ronshapiro): figure out how to specify the version number for release builds
     doctitle = "Dagger Dependency Injection API",
     exclude_packages = [
-        "dagger.hilt.android.internal",
-        "dagger.hilt.internal",
         "dagger.internal",
         "dagger.producers.internal",
         "dagger.producers.monitoring.internal",
@@ -128,8 +172,7 @@
         "//java/dagger/android/support",
         "//java/dagger/grpc/server",
         "//java/dagger/grpc/server/processor",
-        "//java/dagger/hilt/android:artifact-lib",
-        "//java/dagger/hilt/android/testing:artifact-lib",
+        "//java/dagger/model",
         "//java/dagger/producers",
         "//java/dagger/spi",
     ],
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 54fb50a..45f15c4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -33,19 +33,11 @@
 *   [Install Bazel](https://docs.bazel.build/versions/master/install.html)
 *   Build the Dagger project with `bazel build <target>`
     *   Learn more about Bazel targets [here][bazel targets].
-    *   Building Dagger's Android targets requires additional setup:
-        *   Set the `ANDROID_HOME` environment variable to point to a directory
-            containing the Android SDK. If you do not have the Android SDK
-            installed, you'll have to
-            [download](https://developer.android.com/studio#command-tools)
-            and unzip it first.
-        *   Install the necessary components. For example, under Linux, run:
-            `$ANDROID_HOME/tools/bin/sdkmanager "platforms;android-30" "build-tools;30.0.2"`
-            *   If you skip this step, you will see an error similar to
-                `ERROR: missing input file '@androidsdk//:build-tools/30.0.2/aapt'`.
-            *   You may also need to run `bazel sync`.
+    *   If you see an error similar to `ERROR: missing input file
+        '@androidsdk//:build-tools/26.0.2/aapt'`, install the missing build
+        tools version with the android `sdkmanager` tool.
 *   Run tests with `bazel test <target>`, or `bazel test //...` to run all
-    tests.
+    tests
 *   You can install the Dagger libraries in your **local maven repository** by
     running the `./util/install-local-snapshot.sh` script.
     *   It will build the libraries and install them with a `LOCAL-SNAPSHOT`
diff --git a/METADATA b/METADATA
index 5eef5c3..59b9e25 100644
--- a/METADATA
+++ b/METADATA
@@ -11,7 +11,7 @@
     type: GIT
     value: "https://github.com/google/dagger"
   }
-  version: "dagger-2.19.1"
-  last_upgrade_date { year: 2020 month: 11 day: 18 }
-  license_type: NOTICE
+  version: "dagger-2.23.1"
+  last_upgrade_date { year: 2019 month: 6 day: 14 }
+  license_type: PERMISSIVE
 }
diff --git a/README.md b/README.md
index 393e2e7..a9ebc26 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,34 @@
-# Dagger
+# Dagger 2
 
 [![Maven Central][mavenbadge-svg]][mavencentral]
 
-A fast dependency injector for Java and Android.
+A fast dependency injector for Android and Java.
 
-Dagger is a compile-time framework for dependency injection. It uses no
-reflection or runtime bytecode generation, does all its analysis at
-compile-time, and generates plain Java source code.
+## About Google's Fork
 
-Dagger is actively maintained by the same team that works on [Guava]. Snapshot
-releases are auto-deployed to Sonatype's central Maven repository on every clean
-build with the version `HEAD-SNAPSHOT`. The current version builds upon previous
-work done at [Square][square].
+Dagger 2 is a compile-time evolution approach to dependency injection.
+Taking the approach started in Dagger 1.x to its ultimate conclusion,
+Dagger 2.x eliminates all reflection, and improves code clarity by
+removing the traditional ObjectGraph/Injector in favor of user-specified
+`@Component` interfaces.
+
+This github project represents the Dagger 2 development stream.  The earlier
+[project page][square] (Square, Inc's repository) represents the earlier 1.0
+development stream. Both versions have benefited from strong involvement from
+Square, Google, and other contributors.
+
+Dagger is currently in active development, primarily internally at Google,
+with regular pushes to the open-source community. Snapshot releases are
+auto-deployed to sonatype's central maven repository on every clean build with
+the version `HEAD-SNAPSHOT`.
+
+> [Dagger 2's main documentation website can be found here.][website]
 
 ## Documentation
 
 You can [find the dagger documentation here][website] which has extended usage
-instructions and other useful information. More detailed information can be
-found in the [API documentation][latestapi].
+instructions and other useful information.  Substantial usage information can be
+found in the [API documentation][20api].
 
 You can also learn more from [the original proposal][proposal],
 [this talk by Greg Kick][gaktalk], and on the dagger-discuss@googlegroups.com
@@ -27,154 +38,19 @@
 
 ### Bazel
 
-First, import the Dagger repository into your `WORKSPACE` file using
-[`http_archive`][bazel-external-deps].
+If you build with `bazel`, follow the [`bazel` documentation for referencing
+external projects][bazel-external-deps] to include Dagger in your build.
 
-Note: The `http_archive` must point to a tagged release of Dagger, not just any
-commit. The version of the Dagger artifacts will match the version of the tagged
-release.
+Given the following `WORKSPACE` definition, you can reference dagger via
+`@com_google_dagger//:dagger_with_compiler` in your deps.
 
 ```python
-# Top-level WORKSPACE file
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-
-DAGGER_TAG = "2.28.1"
-DAGGER_SHA = "9e69ab2f9a47e0f74e71fe49098bea908c528aa02fa0c5995334447b310d0cdd"
 http_archive(
-    name = "dagger",
-    strip_prefix = "dagger-dagger-%s" % DAGGER_TAG,
-    sha256 = DAGGER_SHA,
-    urls = ["https://github.com/google/dagger/archive/dagger-%s.zip" % DAGGER_TAG],
+    name = "com_google_dagger",
+    urls = ["https://github.com/google/dagger/archive/dagger-<version>.zip"],
 )
 ```
 
-Next you will need to setup targets that export the proper dependencies
-and plugins. Follow the sections below to setup the dependencies you need.
-
-#### Dagger Setup
-
-First, load the Dagger artifacts and repositories, and add them to your list of
-[`maven_install`] artifacts.
-
-```python
-# Top-level WORKSPACE file
-
-load("@dagger//:workspace_defs.bzl", "DAGGER_ARTIFACTS", "DAGGER_REPOSITORIES")
-
-maven_install(
-    artifacts = DAGGER_ARTIFACTS + [...],
-    repositories = DAGGER_REPOSITORIES + [...],
-)
-```
-
-Next, load and call [`dagger_rules`](https://github.com/google/dagger/blob/master/workspace_defs.bzl)
-in your top-level `BUILD` file:
-
-```python
-# Top-level BUILD file
-
-load("@dagger//:workspace_defs.bzl", "dagger_rules")
-
-dagger_rules()
-```
-
-This will add the following Dagger build targets:
-(Note that these targets already export all of the dependencies and processors
-they need).
-
-```python
-deps = [
-    ":dagger",                  # For Dagger
-    ":dagger-spi",              # For Dagger SPI
-    ":dagger-producers",        # For Dagger Producers
-]
-```
-
-#### Dagger Android Setup
-
-First, load the Dagger Android artifacts and repositories, and add them to your
-list of [`maven_install`] artifacts.
-
-```python
-# Top-level WORKSPACE file
-
-load(
-    "@dagger//:workspace_defs.bzl",
-    "DAGGER_ANDROID_ARTIFACTS",
-    "DAGGER_ANDROID_REPOSITORIES"
-)
-
-maven_install(
-    artifacts = DAGGER_ANDROID_ARTIFACTS + [...],
-    repositories = DAGGER_ANDROID_REPOSITORIES + [...],
-)
-```
-
-Next, load and call [`dagger_android_rules`](https://github.com/google/dagger/blob/master/workspace_defs.bzl)
-in your top-level `BUILD` file:
-
-```python
-# Top-level BUILD file
-
-load("@dagger//:workspace_defs.bzl", "dagger_android_rules")
-
-dagger_android_rules()
-```
-
-This will add the following Dagger Android build targets:
-(Note that these targets already export all of the dependencies and processors
-they need).
-
-```python
-deps = [
-    ":dagger-android",          # For Dagger Android
-    ":dagger-android-support",  # For Dagger Android (Support)
-]
-```
-
-#### Hilt Android Setup
-
-First, load the Hilt Android artifacts and repositories, and add them to your
-list of [`maven_install`] artifacts.
-
-```python
-# Top-level WORKSPACE file
-
-load(
-    "@dagger//:workspace_defs.bzl",
-    "HILT_ANDROID_ARTIFACTS",
-    "HILT_ANDROID_REPOSITORIES"
-)
-
-maven_install(
-    artifacts = HILT_ANDROID_ARTIFACTS + [...],
-    repositories = HILT_ANDROID_REPOSITORIES + [...],
-)
-```
-
-Next, load and call [`hilt_android_rules`](https://github.com/google/dagger/blob/master/workspace_defs.bzl)
-in your top-level `BUILD` file:
-
-```python
-# Top-level BUILD file
-
-load("@dagger//:workspace_defs.bzl", "hilt_android_rules")
-
-hilt_android_rules()
-```
-
-This will add the following Hilt Android build targets:
-(Note that these targets already export all of the dependencies and processors
-they need).
-
-```python
-deps = [
-    ":hilt-android",            # For Hilt Android
-    ":hilt-android-testing",    # For Hilt Android Testing
-]
-```
-
 ### Other build systems
 
 You will need to include the `dagger-2.x.jar` in your application's runtime.
@@ -248,11 +124,25 @@
 </dependencies>
 ```
 
-#### Gradle
+#### Java Gradle
+```groovy
+// Add plugin https://plugins.gradle.org/plugin/net.ltgt.apt
+plugins {
+  id "net.ltgt.apt" version "0.10"
+}
+
+// Add Dagger dependencies
+dependencies {
+  compile 'com.google.dagger:dagger:2.x'
+  apt 'com.google.dagger:dagger-compiler:2.x'
+}
+```
+
+#### Android Gradle
 ```groovy
 // Add Dagger dependencies
 dependencies {
-  implementation 'com.google.dagger:dagger:2.x'
+  compile 'com.google.dagger:dagger:2.x'
   annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
 }
 ```
@@ -260,19 +150,13 @@
 If you're using classes in `dagger.android` you'll also want to include:
 
 ```groovy
-implementation 'com.google.dagger:dagger-android:2.x'
-implementation 'com.google.dagger:dagger-android-support:2.x' // if you use the support libraries
+compile 'com.google.dagger:dagger-android:2.x'
+compile 'com.google.dagger:dagger-android-support:2.x' // if you use the support libraries
 annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
 ```
 
-Notes:
-
--   We use `implementation` instead of `api` for better compilation performance.
-    -   See the [Gradle documentation][gradle-api-implementation] for more
-        information on how to select appropriately, and the [Android Gradle
-        plugin documentation][gradle-api-implementation-android] for Android
-        projects.
--   For Kotlin projects, use [`kapt`] in place of `annotationProcessor`.
+If you're using a version of the Android gradle plugin below `2.2`, see
+https://bitbucket.org/hvisser/android-apt.
 
 If you're using the [Android Databinding library][databinding], you may want to
 increase the number of errors that `javac` will print. When Dagger prints an
@@ -288,11 +172,16 @@
 }
 ```
 
-### Resources
+### Download
 
-*   [Documentation][website]
-*   [Javadocs][latestapi]
-*   [GitHub Issues]
+  * 2.x (google/dagger)
+    * [Dagger 2.0 Documentation][website]
+    * [Dagger 2.0 Javadocs][20api]
+    * [Dagger development Javadocs][latestapi] (from the `master` branch
+      on GitHub)
+    * [Google's Dagger project site on GitHub][project]
+  * 1.x (square/dagger)
+    * [Square's original Dagger project site on GitHub][square]
 
 
 If you do not use maven, gradle, ivy, or other build systems that consume
@@ -323,18 +212,13 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 
+[20api]: https://dagger.dev/api/2.0/
 [`bazel`]: https://bazel.build
 [bazel-external-deps]: https://docs.bazel.build/versions/master/external.html#depending-on-other-bazel-projects
-[`maven_install`]: https://github.com/bazelbuild/rules_jvm_external#exporting-and-consuming-artifacts-from-external-repositories
 [Building Dagger]: CONTRIBUTING.md#building-dagger
 [dagger-snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/dagger/
 [databinding]: https://developer.android.com/topic/libraries/data-binding/
 [gaktalk]: https://www.youtube.com/watch?v=oK_XtfXPkqw
-[GitHub Issues]: https://github.com/google/dagger/issues
-[gradle-api-implementation]: https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation
-[gradle-api-implementation-android]: https://developer.android.com/studio/build/dependencies#dependency_configurations
-[Guava]: https://github.com/google/guava
-[`kapt`]: https://kotlinlang.org/docs/reference/kapt.html
 [latestapi]: https://dagger.dev/api/latest/
 [mavenbadge-svg]: https://maven-badges.herokuapp.com/maven-central/com.google.dagger/dagger/badge.svg
 [mavencentral]: https://search.maven.org/artifact/com.google.dagger/dagger
diff --git a/WORKSPACE b/WORKSPACE
index 6c2b6b0..8758b38 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -12,143 +12,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Declare the nested workspace so that the top-level workspace doesn't try to
-# traverse it when calling `bazel build //...`
-local_repository(
-    name = "examples_bazel",
-    path = "examples/bazel",
-)
-
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "google_bazel_common",
-    sha256 = "d8aa0ef609248c2a494d5dbdd4c89ef2a527a97c5a87687e5a218eb0b77ff640",
-    strip_prefix = "bazel-common-4a8d451e57fb7e1efecbf9495587a10684a19eb2",
-    urls = ["https://github.com/google/bazel-common/archive/4a8d451e57fb7e1efecbf9495587a10684a19eb2.zip"],
+    strip_prefix = "bazel-common-26011657fee96a949c66500b1662c4c7288a4968",
+    urls = ["https://github.com/google/bazel-common/archive/26011657fee96a949c66500b1662c4c7288a4968.zip"],
 )
 
 load("@google_bazel_common//:workspace_defs.bzl", "google_common_workspace_rules")
 
 google_common_workspace_rules()
 
-RULES_JVM_EXTERNAL_TAG = "2.7"
-
-RULES_JVM_EXTERNAL_SHA = "f04b1466a00a2845106801e0c5cec96841f49ea4e7d1df88dc8e4bf31523df74"
-
-http_archive(
-    name = "rules_jvm_external",
-    sha256 = RULES_JVM_EXTERNAL_SHA,
-    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
-    url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
-)
-
-# rules_python and zlib are required by protobuf.
-# TODO(ronshapiro): Figure out if zlib is in fact necessary, or if proto can depend on the
+# This fixes an issue with protobuf starting to use zlib by default in 3.7.0.
+# TODO(ronshapiro): Figure out if this is in fact necessary, or if proto can depend on the
 # @bazel_tools library directly. See discussion in
 # https://github.com/protocolbuffers/protobuf/pull/5389#issuecomment-481785716
-# TODO(cpovirk): Should we eventually get rules_python from "Bazel Federation?"
-# https://github.com/bazelbuild/rules_python#getting-started
-
-http_archive(
-    name = "rules_python",
-    sha256 = "e5470e92a18aa51830db99a4d9c492cc613761d5bdb7131c04bd92b9834380f6",
-    strip_prefix = "rules_python-4b84ad270387a7c439ebdccfd530e2339601ef27",
-    urls = ["https://github.com/bazelbuild/rules_python/archive/4b84ad270387a7c439ebdccfd530e2339601ef27.tar.gz"],
-)
-
-http_archive(
+bind(
     name = "zlib",
-    build_file = "@com_google_protobuf//:third_party/zlib.BUILD",
-    sha256 = "629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff",
-    strip_prefix = "zlib-1.2.11",
-    urls = ["https://github.com/madler/zlib/archive/v1.2.11.tar.gz"],
+    actual = "@bazel_tools//third_party/zlib",
 )
-
-RULES_KOTLIN_COMMIT = "2c283821911439e244285b5bfec39148e7d90e21"
-
-RULES_KOTLIN_SHA = "b04cd539e7e3571745179da95069586b6fa76a64306b24bb286154e652010608"
-
-http_archive(
-    name = "io_bazel_rules_kotlin",
-    sha256 = RULES_KOTLIN_SHA,
-    strip_prefix = "rules_kotlin-%s" % RULES_KOTLIN_COMMIT,
-    type = "zip",
-    urls = ["https://github.com/bazelbuild/rules_kotlin/archive/%s.zip" % RULES_KOTLIN_COMMIT],
-)
-
-load("@io_bazel_rules_kotlin//kotlin:dependencies.bzl", "kt_download_local_dev_dependencies")
-
-kt_download_local_dev_dependencies()
-
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories")
-
-KOTLIN_VERSION = "1.4.20"
-
-KOTLINC_RELEASE_SHA = "11db93a4d6789e3406c7f60b9f267eba26d6483dcd771eff9f85bb7e9837011f"
-
-KOTLINC_RELEASE = {
-    "sha256": KOTLINC_RELEASE_SHA,
-    "urls": ["https://github.com/JetBrains/kotlin/releases/download/v{v}/kotlin-compiler-{v}.zip".format(v = KOTLIN_VERSION)],
-}
-
-kotlin_repositories(compiler_release = KOTLINC_RELEASE)
-
-register_toolchains("//:kotlin_toolchain")
-
-load("@rules_jvm_external//:defs.bzl", "maven_install")
-
-ANDROID_LINT_VERSION = "26.6.2"
-
-maven_install(
-    artifacts = [
-        "androidx.annotation:annotation:1.1.0",
-        "androidx.appcompat:appcompat:1.2.0",
-        "androidx.activity:activity:1.1.0",
-        "androidx.fragment:fragment:1.2.5",
-        "androidx.lifecycle:lifecycle-viewmodel:2.2.0",
-        "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0",
-        "androidx.multidex:multidex:2.0.1",
-        "androidx.savedstate:savedstate:1.0.0",
-        "androidx.test:monitor:1.1.1",
-        "androidx.test:core:1.1.0",
-        "com.google.auto:auto-common:0.11",
-        "com.android.support:appcompat-v7:25.0.0",
-        "com.android.support:support-annotations:25.0.0",
-        "com.android.support:support-fragment:25.0.0",
-        "com.android.tools.external.org-jetbrains:uast:%s" % ANDROID_LINT_VERSION,
-        "com.android.tools.external.com-intellij:intellij-core:%s" % ANDROID_LINT_VERSION,
-        "com.android.tools.external.com-intellij:kotlin-compiler:%s" % ANDROID_LINT_VERSION,
-        "com.android.tools.lint:lint:%s" % ANDROID_LINT_VERSION,
-        "com.android.tools.lint:lint-api:%s" % ANDROID_LINT_VERSION,
-        "com.android.tools.lint:lint-checks:%s" % ANDROID_LINT_VERSION,
-        "com.android.tools.lint:lint-tests:%s" % ANDROID_LINT_VERSION,
-        "com.android.tools:testutils:%s" % ANDROID_LINT_VERSION,
-        "com.github.tschuchortdev:kotlin-compile-testing:1.2.8",
-        "com.google.guava:guava:27.1-android",
-        "org.jetbrains.kotlin:kotlin-stdlib:%s" % KOTLIN_VERSION,
-        "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0",
-        "org.robolectric:robolectric:4.3.1",
-    ],
-    repositories = [
-        "https://repo1.maven.org/maven2",
-        "https://maven.google.com",
-        "https://jcenter.bintray.com/",  # Lint has one trove4j dependency in jCenter
-    ],
-)
-
-BAZEL_SKYLIB_VERSION = "1.0.2"
-
-BAZEL_SKYLIB_SHA = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44"
-
-http_archive(
-    name = "bazel_skylib",
-    sha256 = BAZEL_SKYLIB_SHA,
-    urls = [
-        "https://github.com/bazelbuild/bazel-skylib/releases/download/{version}/bazel-skylib-{version}.tar.gz".format(version = BAZEL_SKYLIB_VERSION),
-    ],
-)
-
-load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
-
-bazel_skylib_workspace()
diff --git a/android-annotation-stubs/gen_annotations.sh b/android-annotation-stubs/gen_annotations.sh
index d4a0290..21aeb46 100755
--- a/android-annotation-stubs/gen_annotations.sh
+++ b/android-annotation-stubs/gen_annotations.sh
@@ -59,8 +59,6 @@
 
 package net.ltgt.gradle.incap;
 public enum IncrementalAnnotationProcessorType {
-  AGGREGATING,
-  DYNAMIC,
-  ISOLATING
+  DYNAMIC
 }
 EOF
diff --git a/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessorType.java b/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessorType.java
index ef86328..83e3590 100644
--- a/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessorType.java
+++ b/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessorType.java
@@ -16,7 +16,5 @@
 
 package net.ltgt.gradle.incap;
 public enum IncrementalAnnotationProcessorType {
-  AGGREGATING,
-  DYNAMIC,
-  ISOLATING
+  DYNAMIC
 }
diff --git a/build_defs.bzl b/build_defs.bzl
index 932ca08..0bd7402 100644
--- a/build_defs.bzl
+++ b/build_defs.bzl
@@ -24,8 +24,3 @@
     "-target",
     "1.7",
 ]
-
-POM_VERSION = "2.29.1"
-
-# DO NOT remove the comment on the next line. It's used in deploy-to-maven-central.sh
-POM_VERSION_ALPHA = POM_VERSION  + "-alpha"
diff --git a/examples/BUILD b/examples/BUILD
deleted file mode 100644
index 5cd2290..0000000
--- a/examples/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2020 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.
-#
-# Description:
-#   Dagger examples
-
-package(default_visibility = ["//:src"])
diff --git a/examples/bazel/BUILD b/examples/bazel/BUILD
deleted file mode 100644
index 0f9a621..0000000
--- a/examples/bazel/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2020 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.
-#
-# Description:
-#   Dagger Bazel examples
-
-load("@dagger//:workspace_defs.bzl", "dagger_rules", "hilt_android_rules")
-
-dagger_rules()
-
-hilt_android_rules()
diff --git a/examples/bazel/WORKSPACE b/examples/bazel/WORKSPACE
deleted file mode 100644
index 23f93b1..0000000
--- a/examples/bazel/WORKSPACE
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (C) 2020 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.
-#
-# Description:
-#   Defines the Bazel workspace rules for the Dagger examples.
-
-########################
-# Load Dagger repository
-########################
-
-# TODO(bcorso): Replace with `http_archive` pointing to tagged released.
-local_repository(
-    name = "dagger",
-    path = "../../",
-)
-
-load(
-    "@dagger//:workspace_defs.bzl",
-    "DAGGER_ARTIFACTS",
-    "DAGGER_REPOSITORIES",
-    "HILT_ANDROID_ARTIFACTS",
-    "HILT_ANDROID_REPOSITORIES",
-)
-
-#########################
-# Load Android repository
-#########################
-
-android_sdk_repository(
-    name = "androidsdk",
-    api_level = 30,
-    build_tools_version = "30.0.2",
-)
-
-#############################
-# Load Robolectric repository
-#############################
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-
-http_archive(
-    name = "robolectric",
-    strip_prefix = "robolectric-bazel-4.1",
-    urls = ["https://github.com/robolectric/robolectric-bazel/archive/4.1.tar.gz"],
-)
-
-load("@robolectric//bazel:robolectric.bzl", "robolectric_repositories")
-
-robolectric_repositories()
-
-#########################
-# Load Maven repositories
-#########################
-
-RULES_JVM_EXTERNAL_TAG = "2.7"
-
-RULES_JVM_EXTERNAL_SHA = "f04b1466a00a2845106801e0c5cec96841f49ea4e7d1df88dc8e4bf31523df74"
-
-http_archive(
-    name = "rules_jvm_external",
-    sha256 = RULES_JVM_EXTERNAL_SHA,
-    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
-    url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
-)
-
-load("@rules_jvm_external//:defs.bzl", "maven_install")
-
-maven_install(
-    artifacts = DAGGER_ARTIFACTS + HILT_ANDROID_ARTIFACTS + [
-        "androidx.test.ext:junit:1.1.1",
-        "androidx.test:runner:1.1.1",
-        "com.google.truth:truth:1.0.1",
-        "junit:junit:4.13",
-        "org.robolectric:robolectric:4.1",
-        "org.robolectric:annotations:4.1",
-    ],
-    repositories = DAGGER_REPOSITORIES + HILT_ANDROID_REPOSITORIES,
-)
diff --git a/examples/bazel/java/example/common/BUILD b/examples/bazel/java/example/common/BUILD
deleted file mode 100644
index 4de78ae..0000000
--- a/examples/bazel/java/example/common/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2020 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.
-
-java_library(
-    name = "common",
-    srcs = glob(["*.java"]),
-    visibility = [
-        "//java/example:__subpackages__",
-        "//javatests/example:__subpackages__",
-    ],
-    deps = [
-        "//:dagger",
-    ],
-)
diff --git a/examples/bazel/java/example/common/CoffeeLogger.java b/examples/bazel/java/example/common/CoffeeLogger.java
deleted file mode 100644
index 10c1849..0000000
--- a/examples/bazel/java/example/common/CoffeeLogger.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.common;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** A logger to logs steps while brewing coffee. */
-@Singleton
-public final class CoffeeLogger {
-  private final List<String> logs = new ArrayList<>();
-
-  @Inject
-  CoffeeLogger() {}
-
-  public void log(String msg) {
-    logs.add(msg);
-  }
-
-  public List<String> logs() {
-    return new ArrayList<>(logs);
-  }
-}
diff --git a/examples/bazel/java/example/common/CoffeeMaker.java b/examples/bazel/java/example/common/CoffeeMaker.java
deleted file mode 100644
index 796638d..0000000
--- a/examples/bazel/java/example/common/CoffeeMaker.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.common;
-
-import dagger.Lazy;
-import javax.inject.Inject;
-
-/** A coffee maker to brew the coffee. */
-public class CoffeeMaker {
-  private final CoffeeLogger logger;
-  private final Lazy<Heater> heater; // Create a possibly costly heater only when we use it.
-  private final Pump pump;
-
-  @Inject
-  CoffeeMaker(CoffeeLogger logger, Lazy<Heater> heater, Pump pump) {
-    this.logger = logger;
-    this.heater = heater;
-    this.pump = pump;
-  }
-
-  public void brew() {
-    heater.get().on();
-    pump.pump();
-    logger.log(" [_]P coffee! [_]P ");
-    heater.get().off();
-  }
-}
diff --git a/examples/bazel/java/example/common/ElectricHeater.java b/examples/bazel/java/example/common/ElectricHeater.java
deleted file mode 100644
index 981a41a..0000000
--- a/examples/bazel/java/example/common/ElectricHeater.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.common;
-
-import javax.inject.Inject;
-
-/** An electric heater to heat the coffee. */
-public class ElectricHeater implements Heater {
-
-  private final CoffeeLogger logger;
-  private boolean heating;
-
-  @Inject
-  ElectricHeater(CoffeeLogger logger) {
-    this.logger = logger;
-  }
-
-  @Override
-  public void on() {
-    this.heating = true;
-    logger.log("~ ~ ~ heating ~ ~ ~");
-  }
-
-  @Override
-  public void off() {
-    this.heating = false;
-  }
-
-  @Override
-  public boolean isHot() {
-    return heating;
-  }
-}
diff --git a/examples/bazel/java/example/common/Heater.java b/examples/bazel/java/example/common/Heater.java
deleted file mode 100644
index 9f9df50..0000000
--- a/examples/bazel/java/example/common/Heater.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.common;
-
-/** A heater to heat the coffee. */
-public interface Heater {
-  void on();
-  void off();
-  boolean isHot();
-}
diff --git a/examples/bazel/java/example/common/Pump.java b/examples/bazel/java/example/common/Pump.java
deleted file mode 100644
index 4a627cf..0000000
--- a/examples/bazel/java/example/common/Pump.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.common;
-
-/** A pump to pump the coffee. */
-public interface Pump {
-  void pump();
-}
diff --git a/examples/bazel/java/example/common/Thermosiphon.java b/examples/bazel/java/example/common/Thermosiphon.java
deleted file mode 100644
index 6509c80..0000000
--- a/examples/bazel/java/example/common/Thermosiphon.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.common;
-
-import javax.inject.Inject;
-
-/** A thermosiphon to pump the coffee. */
-public class Thermosiphon implements Pump {
-  private final CoffeeLogger logger;
-  private final Heater heater;
-
-  @Inject
-  Thermosiphon(CoffeeLogger logger, Heater heater) {
-    this.logger = logger;
-    this.heater = heater;
-  }
-
-  @Override
-  public void pump() {
-    if (heater.isHot()) {
-      logger.log("=> => pumping => =>");
-    }
-  }
-}
diff --git a/examples/bazel/java/example/dagger/BUILD b/examples/bazel/java/example/dagger/BUILD
deleted file mode 100644
index 7af63b9..0000000
--- a/examples/bazel/java/example/dagger/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) 2020 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.
-
-java_binary(
-    name = "dagger",
-    srcs = glob(["*.java"]),
-    main_class = "dagger.coffee.CoffeeApp",
-    deps = [
-        "//:dagger",
-        "//java/example/common",
-    ],
-)
diff --git a/examples/bazel/java/example/dagger/CoffeeApp.java b/examples/bazel/java/example/dagger/CoffeeApp.java
deleted file mode 100644
index 624fdf7..0000000
--- a/examples/bazel/java/example/dagger/CoffeeApp.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import dagger.Component;
-import example.common.CoffeeLogger;
-import example.common.CoffeeMaker;
-import javax.inject.Singleton;
-
-/** The main app responsible for brewing the coffee and printing the logs. */
-public class CoffeeApp {
-  @Singleton
-  @Component(
-      modules = {
-        HeaterModule.class,
-        PumpModule.class
-      }
-  )
-  public interface CoffeeShop {
-    CoffeeMaker maker();
-    CoffeeLogger logger();
-  }
-
-  public static void main(String[] args) {
-    CoffeeShop coffeeShop = DaggerCoffeeApp_CoffeeShop.builder().build();
-    coffeeShop.maker().brew();
-    coffeeShop.logger().logs().forEach(log -> System.out.println(log));
-  }
-}
diff --git a/examples/bazel/java/example/dagger/HeaterModule.java b/examples/bazel/java/example/dagger/HeaterModule.java
deleted file mode 100644
index 0709222..0000000
--- a/examples/bazel/java/example/dagger/HeaterModule.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import dagger.Binds;
-import dagger.Module;
-import example.common.ElectricHeater;
-import example.common.Heater;
-import javax.inject.Singleton;
-
-@Module
-interface HeaterModule {
-  @Binds
-  @Singleton
-  Heater bindHeater(ElectricHeater impl);
-}
diff --git a/examples/bazel/java/example/dagger/PumpModule.java b/examples/bazel/java/example/dagger/PumpModule.java
deleted file mode 100644
index 3af7052..0000000
--- a/examples/bazel/java/example/dagger/PumpModule.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import dagger.Binds;
-import dagger.Module;
-import example.common.Pump;
-import example.common.Thermosiphon;
-
-@Module
-abstract class PumpModule {
-  @Binds
-  abstract Pump providePump(Thermosiphon pump);
-}
diff --git a/examples/bazel/java/example/hilt/AndroidManifest.xml b/examples/bazel/java/example/hilt/AndroidManifest.xml
deleted file mode 100644
index a786737..0000000
--- a/examples/bazel/java/example/hilt/AndroidManifest.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="example.hilt">
-
-  <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="28"/>
-
-  <application android:name=".CoffeeApp">
-  </application>
-</manifest>
diff --git a/examples/bazel/java/example/hilt/BUILD b/examples/bazel/java/example/hilt/BUILD
deleted file mode 100644
index e890401..0000000
--- a/examples/bazel/java/example/hilt/BUILD
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (C) 2020 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.
-
-android_binary(
-    name = "hilt",
-    srcs = ["CoffeeApp.java"],
-    manifest = "AndroidManifest.xml",
-    resource_files = glob(["res/**"]),
-    deps = [
-        ":heater_module",
-        ":pump_module",
-        "//:hilt-android",
-        "//java/example/common",
-    ],
-)
-
-android_library(
-    name = "heater_module",
-    srcs = ["HeaterModule.java"],
-    manifest = "AndroidManifest.xml",
-    visibility = ["//javatests/example/hilt:__pkg__"],
-    deps = [
-        "//:hilt-android",
-        "//java/example/common",
-    ],
-)
-
-android_library(
-    name = "pump_module",
-    srcs = ["PumpModule.java"],
-    manifest = "AndroidManifest.xml",
-    visibility = ["//javatests/example/hilt:__pkg__"],
-    deps = [
-        "//:hilt-android",
-        "//java/example/common",
-    ],
-)
diff --git a/examples/bazel/java/example/hilt/CoffeeApp.java b/examples/bazel/java/example/hilt/CoffeeApp.java
deleted file mode 100644
index 0ff7212..0000000
--- a/examples/bazel/java/example/hilt/CoffeeApp.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.hilt;
-
-import android.app.Application;
-import dagger.hilt.android.HiltAndroidApp;
-import example.common.CoffeeLogger;
-import example.common.CoffeeMaker;
-import javax.inject.Inject;
-
-/** The main app responsible for brewing the coffee and printing the logs. */
-@HiltAndroidApp(Application.class)
-public class CoffeeApp extends Hilt_CoffeeApp {
-
-  @Inject CoffeeMaker maker;
-  @Inject CoffeeLogger logger;
-
-  @Override
-  public void onCreate() {
-    super.onCreate();
-    maker.brew();
-    logger.logs().forEach(log -> System.out.println(log));
-  }
-}
diff --git a/examples/bazel/java/example/hilt/HeaterModule.java b/examples/bazel/java/example/hilt/HeaterModule.java
deleted file mode 100644
index 122bec0..0000000
--- a/examples/bazel/java/example/hilt/HeaterModule.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.hilt;
-
-import dagger.Binds;
-import dagger.Module;
-import dagger.hilt.InstallIn;
-import dagger.hilt.components.SingletonComponent;
-import example.common.ElectricHeater;
-import example.common.Heater;
-import javax.inject.Singleton;
-
-@Module
-@InstallIn(SingletonComponent.class)
-interface HeaterModule {
-  @Binds
-  @Singleton
-  Heater bindHeater(ElectricHeater impl);
-}
diff --git a/examples/bazel/java/example/hilt/PumpModule.java b/examples/bazel/java/example/hilt/PumpModule.java
deleted file mode 100644
index 0ad3903..0000000
--- a/examples/bazel/java/example/hilt/PumpModule.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.hilt;
-
-import dagger.Binds;
-import dagger.Module;
-import dagger.hilt.InstallIn;
-import dagger.hilt.components.SingletonComponent;
-import example.common.Pump;
-import example.common.Thermosiphon;
-
-@Module
-@InstallIn(SingletonComponent.class)
-abstract class PumpModule {
-  @Binds
-  abstract Pump providePump(Thermosiphon pump);
-}
diff --git a/examples/bazel/javatests/example/hilt/BUILD b/examples/bazel/javatests/example/hilt/BUILD
deleted file mode 100644
index 9982fbd..0000000
--- a/examples/bazel/javatests/example/hilt/BUILD
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (C) 2020 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.
-
-android_local_test(
-    name = "CoffeeAppFakePumpTest",
-    srcs = [
-        "CoffeeAppFakePumpTest.java",
-    ],
-    manifest_values = {
-        "minSdkVersion": "15",
-    },
-    deps = [
-        "//:hilt-android-testing",
-        "//java/example/common",
-        "//java/example/hilt:heater_module",
-        "@maven//:androidx_test_ext_junit",
-        "@maven//:androidx_test_runner",
-        "@maven//:com_google_truth_truth",
-        "@maven//:org_robolectric_annotations",
-        "@maven//:org_robolectric_robolectric",
-        "@robolectric//bazel:android-all",
-    ],
-)
-
-android_local_test(
-    name = "CoffeeAppFakeHeaterTest",
-    srcs = [
-        "CoffeeAppFakeHeaterTest.java",
-    ],
-    manifest_values = {
-        "minSdkVersion": "15",
-    },
-    deps = [
-        "//:hilt-android-testing",
-        "//java/example/common",
-        "//java/example/hilt:pump_module",
-        "@maven//:androidx_test_ext_junit",
-        "@maven//:androidx_test_runner",
-        "@maven//:com_google_truth_truth",
-        "@maven//:org_robolectric_annotations",
-        "@maven//:org_robolectric_robolectric",
-        "@robolectric//bazel:android-all",
-    ],
-)
diff --git a/examples/bazel/javatests/example/hilt/CoffeeAppFakeHeaterTest.java b/examples/bazel/javatests/example/hilt/CoffeeAppFakeHeaterTest.java
deleted file mode 100644
index 5f4e162..0000000
--- a/examples/bazel/javatests/example/hilt/CoffeeAppFakeHeaterTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.hilt;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.Build;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.android.testing.HiltTestApplication;
-import example.common.CoffeeLogger;
-import example.common.CoffeeMaker;
-import example.common.Heater;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-/** Tests using a fake heater. */
-@HiltAndroidTest
-@Config(sdk = {Build.VERSION_CODES.P}, application = HiltTestApplication.class)
-@RunWith(AndroidJUnit4.class)
-public final class CoffeeAppFakeHeaterTest {
-  public @Rule HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  final class FakeHeater implements Heater {
-    private boolean heating;
-
-    @Override
-    public void on() {
-      this.heating = true;
-      logger.log("~ ~ ~ fake heating ~ ~ ~");
-    }
-
-    @Override
-    public void off() {
-      this.heating = false;
-    }
-
-    @Override
-    public boolean isHot() {
-      return heating;
-    }
-  }
-
-  @Inject CoffeeMaker maker;
-  @Inject CoffeeLogger logger;
-
-  @BindValue Heater fakeHeater = new FakeHeater();
-
-  @Test
-  public void testApplicationClass() throws Exception {
-    assertThat((Context) ApplicationProvider.getApplicationContext())
-        .isInstanceOf(HiltTestApplication.class);
-  }
-
-  @Test
-  public void testLogs() throws Exception {
-    rule.inject();
-    assertThat(logger.logs()).isEmpty();
-    maker.brew();
-    assertThat(logger.logs())
-        .containsExactly(
-            "~ ~ ~ fake heating ~ ~ ~",
-            "=> => pumping => =>",
-            " [_]P coffee! [_]P ")
-        .inOrder();
-  }
-}
diff --git a/examples/bazel/javatests/example/hilt/CoffeeAppFakePumpTest.java b/examples/bazel/javatests/example/hilt/CoffeeAppFakePumpTest.java
deleted file mode 100644
index 6d89270..0000000
--- a/examples/bazel/javatests/example/hilt/CoffeeAppFakePumpTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.hilt;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.Build;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.android.testing.HiltTestApplication;
-import example.common.CoffeeLogger;
-import example.common.CoffeeMaker;
-import example.common.Pump;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-/** Tests using a fake pump. */
-@HiltAndroidTest
-@Config(sdk = {Build.VERSION_CODES.P}, application = HiltTestApplication.class)
-@RunWith(AndroidJUnit4.class)
-public final class CoffeeAppFakePumpTest {
-  public @Rule HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @Inject CoffeeMaker maker;
-  @Inject CoffeeLogger logger;
-
-  @BindValue Pump fakePump = () -> logger.log("=> => fake pumping => =>");
-
-  @Test
-  public void testApplicationClass() throws Exception {
-    assertThat((Context) ApplicationProvider.getApplicationContext())
-        .isInstanceOf(HiltTestApplication.class);
-  }
-
-  @Test
-  public void testLogs() throws Exception {
-    rule.inject();
-    assertThat(logger.logs()).isEmpty();
-    maker.brew();
-    assertThat(logger.logs())
-        .containsExactly(
-            "~ ~ ~ heating ~ ~ ~",
-            "=> => fake pumping => =>",
-            " [_]P coffee! [_]P ")
-        .inOrder();
-  }
-}
diff --git a/examples/maven/coffee/pom.xml b/examples/maven/coffee/pom.xml
deleted file mode 100644
index a196d99..0000000
--- a/examples/maven/coffee/pom.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>com.google.dagger.examples</groupId>
-    <artifactId>parent</artifactId>
-    <version>LOCAL-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>coffee</artifactId>
-  <name>Examples: Coffee</name>
-
-  <dependencies>
-    <dependency>
-      <!-- Force the correct version of Guava to be on the classpath. -->
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.google.dagger</groupId>
-      <artifactId>dagger</artifactId>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.6.1</version>
-        <configuration>
-          <annotationProcessorPaths>
-            <path>
-              <groupId>com.google.dagger</groupId>
-              <artifactId>dagger-compiler</artifactId>
-              <version>${project.version}</version>
-            </path>
-          </annotationProcessorPaths>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/examples/maven/coffee/src/main/java/example/dagger/CoffeeApp.java b/examples/maven/coffee/src/main/java/example/dagger/CoffeeApp.java
deleted file mode 100644
index 723ab91..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/CoffeeApp.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import dagger.Component;
-import javax.inject.Singleton;
-
-/** The main app responsible for brewing the coffee and printing the logs. */
-public class CoffeeApp {
-  @Singleton
-  @Component(
-      modules = {
-        HeaterModule.class,
-        PumpModule.class
-      }
-  )
-  public interface CoffeeShop {
-    CoffeeMaker maker();
-    CoffeeLogger logger();
-  }
-
-  public static void main(String[] args) {
-    CoffeeShop coffeeShop = DaggerCoffeeApp_CoffeeShop.builder().build();
-    coffeeShop.maker().brew();
-    coffeeShop.logger().logs().forEach(log -> System.out.println(log));
-  }
-}
diff --git a/examples/maven/coffee/src/main/java/example/dagger/CoffeeLogger.java b/examples/maven/coffee/src/main/java/example/dagger/CoffeeLogger.java
deleted file mode 100644
index 16d2bdb..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/CoffeeLogger.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** A logger to logs steps while brewing coffee. */
-@Singleton
-public final class CoffeeLogger {
-  private final List<String> logs = new ArrayList<>();
-
-  @Inject
-  CoffeeLogger() {}
-
-  public void log(String msg) {
-    logs.add(msg);
-  }
-
-  public List<String> logs() {
-    return new ArrayList<>(logs);
-  }
-}
diff --git a/examples/maven/coffee/src/main/java/example/dagger/CoffeeMaker.java b/examples/maven/coffee/src/main/java/example/dagger/CoffeeMaker.java
deleted file mode 100644
index 20c1f27..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/CoffeeMaker.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import dagger.Lazy;
-import javax.inject.Inject;
-
-/** A coffee maker to brew the coffee. */
-public class CoffeeMaker {
-  private final CoffeeLogger logger;
-  private final Lazy<Heater> heater; // Create a possibly costly heater only when we use it.
-  private final Pump pump;
-
-  @Inject
-  CoffeeMaker(CoffeeLogger logger, Lazy<Heater> heater, Pump pump) {
-    this.logger = logger;
-    this.heater = heater;
-    this.pump = pump;
-  }
-
-  public void brew() {
-    heater.get().on();
-    pump.pump();
-    logger.log(" [_]P coffee! [_]P ");
-    heater.get().off();
-  }
-}
diff --git a/examples/maven/coffee/src/main/java/example/dagger/ElectricHeater.java b/examples/maven/coffee/src/main/java/example/dagger/ElectricHeater.java
deleted file mode 100644
index 567c7aa..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/ElectricHeater.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import javax.inject.Inject;
-
-/** An electric heater to heat the coffee. */
-public class ElectricHeater implements Heater {
-
-  private final CoffeeLogger logger;
-  private boolean heating;
-
-  @Inject
-  ElectricHeater(CoffeeLogger logger) {
-    this.logger = logger;
-  }
-
-  @Override
-  public void on() {
-    this.heating = true;
-    logger.log("~ ~ ~ heating ~ ~ ~");
-  }
-
-  @Override
-  public void off() {
-    this.heating = false;
-  }
-
-  @Override
-  public boolean isHot() {
-    return heating;
-  }
-}
diff --git a/examples/maven/coffee/src/main/java/example/dagger/Heater.java b/examples/maven/coffee/src/main/java/example/dagger/Heater.java
deleted file mode 100644
index 3d6d1f2..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/Heater.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-/** A heater to heat the coffee. */
-public interface Heater {
-  void on();
-  void off();
-  boolean isHot();
-}
diff --git a/examples/maven/coffee/src/main/java/example/dagger/HeaterModule.java b/examples/maven/coffee/src/main/java/example/dagger/HeaterModule.java
deleted file mode 100644
index fb8c969..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/HeaterModule.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import dagger.Binds;
-import dagger.Module;
-import javax.inject.Singleton;
-
-@Module
-interface HeaterModule {
-  @Binds
-  @Singleton
-  Heater bindHeater(ElectricHeater impl);
-}
diff --git a/examples/maven/coffee/src/main/java/example/dagger/Pump.java b/examples/maven/coffee/src/main/java/example/dagger/Pump.java
deleted file mode 100644
index 712b21c..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/Pump.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-/** A pump to pump the coffee. */
-public interface Pump {
-  void pump();
-}
diff --git a/examples/maven/coffee/src/main/java/example/dagger/PumpModule.java b/examples/maven/coffee/src/main/java/example/dagger/PumpModule.java
deleted file mode 100644
index 202fed3..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/PumpModule.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import dagger.Binds;
-import dagger.Module;
-
-@Module
-abstract class PumpModule {
-  @Binds
-  abstract Pump providePump(Thermosiphon pump);
-}
diff --git a/examples/maven/coffee/src/main/java/example/dagger/Thermosiphon.java b/examples/maven/coffee/src/main/java/example/dagger/Thermosiphon.java
deleted file mode 100644
index d94c33f..0000000
--- a/examples/maven/coffee/src/main/java/example/dagger/Thermosiphon.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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 example.dagger;
-
-import javax.inject.Inject;
-
-/** A thermosiphon to pump the coffee. */
-public class Thermosiphon implements Pump {
-  private final CoffeeLogger logger;
-  private final Heater heater;
-
-  @Inject
-  Thermosiphon(CoffeeLogger logger, Heater heater) {
-    this.logger = logger;
-    this.heater = heater;
-  }
-
-  @Override
-  public void pump() {
-    if (heater.isHot()) {
-      logger.log("=> => pumping => =>");
-    }
-  }
-}
diff --git a/examples/maven/pom.xml b/examples/maven/pom.xml
deleted file mode 100644
index be21b96..0000000
--- a/examples/maven/pom.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Copyright (C) 2013 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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.sonatype.oss</groupId>
-    <artifactId>oss-parent</artifactId>
-    <version>9</version>
-  </parent>
-
-  <groupId>com.google.dagger.examples</groupId>
-  <artifactId>parent</artifactId>
-  <packaging>pom</packaging>
-  <name>Examples</name>
-  <version>LOCAL-SNAPSHOT</version>
-
-  <modules>
-    <module>coffee</module>
-  </modules>
-
-  <!-- Example-only dependencies. -->
-  <dependencyManagement>
-    <dependencies>
-      <dependency>
-        <groupId>com.google.dagger</groupId>
-        <artifactId>dagger</artifactId>
-        <version>${project.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>com.google.dagger</groupId>
-        <artifactId>dagger-compiler</artifactId>
-        <version>${project.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>com.google.guava</groupId>
-        <artifactId>guava</artifactId>
-        <version>26.0-jre</version>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
-
-  <build>
-    <pluginManagement>
-      <plugins>
-       <plugin>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <configuration>
-            <source>1.8</source>
-            <target>1.8</target>
-          </configuration>
-        </plugin>
-      </plugins>
-    </pluginManagement>
-  </build>
-</project>
diff --git a/examples/pom.xml b/examples/pom.xml
new file mode 100644
index 0000000..c12050d
--- /dev/null
+++ b/examples/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (C) 2013 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.sonatype.oss</groupId>
+    <artifactId>oss-parent</artifactId>
+    <version>9</version>
+  </parent>
+
+  <groupId>com.google.dagger.example</groupId>
+  <artifactId>dagger-example-parent</artifactId>
+  <packaging>pom</packaging>
+  <name>Examples</name>
+  <version>2.17</version>
+
+  <modules>
+    <module>simple</module>
+  </modules>
+
+  <!-- Example-only dependencies. -->
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>com.google.dagger</groupId>
+        <artifactId>dagger</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.dagger</groupId>
+        <artifactId>dagger-compiler</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.guava</groupId>
+        <artifactId>guava</artifactId>
+        <version>26.0-jre</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+       <plugin>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <configuration>
+            <source>1.6</source>
+            <target>1.6</target>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/examples/simple/pom.xml b/examples/simple/pom.xml
new file mode 100644
index 0000000..ffc99dc
--- /dev/null
+++ b/examples/simple/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (C) 2012 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.dagger.example</groupId>
+    <artifactId>dagger-example-parent</artifactId>
+    <version>2.17</version>
+  </parent>
+
+  <artifactId>simple</artifactId>
+  <name>Examples: Simple</name>
+
+  <dependencies>
+    <dependency>
+      <!-- Force the correct version of Guava to be on the classpath. -->
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.dagger</groupId>
+      <artifactId>dagger</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.6.1</version>
+        <configuration>
+          <annotationProcessorPaths>
+            <path>
+              <groupId>com.google.dagger</groupId>
+              <artifactId>dagger-compiler</artifactId>
+              <version>${project.version}</version>
+            </path>
+          </annotationProcessorPaths>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/examples/simple/src/main/java/coffee/CoffeeApp.java b/examples/simple/src/main/java/coffee/CoffeeApp.java
new file mode 100644
index 0000000..7a2b9a6
--- /dev/null
+++ b/examples/simple/src/main/java/coffee/CoffeeApp.java
@@ -0,0 +1,17 @@
+package coffee;
+
+import dagger.Component;
+import javax.inject.Singleton;
+
+public class CoffeeApp {
+  @Singleton
+  @Component(modules = { DripCoffeeModule.class })
+  public interface CoffeeShop {
+    CoffeeMaker maker();
+  }
+
+  public static void main(String[] args) {
+    CoffeeShop coffeeShop = DaggerCoffeeApp_CoffeeShop.builder().build();
+    coffeeShop.maker().brew();
+  }
+}
diff --git a/examples/simple/src/main/java/coffee/CoffeeMaker.java b/examples/simple/src/main/java/coffee/CoffeeMaker.java
new file mode 100644
index 0000000..6410336
--- /dev/null
+++ b/examples/simple/src/main/java/coffee/CoffeeMaker.java
@@ -0,0 +1,21 @@
+package coffee;
+
+import dagger.Lazy;
+import javax.inject.Inject;
+
+class CoffeeMaker {
+  private final Lazy<Heater> heater; // Create a possibly costly heater only when we use it.
+  private final Pump pump;
+
+  @Inject CoffeeMaker(Lazy<Heater> heater, Pump pump) {
+    this.heater = heater;
+    this.pump = pump;
+  }
+
+  public void brew() {
+    heater.get().on();
+    pump.pump();
+    System.out.println(" [_]P coffee! [_]P ");
+    heater.get().off();
+  }
+}
diff --git a/examples/simple/src/main/java/coffee/DripCoffeeModule.java b/examples/simple/src/main/java/coffee/DripCoffeeModule.java
new file mode 100644
index 0000000..e50d249
--- /dev/null
+++ b/examples/simple/src/main/java/coffee/DripCoffeeModule.java
@@ -0,0 +1,12 @@
+package coffee;
+
+import dagger.Module;
+import dagger.Provides;
+import javax.inject.Singleton;
+
+@Module(includes = PumpModule.class)
+class DripCoffeeModule {
+  @Provides @Singleton Heater provideHeater() {
+    return new ElectricHeater();
+  }
+}
diff --git a/examples/simple/src/main/java/coffee/ElectricHeater.java b/examples/simple/src/main/java/coffee/ElectricHeater.java
new file mode 100644
index 0000000..fbab399
--- /dev/null
+++ b/examples/simple/src/main/java/coffee/ElectricHeater.java
@@ -0,0 +1,18 @@
+package coffee;
+
+class ElectricHeater implements Heater {
+  boolean heating;
+
+  @Override public void on() {
+    System.out.println("~ ~ ~ heating ~ ~ ~");
+    this.heating = true;
+  }
+
+  @Override public void off() {
+    this.heating = false;
+  }
+
+  @Override public boolean isHot() {
+    return heating;
+  }
+}
diff --git a/examples/simple/src/main/java/coffee/Heater.java b/examples/simple/src/main/java/coffee/Heater.java
new file mode 100644
index 0000000..b5ddb6b
--- /dev/null
+++ b/examples/simple/src/main/java/coffee/Heater.java
@@ -0,0 +1,7 @@
+package coffee;
+
+interface Heater {
+  void on();
+  void off();
+  boolean isHot();
+}
diff --git a/examples/simple/src/main/java/coffee/Pump.java b/examples/simple/src/main/java/coffee/Pump.java
new file mode 100644
index 0000000..e394349
--- /dev/null
+++ b/examples/simple/src/main/java/coffee/Pump.java
@@ -0,0 +1,5 @@
+package coffee;
+
+interface Pump {
+  void pump();
+}
diff --git a/examples/simple/src/main/java/coffee/PumpModule.java b/examples/simple/src/main/java/coffee/PumpModule.java
new file mode 100644
index 0000000..df00b86
--- /dev/null
+++ b/examples/simple/src/main/java/coffee/PumpModule.java
@@ -0,0 +1,10 @@
+package coffee;
+
+import dagger.Binds;
+import dagger.Module;
+
+@Module
+abstract class PumpModule {
+  @Binds
+  abstract Pump providePump(Thermosiphon pump);
+}
diff --git a/examples/simple/src/main/java/coffee/Thermosiphon.java b/examples/simple/src/main/java/coffee/Thermosiphon.java
new file mode 100644
index 0000000..c9f9828
--- /dev/null
+++ b/examples/simple/src/main/java/coffee/Thermosiphon.java
@@ -0,0 +1,18 @@
+package coffee;
+
+import javax.inject.Inject;
+
+class Thermosiphon implements Pump {
+  private final Heater heater;
+
+  @Inject
+  Thermosiphon(Heater heater) {
+    this.heater = heater;
+  }
+
+  @Override public void pump() {
+    if (heater.isHot()) {
+      System.out.println("=> => pumping => =>");
+    }
+  }
+}
diff --git a/gwt/BUILD b/gwt/BUILD
index 5aa9110..da73013 100644
--- a/gwt/BUILD
+++ b/gwt/BUILD
@@ -15,12 +15,10 @@
 # Description:
 #   GWT-specific files for Dagger
 
-load("@rules_java//java:defs.bzl", "java_library")
-load("//tools:maven.bzl", "pom_file")
-load("//:build_defs.bzl", "POM_VERSION")
-
 package(default_visibility = ["//:src"])
 
+load("//tools:maven.bzl", "pom_file", "POM_VERSION")
+
 java_library(
     name = "gwt",
     resource_strip_prefix = "gwt/",
diff --git a/java/dagger/BUILD b/java/dagger/BUILD
index aaebade..3485431 100644
--- a/java/dagger/BUILD
+++ b/java/dagger/BUILD
@@ -15,17 +15,14 @@
 # Description:
 #   A JSR-330 compliant dependency injection system for android and java
 
-load("@rules_java//java:defs.bzl", "java_library")
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
-    "POM_VERSION",
     "SOURCE_7_TARGET_7",
 )
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-
-package(default_visibility = ["//:src"])
+load("//tools:maven.bzl", "POM_VERSION", "pom_file")
 
 java_library(
     name = "core",
@@ -50,6 +47,8 @@
     srcs = glob(["**/*"]),
 )
 
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+
 javadoc_library(
     name = "core-javadoc",
     srcs = [":javadoc-srcs"],
diff --git a/java/dagger/Provides.java b/java/dagger/Provides.java
index 5d7827b..a60be3b 100644
--- a/java/dagger/Provides.java
+++ b/java/dagger/Provides.java
@@ -30,11 +30,11 @@
  *
  * <h3>Nullability</h3>
  *
- * <p>Dagger forbids injecting {@code null} by default. Component implementations that invoke
+ * <p>Dagger forbids injecting {@code null} by default. Component implemenations that invoke
  * {@code @Provides} methods that return {@code null} will throw a {@link NullPointerException}
  * immediately thereafter. {@code @Provides} methods may opt into allowing {@code null} by
  * annotating the method with any {@code @Nullable} annotation like
- * {@code javax.annotation.Nullable} or {@code androidx.annotation.Nullable}.
+ * {@code javax.annotation.Nullable} or {@code android.support.annotation.Nullable}.
  *
  * <p>If a {@code @Provides} method is marked {@code @Nullable}, Dagger will <em>only</em>
  * allow injection into sites that are marked {@code @Nullable} as well. A component that
diff --git a/java/dagger/android/AndroidInjection.java b/java/dagger/android/AndroidInjection.java
index f3296c6..2f4fb4c 100644
--- a/java/dagger/android/AndroidInjection.java
+++ b/java/dagger/android/AndroidInjection.java
@@ -1,4 +1,4 @@
-/*
+  /*
  * Copyright (C) 2017 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -39,71 +39,99 @@
    * otherwise throws an {@link IllegalArgumentException}.
    *
    * @throws RuntimeException if the {@link Application} doesn't implement {@link
-   *     HasAndroidInjector}.
+   *     HasAndroidInjector} or {@link HasActivityInjector}.
    */
   public static void inject(Activity activity) {
     checkNotNull(activity, "activity");
     Application application = activity.getApplication();
-    if (!(application instanceof HasAndroidInjector)) {
+    AndroidInjector<? super Activity> injector;
+    if (application instanceof HasAndroidInjector) {
+      injector = ((HasAndroidInjector) application).androidInjector();
+      checkNotNull(injector, "%s.androidInjector() returned null", application.getClass());
+    } else if (application instanceof HasActivityInjector) {
+      injector = ((HasActivityInjector) application).activityInjector();
+      checkNotNull(injector, "%s.activityInjector() returned null", application.getClass());
+    } else {
       throw new RuntimeException(
           String.format(
-              "%s does not implement %s",
+              "%s does not implement %s or %s",
               application.getClass().getCanonicalName(),
-              HasAndroidInjector.class.getCanonicalName()));
+              HasAndroidInjector.class.getCanonicalName(),
+              HasActivityInjector.class.getCanonicalName()));
     }
 
-    inject(activity, (HasAndroidInjector) application);
+    injector.inject(activity);
   }
 
   /**
    * Injects {@code fragment} if an associated {@link AndroidInjector} implementation can be found,
    * otherwise throws an {@link IllegalArgumentException}.
    *
-   * <p>Uses the following algorithm to find the appropriate {@code AndroidInjector<Fragment>} to
-   * use to inject {@code fragment}:
+   * <p>Uses the following algorithm to find the appropriate {@link AndroidInjector} to use to
+   * inject {@code fragment}:
    *
    * <ol>
-   *   <li>Walks the parent-fragment hierarchy to find the a fragment that implements {@link
-   *       HasAndroidInjector}, and if none do
+   *   <li>Walks the parent-fragment hierarchy to find a fragment that implements {@link
+   *       HasAndroidInjector} or {@link HasFragmentInjector}, and if none do
    *   <li>Uses the {@code fragment}'s {@link Fragment#getActivity() activity} if it implements
-   *       {@link HasAndroidInjector}, and if not
-   *   <li>Uses the {@link android.app.Application} if it implements {@link HasAndroidInjector}.
+   *       {@link HasAndroidInjector} or {@link HasFragmentInjector}, and if not
+   *   <li>Uses the {@link android.app.Application} if it implements {@link HasAndroidInjector}
+   *       {@link HasFragmentInjector}.
    * </ol>
    *
-   * If none of them implement {@link HasAndroidInjector}, a {@link IllegalArgumentException} is
-   * thrown.
+   * If none of them implement {@link HasAndroidInjector} or {@link HasFragmentInjector}, a {@link
+   * IllegalArgumentException} is thrown.
    *
    * @throws IllegalArgumentException if no parent fragment, activity, or application implements
-   *     {@link HasAndroidInjector}.
+   *     {@link HasAndroidInjector} or {@link HasFragmentInjector}.
    */
   public static void inject(Fragment fragment) {
     checkNotNull(fragment, "fragment");
-    HasAndroidInjector hasAndroidInjector = findHasAndroidInjectorForFragment(fragment);
+
+    Object hasInjector = findHasFragmentInjector(fragment);
+    AndroidInjector<? super Fragment> injector;
+    if (hasInjector instanceof HasAndroidInjector) {
+      injector = ((HasAndroidInjector) hasInjector).androidInjector();
+      checkNotNull(injector, "%s.androidInjector() returned null", hasInjector.getClass());
+    } else if (hasInjector instanceof HasFragmentInjector) {
+      injector = ((HasFragmentInjector) hasInjector).fragmentInjector();
+      checkNotNull(injector, "%s.fragmentInjector() returned null", hasInjector.getClass());
+    } else {
+      throw new RuntimeException(
+          String.format(
+              "%s does not implement %s or %s",
+              hasInjector.getClass().getCanonicalName(),
+              HasAndroidInjector.class.getCanonicalName(),
+              HasFragmentInjector.class.getCanonicalName()));
+    }
+
     if (Log.isLoggable(TAG, DEBUG)) {
       Log.d(
           TAG,
           String.format(
               "An injector for %s was found in %s",
               fragment.getClass().getCanonicalName(),
-              hasAndroidInjector.getClass().getCanonicalName()));
+              hasInjector.getClass().getCanonicalName()));
     }
 
-    inject(fragment, hasAndroidInjector);
+    injector.inject(fragment);
   }
 
-  private static HasAndroidInjector findHasAndroidInjectorForFragment(Fragment fragment) {
+  private static Object findHasFragmentInjector(Fragment fragment) {
     Fragment parentFragment = fragment;
     while ((parentFragment = parentFragment.getParentFragment()) != null) {
-      if (parentFragment instanceof HasAndroidInjector) {
-        return (HasAndroidInjector) parentFragment;
+      if (parentFragment instanceof HasAndroidInjector
+          || parentFragment instanceof HasFragmentInjector) {
+        return parentFragment;
       }
     }
     Activity activity = fragment.getActivity();
-    if (activity instanceof HasAndroidInjector) {
-      return (HasAndroidInjector) activity;
+    if (activity instanceof HasAndroidInjector || activity instanceof HasFragmentInjector) {
+      return activity;
     }
-    if (activity.getApplication() instanceof HasAndroidInjector) {
-      return (HasAndroidInjector) activity.getApplication();
+    Application application = activity.getApplication();
+    if (application instanceof HasAndroidInjector || application instanceof HasFragmentInjector) {
+      return application;
     }
     throw new IllegalArgumentException(
         String.format("No injector was found for %s", fragment.getClass().getCanonicalName()));
@@ -114,20 +142,28 @@
    * otherwise throws an {@link IllegalArgumentException}.
    *
    * @throws RuntimeException if the {@link Application} doesn't implement {@link
-   *     HasAndroidInjector}.
+   *     HasAndroidInjector} or {@link HasServiceInjector}.
    */
   public static void inject(Service service) {
     checkNotNull(service, "service");
     Application application = service.getApplication();
-    if (!(application instanceof HasAndroidInjector)) {
+    AndroidInjector<? super Service> injector;
+    if (application instanceof HasAndroidInjector) {
+      injector = ((HasAndroidInjector) application).androidInjector();
+      checkNotNull(injector, "%s.androidInjector() returned null", application.getClass());
+    } else if (application instanceof HasServiceInjector) {
+      injector = ((HasServiceInjector) application).serviceInjector();
+      checkNotNull(injector, "%s.serviceInjector() returned null", application.getClass());
+    } else {
       throw new RuntimeException(
           String.format(
-              "%s does not implement %s",
+              "%s does not implement %s or %s",
               application.getClass().getCanonicalName(),
-              HasAndroidInjector.class.getCanonicalName()));
+              HasAndroidInjector.class.getCanonicalName(),
+              HasServiceInjector.class.getCanonicalName()));
     }
 
-    inject(service, (HasAndroidInjector) application);
+    injector.inject(service);
   }
 
   /**
@@ -135,21 +171,32 @@
    * be found, otherwise throws an {@link IllegalArgumentException}.
    *
    * @throws RuntimeException if the {@link Application} from {@link
-   *     Context#getApplicationContext()} doesn't implement {@link HasAndroidInjector}.
+   *     Context#getApplicationContext()} doesn't implement {@link HasAndroidInjector} or {@link
+   *     HasBroadcastReceiverInjector}.
    */
   public static void inject(BroadcastReceiver broadcastReceiver, Context context) {
     checkNotNull(broadcastReceiver, "broadcastReceiver");
     checkNotNull(context, "context");
+
     Application application = (Application) context.getApplicationContext();
-    if (!(application instanceof HasAndroidInjector)) {
+    AndroidInjector<? super BroadcastReceiver> injector;
+    if (application instanceof HasAndroidInjector) {
+      injector = ((HasAndroidInjector) application).androidInjector();
+      checkNotNull(injector, "%s.androidInjector() returned null", application.getClass());
+    } else if (application instanceof HasBroadcastReceiverInjector) {
+      injector = ((HasBroadcastReceiverInjector) application).broadcastReceiverInjector();
+      checkNotNull(
+          injector, "%s.broadcastReceiverInjector() returned null", application.getClass());
+    } else {
       throw new RuntimeException(
           String.format(
-              "%s does not implement %s",
+              "%s does not implement %s or %s",
               application.getClass().getCanonicalName(),
-              HasAndroidInjector.class.getCanonicalName()));
+              HasAndroidInjector.class.getCanonicalName(),
+              HasBroadcastReceiverInjector.class.getCanonicalName()));
     }
 
-    inject(broadcastReceiver, (HasAndroidInjector) application);
+    injector.inject(broadcastReceiver);
   }
 
   /**
@@ -157,28 +204,29 @@
    * found, otherwise throws an {@link IllegalArgumentException}.
    *
    * @throws RuntimeException if the {@link Application} doesn't implement {@link
-   *     HasAndroidInjector}.
+   *     HasAndroidInjector} or {@link HasContentProviderInjector}.
    */
   public static void inject(ContentProvider contentProvider) {
     checkNotNull(contentProvider, "contentProvider");
     Application application = (Application) contentProvider.getContext().getApplicationContext();
-    if (!(application instanceof HasAndroidInjector)) {
+
+    AndroidInjector<? super ContentProvider> injector;
+    if (application instanceof HasAndroidInjector) {
+      injector = ((HasAndroidInjector) application).androidInjector();
+      checkNotNull(injector, "%s.androidInjector() returned null", application.getClass());
+    } else if (application instanceof HasContentProviderInjector) {
+      injector = ((HasContentProviderInjector) application).contentProviderInjector();
+      checkNotNull(injector, "%s.contentProviderInjector() returned null", application.getClass());
+    } else {
       throw new RuntimeException(
           String.format(
-              "%s does not implement %s",
+              "%s does not implement %s or %s",
               application.getClass().getCanonicalName(),
-              HasAndroidInjector.class.getCanonicalName()));
+              HasAndroidInjector.class.getCanonicalName(),
+              HasBroadcastReceiverInjector.class.getCanonicalName()));
     }
 
-    inject(contentProvider, (HasAndroidInjector) application);
-  }
-
-  private static void inject(Object target, HasAndroidInjector hasAndroidInjector) {
-    AndroidInjector<Object> androidInjector = hasAndroidInjector.androidInjector();
-    checkNotNull(
-        androidInjector, "%s.androidInjector() returned null", hasAndroidInjector.getClass());
-
-    androidInjector.inject(target);
+    injector.inject(contentProvider);
   }
 
   private AndroidInjection() {}
diff --git a/java/dagger/android/AndroidInjectionKey.java b/java/dagger/android/AndroidInjectionKey.java
index ff4a1f6..d4a5d72 100644
--- a/java/dagger/android/AndroidInjectionKey.java
+++ b/java/dagger/android/AndroidInjectionKey.java
@@ -28,7 +28,11 @@
  * #value() value} of the annotation is the canonical name of the class that will be passed to
  * {@link AndroidInjector#inject(Object)}.
  *
- * <p>All key strings will be obfuscated by ProGuard/R8 if the named class is obfuscated.
+ * <p>All key strings will be obfuscated by ProGuard/R8/AppReduce if the named class is obfuscated.
+ *
+ * <p>
+ * You should only use this annotation if you are using a version of ProGuard/R8/AppReduce that
+ * supports the {@code -identifiernamestring} flag.
  */
 @Beta
 @MapKey
diff --git a/java/dagger/android/BUILD b/java/dagger/android/BUILD
index f0cea41..a88d16e 100644
--- a/java/dagger/android/BUILD
+++ b/java/dagger/android/BUILD
@@ -15,18 +15,15 @@
 # Description:
 #   Public Dagger API for Android
 
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
     "DOCLINT_REFERENCES",
-    "POM_VERSION",
     "SOURCE_7_TARGET_7",
 )
-load("//tools:dejetify.bzl", "dejetified_library")
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-
-package(default_visibility = ["//:src"])
+load("//tools:maven.bzl", "POM_VERSION", "pom_file")
 
 # Work around b/70476182 which prevents Kythe from connecting :producers to the .java files it
 # contains.
@@ -45,18 +42,24 @@
     srcs = SRCS,
     javacopts = SOURCE_7_TARGET_7 + DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     manifest = "AndroidManifest.xml",
-    plugins = [
-        "//java/dagger/android/internal/proguard:plugin",
-    ],
+    proguard_specs = ["proguard.cfg"],
     tags = ["maven_coordinates=com.google.dagger:dagger-android:" + POM_VERSION],
-    exports = [
-        "//java/dagger/lint:lint-android-artifact-lib",
-    ],
     deps = [
+        ":manual-maven-deps",
         "//:dagger_with_compiler",
         "@google_bazel_common//third_party/java/auto:value",
         "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@maven//:androidx_annotation_annotation",
+    ],
+)
+
+# Our pom.xml generator does not have a way to add manual maven deps. This target exports the
+# targets that don't have the necessary maven_coordinates tags.
+android_library(
+    name = "manual-maven-deps",
+    tags = ["maven_coordinates=com.android.support:support-annotations:25.0.0"],
+    visibility = ["//visibility:private"],
+    exports = [
+        "@androidsdk//com.android.support:support-annotations-25.0.0",
     ],
 )
 
@@ -76,35 +79,12 @@
     targets = [":android"],
 )
 
-dejetified_library(
-    name = "dejetified-android",
-    input = ":android.aar",
-    output = "android-legacy.aar",
-)
-
-android_library(
-    name = "legacy-deps",
-    tags = ["maven_coordinates=com.google.dagger:dagger-android-legacy:" + POM_VERSION],
-    exports = [
-        "//:dagger_with_compiler",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@maven//:com_android_support_support_annotations",
-    ],
-)
-
-pom_file(
-    name = "legacy-pom",
-    artifact_id = "dagger-android-legacy",
-    artifact_name = "Dagger Android Legacy",
-    packaging = "aar",
-    targets = [":legacy-deps"],
-)
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
 
 javadoc_library(
     name = "android-javadoc",
     srcs = [":android-srcs"],
-    android_api_level = 30,
+    android_api_level = 26,
     exclude_packages = ["dagger.android.internal"],
     root_packages = ["dagger.android"],
     deps = [":android"],
diff --git a/java/dagger/android/DaggerActivity.java b/java/dagger/android/DaggerActivity.java
index 9f37223..43708f3 100644
--- a/java/dagger/android/DaggerActivity.java
+++ b/java/dagger/android/DaggerActivity.java
@@ -19,7 +19,7 @@
 import android.app.Activity;
 import android.app.Fragment;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
+import android.support.annotation.Nullable;
 import dagger.internal.Beta;
 import javax.inject.Inject;
 
diff --git a/java/dagger/android/DaggerBroadcastReceiver.java b/java/dagger/android/DaggerBroadcastReceiver.java
index 2efd724..d39aa86 100644
--- a/java/dagger/android/DaggerBroadcastReceiver.java
+++ b/java/dagger/android/DaggerBroadcastReceiver.java
@@ -19,7 +19,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import androidx.annotation.CallSuper;
+import android.support.annotation.CallSuper;
 import dagger.internal.Beta;
 
 /**
diff --git a/java/dagger/android/DaggerContentProvider.java b/java/dagger/android/DaggerContentProvider.java
index e1d3f54..4aad485 100644
--- a/java/dagger/android/DaggerContentProvider.java
+++ b/java/dagger/android/DaggerContentProvider.java
@@ -17,7 +17,7 @@
 package dagger.android;
 
 import android.content.ContentProvider;
-import androidx.annotation.CallSuper;
+import android.support.annotation.CallSuper;
 import dagger.internal.Beta;
 
 /** A {@link ContentProvider} that injects its members in {@link #onCreate()}. */
diff --git a/java/dagger/android/HasActivityInjector.java b/java/dagger/android/HasActivityInjector.java
new file mode 100644
index 0000000..136bbad
--- /dev/null
+++ b/java/dagger/android/HasActivityInjector.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.android;
+
+import android.app.Activity;
+import dagger.internal.Beta;
+
+/** Provides an {@link AndroidInjector} of {@link Activity}s. */
+@Beta
+public interface HasActivityInjector {
+
+  /** Returns an {@link AndroidInjector} of {@link Activity}s. */
+  AndroidInjector<Activity> activityInjector();
+}
diff --git a/java/dagger/android/HasBroadcastReceiverInjector.java b/java/dagger/android/HasBroadcastReceiverInjector.java
new file mode 100644
index 0000000..b2aa992
--- /dev/null
+++ b/java/dagger/android/HasBroadcastReceiverInjector.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.android;
+
+import android.content.BroadcastReceiver;
+import dagger.internal.Beta;
+
+/** Provides an {@link AndroidInjector} of {@link BroadcastReceiver}s. */
+@Beta
+public interface HasBroadcastReceiverInjector {
+
+  /** Returns an {@link AndroidInjector} of {@link BroadcastReceiver}s. */
+  AndroidInjector<BroadcastReceiver> broadcastReceiverInjector();
+}
diff --git a/java/dagger/android/HasContentProviderInjector.java b/java/dagger/android/HasContentProviderInjector.java
new file mode 100644
index 0000000..997ddb8
--- /dev/null
+++ b/java/dagger/android/HasContentProviderInjector.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.android;
+
+import android.content.ContentProvider;
+import dagger.internal.Beta;
+
+/** Provides an {@link AndroidInjector} of {@link ContentProvider}s. */
+@Beta
+public interface HasContentProviderInjector {
+
+  /** Returns an {@link AndroidInjector} of {@link ContentProvider}s. */
+  AndroidInjector<ContentProvider> contentProviderInjector();
+}
diff --git a/java/dagger/android/HasFragmentInjector.java b/java/dagger/android/HasFragmentInjector.java
new file mode 100644
index 0000000..564f32d
--- /dev/null
+++ b/java/dagger/android/HasFragmentInjector.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.android;
+
+import android.app.Fragment;
+import dagger.internal.Beta;
+
+/** Provides an {@link AndroidInjector} of {@link Fragment}s. */
+@Beta
+public interface HasFragmentInjector {
+
+  /** Returns an {@link AndroidInjector} of {@link Fragment}s. */
+  AndroidInjector<Fragment> fragmentInjector();
+}
diff --git a/java/dagger/android/HasServiceInjector.java b/java/dagger/android/HasServiceInjector.java
new file mode 100644
index 0000000..d1c6a6c
--- /dev/null
+++ b/java/dagger/android/HasServiceInjector.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.android;
+
+import android.app.Service;
+import dagger.internal.Beta;
+
+/** Provides an {@link AndroidInjector} of {@link Service}s. */
+@Beta
+public interface HasServiceInjector {
+
+  /** Returns an {@link AndroidInjector} of {@link Service}s. */
+  AndroidInjector<Service> serviceInjector();
+}
diff --git a/java/dagger/android/internal/AndroidInjectionKeys.java b/java/dagger/android/internal/AndroidInjectionKeys.java
index 1425350..f30b92c 100644
--- a/java/dagger/android/internal/AndroidInjectionKeys.java
+++ b/java/dagger/android/internal/AndroidInjectionKeys.java
@@ -20,7 +20,6 @@
  * An internal implementation detail of Dagger's generated code. This is not guaranteed to remain
  * consistent from version to version.
  */
-@GenerateAndroidInjectionProguardRules
 public final class AndroidInjectionKeys {
   /**
    * Accepts the fully qualified name of a class that is injected with {@code dagger.android}.
diff --git a/java/dagger/android/internal/GenerateAndroidInjectionProguardRules.java b/java/dagger/android/internal/GenerateAndroidInjectionProguardRules.java
deleted file mode 100644
index 46bbb66..0000000
--- a/java/dagger/android/internal/GenerateAndroidInjectionProguardRules.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.internal;
-
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Our proguard rules generator needs one annotation to hook into for it to run, so we use this
- * internally on {@link dagger.android.internal.AndroidInjectionKeys} as a throwaway for it to run.
- * It has no other purpose.
- */
-@Target(TYPE)
-@Retention(SOURCE)
-@interface GenerateAndroidInjectionProguardRules {}
diff --git a/java/dagger/android/internal/proguard/BUILD b/java/dagger/android/internal/proguard/BUILD
deleted file mode 100644
index a11d0c0..0000000
--- a/java/dagger/android/internal/proguard/BUILD
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Internal Proguard Processor
-
-load("@rules_java//java:defs.bzl", "java_library", "java_plugin")
-load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "DOCLINT_REFERENCES")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "proguard-processor",
-    srcs = ["ProguardProcessor.java"],
-    javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
-    deps = [
-        "@google_bazel_common//third_party/java/auto:service",
-    ],
-)
-
-java_plugin(
-    name = "plugin",
-    generates_api = 1,
-    processor_class = "dagger.android.internal.proguard.ProguardProcessor",
-    deps = [":proguard-processor"],
-)
diff --git a/java/dagger/android/internal/proguard/ProguardProcessor.java b/java/dagger/android/internal/proguard/ProguardProcessor.java
deleted file mode 100644
index 49274e9..0000000
--- a/java/dagger/android/internal/proguard/ProguardProcessor.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.internal.proguard;
-
-import static javax.tools.StandardLocation.CLASS_OUTPUT;
-
-import com.google.auto.service.AutoService;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Set;
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Filer;
-import javax.annotation.processing.Processor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.TypeElement;
-
-/**
- * An {@linkplain Processor annotation processor} to generate dagger-android's specific proguard
- * needs. This is only intended to run over the dagger-android project itself, as the alternative is
- * to create an intermediary java_library for proguard rules to be consumed by the project.
- *
- * <p>Basic structure looks like this:
- *
- * <pre><code>
- *   resources/META-INF/com.android.tools/proguard/dagger-android.pro
- *   resources/META-INF/com.android.tools/r8/dagger-android.pro
- *   resources/META-INF/proguard/dagger-android.pro
- * </code></pre>
- */
-@AutoService(Processor.class)
-@SupportedAnnotationTypes(ProguardProcessor.GENERATE_RULES_ANNOTATION_NAME)
-public final class ProguardProcessor extends AbstractProcessor {
-
-  static final String GENERATE_RULES_ANNOTATION_NAME =
-      "dagger.android.internal.GenerateAndroidInjectionProguardRules";
-
-  @Override
-  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
-    roundEnv
-        .getElementsAnnotatedWith(
-            processingEnv.getElementUtils().getTypeElement(GENERATE_RULES_ANNOTATION_NAME))
-        .forEach(element -> generate());
-
-    return false;
-  }
-
-  private void generate() {
-    Filer filer = processingEnv.getFiler();
-
-    String errorProneRule = "-dontwarn com.google.errorprone.annotations.**\n";
-    String androidInjectionKeysRule =
-        "-identifiernamestring class dagger.android.internal.AndroidInjectionKeys {\n"
-            + "  java.lang.String of(java.lang.String);\n"
-            + "}\n";
-
-    writeFile(filer, "com.android.tools/proguard", errorProneRule);
-    writeFile(filer, "com.android.tools/r8", errorProneRule + androidInjectionKeysRule);
-    writeFile(filer, "proguard", errorProneRule);
-  }
-
-  private static void writeFile(Filer filer, String intermediatePath, String contents) {
-    try (Writer writer =
-        filer
-            .createResource(
-                CLASS_OUTPUT, "", "META-INF/" + intermediatePath + "/dagger-android.pro")
-            .openWriter()) {
-      writer.write(contents);
-    } catch (IOException e) {
-      throw new IllegalStateException(e);
-    }
-  }
-
-  @Override
-  public SourceVersion getSupportedSourceVersion() {
-    return SourceVersion.latestSupported();
-  }
-}
diff --git a/java/dagger/android/processor/AndroidProcessor.java b/java/dagger/android/processor/AndroidProcessor.java
index ad7f08e..5c17341 100644
--- a/java/dagger/android/processor/AndroidProcessor.java
+++ b/java/dagger/android/processor/AndroidProcessor.java
@@ -17,18 +17,23 @@
 package dagger.android.processor;
 
 import static javax.tools.Diagnostic.Kind.ERROR;
+import static javax.tools.StandardLocation.CLASS_OUTPUT;
 import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
 
 import com.google.auto.common.BasicAnnotationProcessor;
 import com.google.auto.service.AutoService;
 import com.google.common.base.Ascii;
+import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.googlejavaformat.java.filer.FormattingFiler;
+import java.io.IOException;
+import java.io.Writer;
 import java.util.Set;
 import javax.annotation.processing.Filer;
 import javax.annotation.processing.Messager;
 import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
 import javax.lang.model.SourceVersion;
 import javax.lang.model.util.Elements;
 import javax.lang.model.util.Types;
@@ -93,6 +98,29 @@
   }
 
   @Override
+  protected void postRound(RoundEnvironment roundEnv) {
+    if (roundEnv.processingOver() && useStringKeys()) {
+      try (Writer writer = createProguardFile()){
+        writer.write(
+            Joiner.on("\n")
+                .join(
+                    "-identifiernamestring class dagger.android.internal.AndroidInjectionKeys {",
+                    "  java.lang.String of(java.lang.String);",
+                    "}"));
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  private Writer createProguardFile() throws IOException {
+    return processingEnv
+        .getFiler()
+        .createResource(CLASS_OUTPUT, "", "META-INF/proguard/dagger.android.AndroidInjectionKeys")
+        .openWriter();
+  }
+
+  @Override
   public Set<String> getSupportedOptions() {
     return ImmutableSet.of(FLAG_EXPERIMENTAL_USE_STRING_KEYS);
   }
diff --git a/java/dagger/android/processor/BUILD b/java/dagger/android/processor/BUILD
index 7e63c76..5754143 100644
--- a/java/dagger/android/processor/BUILD
+++ b/java/dagger/android/processor/BUILD
@@ -15,17 +15,14 @@
 # Description:
 #   Public Dagger API for Android
 
-load("@rules_java//java:defs.bzl", "java_import", "java_library", "java_plugin")
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
     "DOCLINT_REFERENCES",
-    "POM_VERSION",
 )
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-
-package(default_visibility = ["//:src"])
+load("//tools:maven.bzl", "POM_VERSION", "pom_file")
 
 filegroup(
     name = "srcs",
@@ -38,15 +35,15 @@
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     tags = ["maven_coordinates=com.google.dagger:dagger-android-processor:" + POM_VERSION],
     deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/auto:service",
         "@google_bazel_common//third_party/java/auto:value",
-        "@maven//:com_google_auto_auto_common",
+        "@google_bazel_common//third_party/java/auto:common",
         "@google_bazel_common//third_party/java/incap",
         "@google_bazel_common//third_party/java/javapoet",
         "@google_bazel_common//third_party/java/google_java_format",
         "//java/dagger:core",
+        "//java/dagger/model",
         "//java/dagger/spi",
         # https://github.com/bazelbuild/bazel/issues/2517
         ":dagger-android-jar",
@@ -81,6 +78,8 @@
     deps = [":processor"],
 )
 
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+
 javadoc_library(
     name = "processor-javadoc",
     srcs = [":srcs"],
diff --git a/java/dagger/android/proguard.cfg b/java/dagger/android/proguard.cfg
new file mode 100644
index 0000000..bd8ffbf
--- /dev/null
+++ b/java/dagger/android/proguard.cfg
@@ -0,0 +1 @@
+-dontwarn com.google.errorprone.annotations.**
diff --git a/java/dagger/android/support/AndroidSupportInjection.java b/java/dagger/android/support/AndroidSupportInjection.java
index c77e297..1624345 100644
--- a/java/dagger/android/support/AndroidSupportInjection.java
+++ b/java/dagger/android/support/AndroidSupportInjection.java
@@ -20,7 +20,8 @@
 import static dagger.internal.Preconditions.checkNotNull;
 
 import android.app.Activity;
-import androidx.fragment.app.Fragment;
+import android.app.Application;
+import android.support.v4.app.Fragment;
 import android.util.Log;
 import dagger.android.AndroidInjector;
 import dagger.android.HasAndroidInjector;
@@ -35,59 +36,72 @@
    * Injects {@code fragment} if an associated {@link AndroidInjector} implementation can be found,
    * otherwise throws an {@link IllegalArgumentException}.
    *
-   * <p>Uses the following algorithm to find the appropriate {@code AndroidInjector<Fragment>} to
-   * use to inject {@code fragment}:
+   * <p>Uses the following algorithm to find the appropriate {@link AndroidInjector} to use to
+   * inject {@code fragment}:
    *
    * <ol>
-   *   <li>Walks the parent-fragment hierarchy to find the a fragment that implements {@link
-   *       HasAndroidInjector}, and if none do
+   *   <li>Walks the parent-fragment hierarchy to find a fragment that implements {@link
+   *       HasAndroidInjector} or {@link HasSupportFragmentInjector}, and if none do
    *   <li>Uses the {@code fragment}'s {@link Fragment#getActivity() activity} if it implements
-   *       {@link HasAndroidInjector}, and if not
-   *   <li>Uses the {@link android.app.Application} if it implements {@link HasAndroidInjector}.
+   *       {@link HasAndroidInjector} or {@link HasSupportFragmentInjector}, and if not
+   *   <li>Uses the {@link android.app.Application} if it implements {@link HasAndroidInjector}
+   *       {@link HasSupportFragmentInjector}.
    * </ol>
    *
-   * If none of them implement {@link HasAndroidInjector}, a {@link IllegalArgumentException} is
-   * thrown.
+   * If none of them implement {@link HasAndroidInjector} or {@link HasSupportFragmentInjector}, a
+   * {@link IllegalArgumentException} is thrown.
    *
    * @throws IllegalArgumentException if no parent fragment, activity, or application implements
-   *     {@link HasAndroidInjector}.
+   *     {@link HasAndroidInjector} or {@link HasSupportFragmentInjector}.
    */
   public static void inject(Fragment fragment) {
     checkNotNull(fragment, "fragment");
-    HasAndroidInjector hasAndroidInjector = findHasAndroidInjectorForFragment(fragment);
+
+    Object hasInjector = findHasSupportFragmentInjector(fragment);
+    AndroidInjector<? super Fragment> injector;
+    if (hasInjector instanceof HasAndroidInjector) {
+      injector = ((HasAndroidInjector) hasInjector).androidInjector();
+      checkNotNull(injector, "%s.androidInjector() returned null", hasInjector.getClass());
+    } else if (hasInjector instanceof HasSupportFragmentInjector) {
+      injector = ((HasSupportFragmentInjector) hasInjector).supportFragmentInjector();
+      checkNotNull(injector, "%s.supportFragmentInjector() returned null", hasInjector.getClass());
+    } else {
+      throw new RuntimeException(
+          String.format(
+              "%s does not implement %s or %s",
+              hasInjector.getClass().getCanonicalName(),
+              HasAndroidInjector.class.getCanonicalName(),
+              HasSupportFragmentInjector.class.getCanonicalName()));
+    }
+
     if (Log.isLoggable(TAG, DEBUG)) {
       Log.d(
           TAG,
           String.format(
               "An injector for %s was found in %s",
               fragment.getClass().getCanonicalName(),
-              hasAndroidInjector.getClass().getCanonicalName()));
+              hasInjector.getClass().getCanonicalName()));
     }
 
-    inject(fragment, hasAndroidInjector);
+    injector.inject(fragment);
   }
 
-  private static void inject(Object target, HasAndroidInjector hasAndroidInjector) {
-    AndroidInjector<Object> androidInjector = hasAndroidInjector.androidInjector();
-    checkNotNull(
-        androidInjector, "%s.androidInjector() returned null", hasAndroidInjector.getClass());
-
-    androidInjector.inject(target);
-  }
-
-  private static HasAndroidInjector findHasAndroidInjectorForFragment(Fragment fragment) {
+  private static Object findHasSupportFragmentInjector(Fragment fragment) {
     Fragment parentFragment = fragment;
     while ((parentFragment = parentFragment.getParentFragment()) != null) {
-      if (parentFragment instanceof HasAndroidInjector) {
-        return (HasAndroidInjector) parentFragment;
+      if (parentFragment instanceof HasAndroidInjector
+          || parentFragment instanceof HasSupportFragmentInjector) {
+        return parentFragment;
       }
     }
     Activity activity = fragment.getActivity();
-    if (activity instanceof HasAndroidInjector) {
-      return (HasAndroidInjector) activity;
+    if (activity instanceof HasAndroidInjector || activity instanceof HasSupportFragmentInjector) {
+      return activity;
     }
-    if (activity.getApplication() instanceof HasAndroidInjector) {
-      return (HasAndroidInjector) activity.getApplication();
+    Application application = activity.getApplication();
+    if (application instanceof HasAndroidInjector
+        || application instanceof HasSupportFragmentInjector) {
+      return application;
     }
     throw new IllegalArgumentException(
         String.format("No injector was found for %s", fragment.getClass().getCanonicalName()));
diff --git a/java/dagger/android/support/BUILD b/java/dagger/android/support/BUILD
index 03846b5..749d541 100644
--- a/java/dagger/android/support/BUILD
+++ b/java/dagger/android/support/BUILD
@@ -15,17 +15,11 @@
 # Description:
 #   Public Dagger API for Android that interacts with the Android support libraries
 
-load(
-    "//:build_defs.bzl",
-    "POM_VERSION",
-    "SOURCE_7_TARGET_7",
-)
-load("//tools:dejetify.bzl", "dejetified_library")
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-
 package(default_visibility = ["//:src"])
 
+load("//:build_defs.bzl", "SOURCE_7_TARGET_7")
+load("//tools:maven.bzl", "pom_file", "POM_VERSION")
+
 filegroup(
     name = "support-srcs",
     srcs = glob(["*.java"]),
@@ -38,12 +32,27 @@
     manifest = "AndroidManifest.xml",
     tags = ["maven_coordinates=com.google.dagger:dagger-android-support:" + POM_VERSION],
     deps = [
+        ":manual-maven-deps",
         "//:dagger_with_compiler",
         "//java/dagger/android",
         "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@maven//:androidx_annotation_annotation",
-        "@maven//:androidx_appcompat_appcompat",
-        "@maven//:androidx_fragment_fragment",
+    ],
+)
+
+# Our pom.xml generator does not have a way to add manual maven deps. This target exports the
+# targets that don't have the necessary maven_coordinates tags.
+android_library(
+    name = "manual-maven-deps",
+    tags = [
+        "maven_coordinates=com.android.support:appcompat-v7:25.0.0",
+        "maven_coordinates=com.android.support:support-annotations:25.0.0",
+        "maven_coordinates=com.android.support:support-fragment:25.0.0",
+    ],
+    visibility = ["//visibility:private"],
+    exports = [
+        "@androidsdk//com.android.support:appcompat-v7-25.0.0",
+        "@androidsdk//com.android.support:support-annotations-25.0.0",
+        "@androidsdk//com.android.support:support-fragment-25.0.0",
     ],
 )
 
@@ -55,37 +64,12 @@
     targets = [":support"],
 )
 
-dejetified_library(
-    name = "dejetified-support",
-    input = ":support.aar",
-    output = "support-legacy.aar",
-)
-
-android_library(
-    name = "legacy-deps",
-    tags = ["maven_coordinates=com.google.dagger:dagger-android-support-legacy:" + POM_VERSION],
-    exports = [
-        "//:dagger_with_compiler",
-        "//java/dagger/android:legacy-deps",
-        "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@maven//:com_android_support_appcompat_v7",
-        "@maven//:com_android_support_support_annotations",
-        "@maven//:com_android_support_support_fragment",
-    ],
-)
-
-pom_file(
-    name = "legacy-pom",
-    artifact_id = "dagger-android-support-legacy",
-    artifact_name = "Dagger Android Legacy Support",
-    packaging = "aar",
-    targets = [":legacy-deps"],
-)
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
 
 javadoc_library(
     name = "support-javadoc",
     srcs = [":support-srcs"],
-    android_api_level = 30,
+    android_api_level = 26,
     root_packages = ["dagger.android.support"],
     deps = [":support"],
 )
diff --git a/java/dagger/android/support/DaggerAppCompatActivity.java b/java/dagger/android/support/DaggerAppCompatActivity.java
index da5b173..ccc4faa 100644
--- a/java/dagger/android/support/DaggerAppCompatActivity.java
+++ b/java/dagger/android/support/DaggerAppCompatActivity.java
@@ -17,10 +17,8 @@
 package dagger.android.support;
 
 import android.os.Bundle;
-import androidx.annotation.ContentView;
-import androidx.annotation.LayoutRes;
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
 import dagger.android.AndroidInjection;
 import dagger.android.AndroidInjector;
 import dagger.android.DispatchingAndroidInjector;
@@ -38,15 +36,6 @@
 
   @Inject DispatchingAndroidInjector<Object> androidInjector;
 
-  public DaggerAppCompatActivity() {
-    super();
-  }
-
-  @ContentView
-  public DaggerAppCompatActivity(@LayoutRes int contentLayoutId) {
-    super(contentLayoutId);
-  }
-
   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
     AndroidInjection.inject(this);
diff --git a/java/dagger/android/support/DaggerAppCompatDialogFragment.java b/java/dagger/android/support/DaggerAppCompatDialogFragment.java
index 7a5a76d..1efaeec 100644
--- a/java/dagger/android/support/DaggerAppCompatDialogFragment.java
+++ b/java/dagger/android/support/DaggerAppCompatDialogFragment.java
@@ -17,8 +17,8 @@
 package dagger.android.support;
 
 import android.content.Context;
-import androidx.fragment.app.Fragment;
-import androidx.appcompat.app.AppCompatDialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.AppCompatDialogFragment;
 import dagger.android.AndroidInjector;
 import dagger.android.DispatchingAndroidInjector;
 import dagger.android.HasAndroidInjector;
diff --git a/java/dagger/android/support/DaggerDialogFragment.java b/java/dagger/android/support/DaggerDialogFragment.java
index 8b0bf23..69b90bc 100644
--- a/java/dagger/android/support/DaggerDialogFragment.java
+++ b/java/dagger/android/support/DaggerDialogFragment.java
@@ -17,8 +17,8 @@
 package dagger.android.support;
 
 import android.content.Context;
-import androidx.fragment.app.DialogFragment;
-import androidx.fragment.app.Fragment;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
 import dagger.android.AndroidInjector;
 import dagger.android.DispatchingAndroidInjector;
 import dagger.android.HasAndroidInjector;
diff --git a/java/dagger/android/support/DaggerFragment.java b/java/dagger/android/support/DaggerFragment.java
index 8874511..332cdaa 100644
--- a/java/dagger/android/support/DaggerFragment.java
+++ b/java/dagger/android/support/DaggerFragment.java
@@ -17,9 +17,7 @@
 package dagger.android.support;
 
 import android.content.Context;
-import androidx.annotation.ContentView;
-import androidx.annotation.LayoutRes;
-import androidx.fragment.app.Fragment;
+import android.support.v4.app.Fragment;
 import dagger.android.AndroidInjector;
 import dagger.android.DispatchingAndroidInjector;
 import dagger.android.HasAndroidInjector;
@@ -36,15 +34,6 @@
 
   @Inject DispatchingAndroidInjector<Object> androidInjector;
 
-  public DaggerFragment() {
-    super();
-  }
-
-  @ContentView
-  public DaggerFragment(@LayoutRes int contentLayoutId) {
-    super(contentLayoutId);
-  }
-
   @Override
   public void onAttach(Context context) {
     AndroidSupportInjection.inject(this);
diff --git a/java/dagger/android/support/HasSupportFragmentInjector.java b/java/dagger/android/support/HasSupportFragmentInjector.java
new file mode 100644
index 0000000..e80609e
--- /dev/null
+++ b/java/dagger/android/support/HasSupportFragmentInjector.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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.android.support;
+
+import android.support.v4.app.Fragment;
+import dagger.android.AndroidInjector;
+import dagger.internal.Beta;
+
+/** Provides an {@link AndroidInjector} of {@link Fragment}s. */
+@Beta
+public interface HasSupportFragmentInjector {
+
+  /** Returns an {@link AndroidInjector} of {@link Fragment}s. */
+  AndroidInjector<Fragment> supportFragmentInjector();
+}
diff --git a/java/dagger/assisted/Assisted.java b/java/dagger/assisted/Assisted.java
deleted file mode 100644
index 59d8eec..0000000
--- a/java/dagger/assisted/Assisted.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2020 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.assisted;
-
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Annotates a parameter within an {@link AssistedInject}-annotated constructor.
- *
- * <p>See {@link AssistedInject}.
- */
-@Documented
-@Retention(RUNTIME)
-@Target(PARAMETER)
-public @interface Assisted {
-
-  /**
-   * Returns an identifier for an {@link Assisted} parameter.
-   *
-   * <p>Within an {@link AssistedInject} constructor, each {@link Assisted} parameter must be
-   * uniquely defined by the combination of its identifier and type. If no identifier is specified,
-   * the default identifier is an empty string. Thus, the following parameters are equivalent within
-   * an {@link AssistedInject} constructor:
-   *
-   * <ul>
-   *   <li> {@code @Assisted Foo foo}
-   *   <li> {@code @Assisted("") Foo foo}
-   * </ul>
-   *
-   * <p>Within an {@link AssistedFactory} method, each parameter must match an {@link Assisted}
-   * parameter in the associated {@link AssistedInject} constructor (i.e. identifier + type).
-   * A parameter with no {@code @Assisted} annotation will be assigned the default identifier. Thus,
-   * the following parameters are equivalent within an {@link AssistedFactory} method:
-   *
-   * <ul>
-   *   <li> {@code Foo foo}
-   *   <li> {@code @Assisted Foo foo}
-   *   <li> {@code @Assisted("") Foo foo}
-   * </ul>
-   *
-   * <p>Example:
-   *
-   * <pre><code>
-   * final class DataService {
-   *   {@literal @}AssistedInject
-   *   DataService(
-   *       BindingFromDagger bindingFromDagger,
-   *       {@literal @}Assisted String name,
-   *       {@literal @}Assisted("id") String id,
-   *       {@literal @}Assisted("repo") String repo) {}
-   * }
-   *
-   * {@literal @}AssistedFactory
-   * interface DataServiceFactory {
-   *   DataService create(
-   *       String name,
-   *       {@literal @}Assisted("id") String id,
-   *       {@literal @}Assisted("repo") String repo);
-   * }
-   * </code></pre>
-   */
-  String value() default "";
-}
diff --git a/java/dagger/assisted/AssistedFactory.java b/java/dagger/assisted/AssistedFactory.java
deleted file mode 100644
index 4eba9a7..0000000
--- a/java/dagger/assisted/AssistedFactory.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 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.assisted;
-
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Annotates an abstract class or interface used to create an instance of a type via an {@link
- * AssistedInject} constructor.
- *
- * <p>An {@link AssistedFactory}-annotated type must obey the following constraints:
- *
- * <ul>
- *   <li>The type must be an abstract class or interface,
- *   <li>The type must contain exactly one abstract, non-default method whose
- *       <ul>
- *         <li>return type must exactly match the type of an assisted injection type, and
- *         <li>parameters must match the exact list of {@link Assisted} parameters in the assisted
- *             injection type's constructor (and in the same order).
- *       </ul>
- * </ul>
- *
- * See {@link AssistedInject}
- */
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-public @interface AssistedFactory {}
diff --git a/java/dagger/assisted/AssistedInject.java b/java/dagger/assisted/AssistedInject.java
deleted file mode 100644
index fadd46d..0000000
--- a/java/dagger/assisted/AssistedInject.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2020 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.assisted;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Annotates the constuctor of a type that will be created via assisted injection.
- *
- * <p>Note that an assisted injection type cannot be scoped. In addition, assisted injection
- * requires the use of a factory annotated with {@link AssistedFactory} (see the example below).
- *
- * <p>Example usage:
- *
- * <p>Suppose we have a type, {@code DataService}, that has two dependencies: {@code DataFetcher}
- * and {@code Config}. When creating {@code DataService}, we would like to pass in an instance of
- * {@code Config} manually rather than having Dagger create it for us. This can be done using
- * assisted injection.
- *
- * <p>To start, we annotate the {@code DataService} constructor with {@link AssistedInject} and we
- * annotate the {@code Config} parameter with {@link Assisted}, as shown below:
- *
- * <pre><code>
- *   final class DataService {
- *     private final DataFetcher dataFetcher;
- *     private final Config config;
- *
- *     {@literal @}AssistedInject
- *     DataService(DataFetcher dataFetcher, {@literal @}Assisted Config config) {
- *       this.dataFetcher = dataFetcher;
- *       this.config = config;
- *     }
- *   }
- * </code></pre>
- *
- * <p>Next, we define a factory for the assisted type, {@code DataService}, and annotate it with
- * {@link AssistedFactory}. The factory must contain a single abstract, non-default method which
- * takes in all of the assisted parameters (in order) and returns the assisted type.
- *
- * <pre><code>
- *   {@literal @}AssistedFactory
- *   interface DataServiceFactory {
- *     DataService create(Config config);
- *   }
- * </code></pre>
- *
- * <p>Dagger will generate an implementation of the factory and bind it to the factory type. The
- * factory can then be used to create an instance of the assisted type:
- *
- * <pre><code>
- *   class MyApplication {
- *     {@literal @}Inject DataServiceFactory dataServiceFactory;
- *
- *     dataService = dataServiceFactory.create(new Config(...));
- *   }
- * </code></pre>
- */
-@Documented
-@Retention(RUNTIME)
-@Target(CONSTRUCTOR)
-public @interface AssistedInject {}
diff --git a/java/dagger/assisted/package-info.java b/java/dagger/assisted/package-info.java
deleted file mode 100644
index 9b8b7f0..0000000
--- a/java/dagger/assisted/package-info.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-/**
- * This package contains the API for Dagger's assisted injection.
- *
- * TODO(bcorso): Link to dagger.dev documentation.
- */
-package dagger.assisted;
diff --git a/java/dagger/errorprone/AndroidSupportInjectionModuleMigrator.java b/java/dagger/errorprone/AndroidSupportInjectionModuleMigrator.java
index bc0be48..e98fe9b 100644
--- a/java/dagger/errorprone/AndroidSupportInjectionModuleMigrator.java
+++ b/java/dagger/errorprone/AndroidSupportInjectionModuleMigrator.java
@@ -19,6 +19,7 @@
 import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
 
 import com.google.errorprone.BugPattern;
+import com.google.errorprone.BugPattern.ProvidesFix;
 import com.google.errorprone.VisitorState;
 import com.google.errorprone.bugpatterns.BugChecker;
 import com.google.errorprone.bugpatterns.BugChecker.MemberSelectTreeMatcher;
@@ -34,6 +35,7 @@
 /** A refactoring to update AndroidInjector bindings to their new form. */
 @BugPattern(
     name = "AndroidSupportInjectionModuleMigrator",
+    providesFix = ProvidesFix.REQUIRES_HUMAN_ATTENTION,
     summary = "Inlines usages of AndroidSupportInjectionModule to AndroidInjectionModule",
     explanation =
         "AndroidSupportInjectionModule is now an empty module and acts as an alias for "
diff --git a/java/dagger/errorprone/BUILD b/java/dagger/errorprone/BUILD
index 9c3707f..408925a 100644
--- a/java/dagger/errorprone/BUILD
+++ b/java/dagger/errorprone/BUILD
@@ -1,8 +1,6 @@
 # Description:
 #   ErrorProne refactorings and static analysis for Dagger
 
-load("@rules_java//java:defs.bzl", "java_library")
-
 package(default_visibility = ["//:src"])
 
 java_library(
@@ -10,8 +8,8 @@
     srcs = glob(["*.java"]),
     deps = [
         "//java/dagger:core",
-        "//java/dagger/internal/guava:collect",
         "@bazel_tools//tools/jdk:langtools-neverlink",
         "@google_bazel_common//third_party/java/error_prone:check_api",
+        "@google_bazel_common//third_party/java/guava",
     ],
 )
diff --git a/java/dagger/example/BUILD b/java/dagger/example/BUILD
deleted file mode 100644
index 1973229..0000000
--- a/java/dagger/example/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2017 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.
-#
-# Description:
-#   Dagger examples.
-
-package(default_visibility = ["//:src"])
diff --git a/java/dagger/example/android/simple/AndroidManifest.xml b/java/dagger/example/android/simple/AndroidManifest.xml
new file mode 100644
index 0000000..711fb1e
--- /dev/null
+++ b/java/dagger/example/android/simple/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<!--
+  ~ Copyright (C) 2017 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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="dagger.example.android.simple">
+
+  <uses-sdk
+    android:minSdkVersion="14"
+    android:targetSdkVersion="24"/>
+
+  <application android:name=".SimpleApplication" android:label="@string/appName">
+    <activity android:name=".MainActivity" android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+  </application>
+</manifest>
diff --git a/java/dagger/example/android/simple/BUILD b/java/dagger/example/android/simple/BUILD
new file mode 100644
index 0000000..7396744
--- /dev/null
+++ b/java/dagger/example/android/simple/BUILD
@@ -0,0 +1,42 @@
+# Copyright (C) 2017 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.
+#
+# Description:
+#   A skeletal application that demonstates wiring for an injected Application and Actiity.
+
+package(default_visibility = ["//:src"])
+
+android_library(
+    name = "simple_lib",
+    srcs = glob(["*.java"]),
+    manifest = "AndroidManifest.xml",
+    resource_files = glob(["res/**"]),
+    deps = [
+        "//:android",
+        "//:android-support",
+        "//:dagger_with_compiler",
+        "@androidsdk//com.android.support:appcompat-v7-25.0.0",
+        "@androidsdk//com.android.support:support-annotations-25.0.0",
+        "@androidsdk//com.android.support:support-fragment-25.0.0",
+    ],
+)
+
+android_binary(
+    name = "simple",
+    aapt_version = "aapt",
+    manifest = "AndroidManifest.xml",
+    deps = [
+        ":simple_lib",
+    ],
+)
diff --git a/java/dagger/example/android/simple/BuildModule.java b/java/dagger/example/android/simple/BuildModule.java
new file mode 100644
index 0000000..40ac8ee
--- /dev/null
+++ b/java/dagger/example/android/simple/BuildModule.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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.example.android.simple;
+
+import static android.os.Build.MODEL;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+final class BuildModule {
+  @Provides
+  @Model
+  static String provideModel() {
+    return MODEL;
+  }
+}
diff --git a/java/dagger/example/android/simple/MainActivity.java b/java/dagger/example/android/simple/MainActivity.java
new file mode 100644
index 0000000..f2aab2d
--- /dev/null
+++ b/java/dagger/example/android/simple/MainActivity.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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.example.android.simple;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.TextView;
+import dagger.Binds;
+import dagger.android.AndroidInjector;
+import dagger.android.support.DaggerAppCompatActivity;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+import javax.inject.Inject;
+
+/**
+ * The main activity application. It can be injected with any binding from both {@link Component}
+ * and {@link dagger.example.android.simple.SimpleApplication.Component}.
+ */
+public class MainActivity extends DaggerAppCompatActivity {
+  @dagger.Subcomponent
+  interface Component extends AndroidInjector<MainActivity> {
+
+    @dagger.Subcomponent.Builder
+    abstract class Builder extends AndroidInjector.Builder<MainActivity> {}
+  }
+
+  @dagger.Module(subcomponents = Component.class)
+  abstract class Module {
+
+    @Binds
+    @IntoMap
+    @ClassKey(MainActivity.class)
+    abstract AndroidInjector.Factory<?> bind(Component.Builder builder);
+  }
+
+  private static final String TAG = MainActivity.class.getSimpleName();
+
+  @Inject @Model String model;
+
+  @Inject
+  void logInjection() {
+    Log.i(TAG, "Injecting " + MainActivity.class.getSimpleName());
+  }
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+
+    setContentView(R.layout.activity_main);
+
+    TextView greeting = (TextView) findViewById(R.id.greeting);
+    String text = getResources().getString(R.string.welcome, model);
+    greeting.setText(text);
+  }
+}
diff --git a/java/dagger/example/android/simple/Model.java b/java/dagger/example/android/simple/Model.java
new file mode 100644
index 0000000..c52bb98
--- /dev/null
+++ b/java/dagger/example/android/simple/Model.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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.example.android.simple;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import javax.inject.Qualifier;
+
+/** Qualifies bindings relating to {@link android.os.Build#MODEL}. */
+@Qualifier
+@Retention(RUNTIME)
+@Documented
+@interface Model {}
diff --git a/java/dagger/example/android/simple/SimpleApplication.java b/java/dagger/example/android/simple/SimpleApplication.java
new file mode 100644
index 0000000..ae3d42d
--- /dev/null
+++ b/java/dagger/example/android/simple/SimpleApplication.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 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.example.android.simple;
+
+import android.util.Log;
+import dagger.android.AndroidInjectionModule;
+import dagger.android.AndroidInjector;
+import dagger.android.DaggerApplication;
+import javax.inject.Inject;
+
+/**
+ * A simple, skeletal application that demonstrates a dependency-injected application using the
+ * utilities in {@code dagger.android}.
+ */
+public class SimpleApplication extends DaggerApplication {
+  private static final String TAG = SimpleApplication.class.getSimpleName();
+
+  @dagger.Component(
+      modules = {AndroidInjectionModule.class, MainActivity.Module.class, BuildModule.class})
+  /* @ApplicationScoped and/or @Singleton */
+  interface Component extends AndroidInjector<SimpleApplication> {
+    @dagger.Component.Builder
+    abstract class Builder extends AndroidInjector.Builder<SimpleApplication> {}
+  }
+
+  @Inject
+  void logInjection() {
+    Log.i(TAG, "Injecting " + SimpleApplication.class.getSimpleName());
+  }
+
+  @Override
+  public void onCreate() {
+    super.onCreate();
+  }
+
+  @Override
+  protected AndroidInjector<SimpleApplication> applicationInjector() {
+    return DaggerSimpleApplication_Component.builder().create(this);
+  }
+}
diff --git a/java/dagger/example/android/simple/res/layout/activity_main.xml b/java/dagger/example/android/simple/res/layout/activity_main.xml
new file mode 100644
index 0000000..37add1f
--- /dev/null
+++ b/java/dagger/example/android/simple/res/layout/activity_main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 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.
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="match_parent"
+  android:layout_height="match_parent"
+  android:background="@android:color/background_light">
+
+  <TextView
+    android:id="@+id/greeting"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_alignParentTop="true"
+    android:textColor="@android:color/primary_text_light"
+    style="@style/TextAppearance.AppCompat.Display4"
+    />
+</RelativeLayout>
diff --git a/java/dagger/example/android/simple/res/values/strings.xml b/java/dagger/example/android/simple/res/values/strings.xml
new file mode 100644
index 0000000..c4ba1fd
--- /dev/null
+++ b/java/dagger/example/android/simple/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <string name="appName">Simple Dagger</string>
+  <string name="welcome">Hello, %s!</string>
+</resources>
\ No newline at end of file
diff --git a/java/dagger/example/atm/AccountModule.java b/java/dagger/example/atm/AccountModule.java
deleted file mode 100644
index 3ff5a75..0000000
--- a/java/dagger/example/atm/AccountModule.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.example.atm.Database.Account;
-
-/** Bindings for the {@link Account} of the currently signed-in user. */
-@Module
-interface AccountModule {
-  @Provides
-  static Account account(Database database, @Username String username) {
-    return database.getAccount(username);
-  }
-}
diff --git a/java/dagger/example/atm/AmountsModule.java b/java/dagger/example/atm/AmountsModule.java
deleted file mode 100644
index 87e5e01..0000000
--- a/java/dagger/example/atm/AmountsModule.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.Module;
-import dagger.Provides;
-import java.math.BigDecimal;
-
-/** Configures various amounts of money the application uses to control transactions. */
-@Module
-abstract class AmountsModule {
-
-  @Provides
-  @MinimumBalance
-  static BigDecimal minimumBalance() {
-    return BigDecimal.ZERO;
-  }
-
-  @Provides
-  @MaximumWithdrawal
-  static BigDecimal maximumWithdrawal() {
-    return new BigDecimal(1000);
-  }
-}
diff --git a/java/dagger/example/atm/BUILD b/java/dagger/example/atm/BUILD
deleted file mode 100644
index d1ff505..0000000
--- a/java/dagger/example/atm/BUILD
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   An example of using dagger in a computerized fake ATM. The User's Guide (https://dagger.dev/users-guide)
-#   is a walkthrough that ultimately builds this example.
-
-load("@rules_java//java:defs.bzl", "java_binary", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "atm",
-    srcs = glob(["*.java"]),
-    deps = ["//:dagger_with_compiler"],
-)
-
-java_binary(
-    name = "CommandLineAtm",
-    main_class = "dagger.example.atm.CommandLineAtm",
-    runtime_deps = [":atm"],
-)
diff --git a/java/dagger/example/atm/BigDecimalCommand.java b/java/dagger/example/atm/BigDecimalCommand.java
deleted file mode 100644
index 29bd6f5..0000000
--- a/java/dagger/example/atm/BigDecimalCommand.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import java.math.BigDecimal;
-
-/**
- * Abstract {@link Command} that expects a single argument that can be converted to {@link
- * BigDecimal}.
- */
-abstract class BigDecimalCommand extends SingleArgCommand {
-
-  private final Outputter outputter;
-
-  protected BigDecimalCommand(Outputter outputter) {
-    this.outputter = outputter;
-  }
-
-  @Override
-  protected final Result handleArg(String arg) {
-    BigDecimal amount = tryParse(arg);
-    if (amount == null) {
-      outputter.output(arg + " is not a valid number");
-    } else if (amount.signum() <= 0) {
-      outputter.output("amount must be positive");
-    } else {
-      handleAmount(amount);
-    }
-    return Result.handled();
-  }
-
-  private static BigDecimal tryParse(String arg) {
-    try {
-      return new BigDecimal(arg);
-    } catch (NumberFormatException e) {
-      return null;
-    }
-  }
-
-  /** Handles the given (positive) {@code amount} of money. */
-  protected abstract void handleAmount(BigDecimal amount);
-}
diff --git a/java/dagger/example/atm/Command.java b/java/dagger/example/atm/Command.java
deleted file mode 100644
index a3ff0d0..0000000
--- a/java/dagger/example/atm/Command.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import java.util.List;
-import java.util.Optional;
-
-/** A text-based command handler. */
-interface Command {
-  /**
-   * Processes and optionally acts upon the given {@code input}.
-   *
-   * @return a {@link Result} indicating how the input was handled
-   */
-  Result handleInput(List<String> input);
-
-  /**
-   * A command result, which has a {@link Status} and optionally a new {@link CommandRouter} that
-   * will handle subsequent commands.
-   */
-  final class Result {
-    private final Status status;
-    private final Optional<CommandRouter> nestedCommandRouter;
-
-    private Result(Status status, Optional<CommandRouter> nestedCommandRouter) {
-      this.status = status;
-      this.nestedCommandRouter = nestedCommandRouter;
-    }
-
-    static Result invalid() {
-      return new Result(Status.INVALID, Optional.empty());
-    }
-
-    static Result handled() {
-      return new Result(Status.HANDLED, Optional.empty());
-    }
-
-    static Result inputCompleted() {
-      return new Result(Status.INPUT_COMPLETED, Optional.empty());
-    }
-
-    static Result enterNestedCommandSet(CommandRouter nestedCommandRouter) {
-      return new Result(Status.HANDLED, Optional.of(nestedCommandRouter));
-    }
-
-    Status status() {
-      return status;
-    }
-
-    Optional<CommandRouter> nestedCommandRouter() {
-      return nestedCommandRouter;
-    }
-  }
-
-  enum Status {
-    /** The command or its arguments were invalid. */
-    INVALID,
-
-    /** The command handled the input and no other commands should attempt to handle it. */
-    HANDLED,
-
-     // TODO(ronshapiro): maybe call this TERMINATED? If so, maybe this should be called
-    // ContinueStatus?
-    /** The command handled the input and no further inputs should be submitted. */
-    INPUT_COMPLETED,
-    ;
-  }
-}
diff --git a/java/dagger/example/atm/CommandLineAtm.java b/java/dagger/example/atm/CommandLineAtm.java
deleted file mode 100644
index be5cbe6..0000000
--- a/java/dagger/example/atm/CommandLineAtm.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.util.Scanner;
-
-/** Main class for the command-line ATM. */
-class CommandLineAtm {
-  public static void main(String[] args) {
-    Scanner scanner = new Scanner(System.in, UTF_8.name());
-    CommandProcessor commandProcessor = CommandProcessorFactory.create().commandProcessor();
-
-    while (scanner.hasNextLine()) {
-      Command.Status commandStatus = commandProcessor.process(scanner.nextLine());
-      if (commandStatus.equals(Command.Status.INPUT_COMPLETED)) {
-        break;
-      }
-    }
-  }
-}
diff --git a/java/dagger/example/atm/CommandProcessor.java b/java/dagger/example/atm/CommandProcessor.java
deleted file mode 100644
index 3b52d73..0000000
--- a/java/dagger/example/atm/CommandProcessor.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.example.atm.Command.Result;
-import dagger.example.atm.Command.Status;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/**
- * Processes successive commands by delegating to a {@link CommandRouter}.
- *
- * <p>Whereas {@link CommandRouter} routes an input string to a particular {@link Command}, this
- * class maintains inter-command state to determine which {@link CommandRouter} should route
- * successive commands.
- *
- * <p>This class is {@link Singleton} scoped because it has mutable state ({@code
- * commandRouterStack}), and all users of {@link CommandProcessor} must use the same instance.
- */
-@Singleton
-final class CommandProcessor {
-  private final Deque<CommandRouter> commandRouterStack = new ArrayDeque<>();
-
-  @Inject
-  CommandProcessor(CommandRouter firstCommandRouter) {
-    commandRouterStack.push(firstCommandRouter);
-  }
-
-  Status process(String input) {
-    if (commandRouterStack.isEmpty()) {
-      throw new IllegalStateException("No command router is available!");
-    }
-
-    Result result = commandRouterStack.peek().route(input);
-    switch (result.status()) {
-      case INPUT_COMPLETED:
-        commandRouterStack.pop();
-        return commandRouterStack.isEmpty() ? Status.INPUT_COMPLETED : Status.HANDLED;
-      case HANDLED:
-        // TODO(ronshapiro): We currently have a case of using a subcomponent for nested commands,
-        // which requires maintaining a binding indicating whether we are in the subcomponent are
-        // not. We can include another example where there's a CommandRouter that is created from an
-        // entirely different component, that way there are no inherited commands.
-        result.nestedCommandRouter().ifPresent(commandRouterStack::push);
-        // fall through
-      case INVALID:
-        return result.status();
-    }
-    throw new AssertionError(result.status());
-  }
-}
diff --git a/java/dagger/example/atm/CommandProcessorFactory.java b/java/dagger/example/atm/CommandProcessorFactory.java
deleted file mode 100644
index a449703..0000000
--- a/java/dagger/example/atm/CommandProcessorFactory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.Component;
-import javax.inject.Singleton;
-
-/**
- * Hand-written API for interfacing with Dagger. The command-line ATM needs a single class to
- * execute: {@link CommandProcessor}.
- *
- * <p>The list of {@code modules} declares where Dagger should look, besides {@link
- * javax.inject.Inject}-annotated constructors, to help instantiate {@link CommandProcessor} and its
- * dependencies.
- */
-@Singleton
-@Component(
-    modules = {
-      CommandsModule.class,
-      InMemoryDatabaseModule.class,
-      UserCommandsRouter.InstallationModule.class,
-      SystemOutModule.class,
-    })
-interface CommandProcessorFactory {
-  CommandProcessor commandProcessor();
-
-  static CommandProcessorFactory create() {
-    return DaggerCommandProcessorFactory.create();
-  }
-}
diff --git a/java/dagger/example/atm/CommandRouter.java b/java/dagger/example/atm/CommandRouter.java
deleted file mode 100644
index ef75220..0000000
--- a/java/dagger/example/atm/CommandRouter.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.example.atm.Command.Result;
-import dagger.example.atm.Command.Status;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import javax.inject.Inject;
-
-/** Routes individual text commands to the appropriate {@link Command}(s). */
-final class CommandRouter {
-  private final Map<String, Command> commands;
-  private final Outputter outputter;
-
-  @Inject
-  CommandRouter(Map<String, Command> commands, Outputter outputter) {
-    this.commands = commands;
-    this.outputter = outputter;
-  }
-
-  /**
-   * Calls {@link Command#handleInput(String) command.handleInput(input)} on this router's
-   * {@linkplain #commands commands}.
-   */
-  Result route(String input) {
-    List<String> splitInput = split(input);
-    if (splitInput.isEmpty()) {
-      return invalidCommand(input);
-    }
-
-    String commandKey = splitInput.get(0);
-    Command command = commands.get(commandKey);
-    if (command == null) {
-      return invalidCommand(input);
-    }
-
-    List<String> args = splitInput.subList(1, splitInput.size());
-    Result result = command.handleInput(args);
-    return result.status().equals(Status.INVALID) ? invalidCommand(input) : result;
-  }
-
-  private Result invalidCommand(String input) {
-    outputter.output(String.format("couldn't understand \"%s\". please try again.", input));
-    return Result.invalid();
-  }
-
-  private static List<String> split(String input) {
-    return Arrays.asList(input.trim().split("\\s+"));
-  }
-}
diff --git a/java/dagger/example/atm/CommandsModule.java b/java/dagger/example/atm/CommandsModule.java
deleted file mode 100644
index 266af12..0000000
--- a/java/dagger/example/atm/CommandsModule.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.Binds;
-import dagger.BindsOptionalOf;
-import dagger.Module;
-import dagger.example.atm.Database.Account;
-import dagger.multibindings.IntoMap;
-import dagger.multibindings.StringKey;
-
-/** Installs basic commands. */
-@Module
-interface CommandsModule {
-  @Binds
-  @IntoMap
-  @StringKey("hello")
-  Command helloWorld(HelloWorldCommand command);
-
-  @Binds
-  @IntoMap
-  @StringKey("login")
-  Command login(LoginCommand command);
-
-  /**
-   * Declare an optional binding for {@link Account}. This allows other bindings to change their
-   * behavior depending on whether an {@link Account} is bound in the current (sub)component.
-   */
-  @BindsOptionalOf
-  Account loggedInAccount();
-}
diff --git a/java/dagger/example/atm/Database.java b/java/dagger/example/atm/Database.java
deleted file mode 100644
index f6c0eda..0000000
--- a/java/dagger/example/atm/Database.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import java.math.BigDecimal;
-
-/** An ATM database. */
-interface Database {
-  Account getAccount(String username);
-
-  /** An individual user's account. */
-  interface Account {
-    String username();
-
-    void deposit(BigDecimal amount);
-
-    void withdraw(BigDecimal amount);
-
-    BigDecimal balance();
-  }
-}
diff --git a/java/dagger/example/atm/DepositCommand.java b/java/dagger/example/atm/DepositCommand.java
deleted file mode 100644
index 9a5e2e2..0000000
--- a/java/dagger/example/atm/DepositCommand.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.example.atm.Database.Account;
-import java.math.BigDecimal;
-import javax.inject.Inject;
-
-/** Deposits money to the ATM. */
-final class DepositCommand extends BigDecimalCommand {
-  private final Outputter outputter;
-  private final Account account;
-  private final WithdrawalLimiter withdrawalLimiter;
-
-  @Inject
-  DepositCommand(Outputter outputter, Account account, WithdrawalLimiter withdrawalLimiter) {
-    super(outputter);
-    this.outputter = outputter;
-    this.account = account;
-    this.withdrawalLimiter = withdrawalLimiter;
-  }
-
-  @Override
-  protected void handleAmount(BigDecimal amount) {
-    account.deposit(amount);
-    withdrawalLimiter.recordDeposit(amount);
-    outputter.output("your new balance is: " + account.balance());
-  }
-}
diff --git a/java/dagger/example/atm/HelloWorldCommand.java b/java/dagger/example/atm/HelloWorldCommand.java
deleted file mode 100644
index f39d585..0000000
--- a/java/dagger/example/atm/HelloWorldCommand.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import java.util.List;
-import javax.inject.Inject;
-
-final class HelloWorldCommand implements Command {
-  private final Outputter outputter;
-
-  @Inject
-  HelloWorldCommand(Outputter outputter) {
-    this.outputter = outputter;
-  }
-
-  @Override
-  public Result handleInput(List<String> args) {
-    if (!args.isEmpty()) {
-      return Result.invalid();
-    }
-    outputter.output("howdy!");
-    return Result.handled();
-  }
-}
diff --git a/java/dagger/example/atm/InMemoryDatabase.java b/java/dagger/example/atm/InMemoryDatabase.java
deleted file mode 100644
index 801d827..0000000
--- a/java/dagger/example/atm/InMemoryDatabase.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import java.math.BigDecimal;
-import java.util.HashMap;
-import java.util.Map;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** A database that stores all of its data in memory. */
-@Singleton
-final class InMemoryDatabase implements Database {
-  private final Map<String, Account> accounts = new HashMap<>();
-
-  @Inject
-  InMemoryDatabase() {}
-
-  @Override
-  public Account getAccount(String username) {
-    return accounts.computeIfAbsent(username, InMemoryAccount::new);
-  }
-
-  private static final class InMemoryAccount implements Account {
-    private final String username;
-    private BigDecimal balance = BigDecimal.ZERO;
-
-    InMemoryAccount(String username) {
-      this.username = username;
-    }
-
-    @Override
-    public String username() {
-      return username;
-    }
-
-    @Override
-    public void deposit(BigDecimal amount) {
-      checkNonNegative(amount, "deposit");
-      balance = balance.add(amount);
-    }
-
-    @Override
-    public void withdraw(BigDecimal amount) {
-      checkNonNegative(amount, "withdraw");
-      balance = balance.subtract(amount);
-    }
-
-    private void checkNonNegative(BigDecimal amount, String action) {
-      if (amount.signum() == -1) {
-        throw new IllegalArgumentException(
-            String.format("Cannot %s negative amounts: %s", action, amount));
-      }
-    }
-
-    @Override
-    public BigDecimal balance() {
-      return balance;
-    }
-  }
-}
diff --git a/java/dagger/example/atm/InMemoryDatabaseModule.java b/java/dagger/example/atm/InMemoryDatabaseModule.java
deleted file mode 100644
index bf4be67..0000000
--- a/java/dagger/example/atm/InMemoryDatabaseModule.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.Binds;
-import dagger.Module;
-
-@Module
-interface InMemoryDatabaseModule {
-  @Binds
-  Database inMemory(InMemoryDatabase database);
-}
diff --git a/java/dagger/example/atm/LoginCommand.java b/java/dagger/example/atm/LoginCommand.java
deleted file mode 100644
index 4978cb5..0000000
--- a/java/dagger/example/atm/LoginCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.example.atm.Database.Account;
-import java.util.Optional;
-import javax.inject.Inject;
-
-/** Logs in a user, allowing them to interact with the ATM. */
-final class LoginCommand extends SingleArgCommand {
-  private final Outputter outputter;
-  private final Optional<Account> account;
-  private final UserCommandsRouter.Factory userCommandsFactory;
-
-  @Inject
-  LoginCommand(
-      Outputter outputter,
-      Optional<Account> account,
-      UserCommandsRouter.Factory userCommandsFactory) {
-    this.outputter = outputter;
-    this.account = account;
-    this.userCommandsFactory = userCommandsFactory;
-  }
-
-  @Override
-  public Result handleArg(String username) {
-    // If an Account binding exists, that means there is a user logged in. Don't allow a login
-    // command if we already have someone logged in!
-    if (account.isPresent()) {
-      String loggedInUser = account.get().username();
-      outputter.output(loggedInUser + " is already logged in");
-      if (!loggedInUser.equals(username)) {
-        outputter.output("run `logout` first before trying to log in another user");
-      }
-      return Result.handled();
-    } else {
-      UserCommandsRouter userCommands = userCommandsFactory.create(username);
-      return Result.enterNestedCommandSet(userCommands.router());
-    }
-  }
-}
diff --git a/java/dagger/example/atm/LogoutCommand.java b/java/dagger/example/atm/LogoutCommand.java
deleted file mode 100644
index 811d4b3..0000000
--- a/java/dagger/example/atm/LogoutCommand.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.example.atm.Database.Account;
-import java.util.List;
-import javax.inject.Inject;
-
-/** Logs out the current user. */
-final class LogoutCommand implements Command {
-
-  private final Outputter outputter;
-  private final Account account;
-
-  @Inject
-  LogoutCommand(Outputter outputter, Account account) {
-    this.outputter = outputter;
-    this.account = account;
-  }
-
-  @Override
-  public Result handleInput(List<String> input) {
-    if (!input.isEmpty()) {
-      return Result.invalid();
-    }
-    outputter.output("logged out " + account.username());
-    return Result.inputCompleted();
-  }
-}
diff --git a/java/dagger/example/atm/MaximumWithdrawal.java b/java/dagger/example/atm/MaximumWithdrawal.java
deleted file mode 100644
index d41c559..0000000
--- a/java/dagger/example/atm/MaximumWithdrawal.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/**
- * Qualifier for the maximum amount that can be withdrawn from an account in a single transaction.
- */
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-@interface MaximumWithdrawal {}
diff --git a/java/dagger/example/atm/MinimumBalance.java b/java/dagger/example/atm/MinimumBalance.java
deleted file mode 100644
index bbb0ed1..0000000
--- a/java/dagger/example/atm/MinimumBalance.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifier for the minimum balance an account may have. */
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-@interface MinimumBalance {}
diff --git a/java/dagger/example/atm/Outputter.java b/java/dagger/example/atm/Outputter.java
deleted file mode 100644
index 3d8de8a..0000000
--- a/java/dagger/example/atm/Outputter.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-/** Writes to a user interface. */
-interface Outputter {
-  void output(String output);
-}
diff --git a/java/dagger/example/atm/PerSession.java b/java/dagger/example/atm/PerSession.java
deleted file mode 100644
index 22faba5..0000000
--- a/java/dagger/example/atm/PerSession.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Scope;
-
-/** A scope for instances that should be retained within a user session. */
-@Retention(RUNTIME)
-@Scope
-@Documented
-@interface PerSession {}
diff --git a/java/dagger/example/atm/SingleArgCommand.java b/java/dagger/example/atm/SingleArgCommand.java
deleted file mode 100644
index 81e5f65..0000000
--- a/java/dagger/example/atm/SingleArgCommand.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import java.util.List;
-
-/** Abstract command that accepts a single argument. */
-abstract class SingleArgCommand implements Command {
-
-  @Override
-  public final Result handleInput(List<String> input) {
-    return input.size() == 1 ? handleArg(input.get(0)) : Result.invalid();
-  }
-
-  /** Handles the single argument to the command. */
-  protected abstract Result handleArg(String arg);
-}
diff --git a/java/dagger/example/atm/SystemOutModule.java b/java/dagger/example/atm/SystemOutModule.java
deleted file mode 100644
index 3c22941..0000000
--- a/java/dagger/example/atm/SystemOutModule.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-final class SystemOutModule {
-  @Provides
-  static Outputter textOutputter() {
-    return System.out::println;
-  }
-}
diff --git a/java/dagger/example/atm/UserCommandsModule.java b/java/dagger/example/atm/UserCommandsModule.java
deleted file mode 100644
index bee4450..0000000
--- a/java/dagger/example/atm/UserCommandsModule.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.Binds;
-import dagger.Module;
-import dagger.multibindings.IntoMap;
-import dagger.multibindings.StringKey;
-
-/** Commands that are only applicable when a user is logged in. */
-@Module
-interface UserCommandsModule {
-  @Binds
-  @IntoMap
-  @StringKey("deposit")
-  Command deposit(DepositCommand command);
-
-  @Binds
-  @IntoMap
-  @StringKey("withdraw")
-  Command withdraw(WithdrawCommand command);
-
-  @Binds
-  @IntoMap
-  @StringKey("logout")
-  Command logout(LogoutCommand command);
-}
diff --git a/java/dagger/example/atm/UserCommandsRouter.java b/java/dagger/example/atm/UserCommandsRouter.java
deleted file mode 100644
index 7d65989..0000000
--- a/java/dagger/example/atm/UserCommandsRouter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.BindsInstance;
-import dagger.Module;
-import dagger.Subcomponent;
-
-@PerSession
-@Subcomponent(modules = {AccountModule.class, AmountsModule.class, UserCommandsModule.class})
-interface UserCommandsRouter {
-  CommandRouter router();
-
-  @Subcomponent.Factory
-  interface Factory {
-    UserCommandsRouter create(@BindsInstance @Username String username);
-  }
-
-  @Module(subcomponents = UserCommandsRouter.class)
-  interface InstallationModule {}
-}
diff --git a/java/dagger/example/atm/Username.java b/java/dagger/example/atm/Username.java
deleted file mode 100644
index 7972844..0000000
--- a/java/dagger/example/atm/Username.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifier for the currently logged-in user. */
-@Retention(RUNTIME)
-@Qualifier
-@Documented
-@interface Username {}
diff --git a/java/dagger/example/atm/WithdrawCommand.java b/java/dagger/example/atm/WithdrawCommand.java
deleted file mode 100644
index 7e0cf04..0000000
--- a/java/dagger/example/atm/WithdrawCommand.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import dagger.example.atm.Database.Account;
-import java.math.BigDecimal;
-import javax.inject.Inject;
-
-/** Withdraws money from the ATM. */
-final class WithdrawCommand extends BigDecimalCommand {
-  private final Outputter outputter;
-  private final Account account;
-  private final BigDecimal minimumBalance;
-  private final WithdrawalLimiter withdrawalLimiter;
-
-  @Inject
-  WithdrawCommand(
-      Outputter outputter,
-      Account account,
-      @MinimumBalance BigDecimal minimumBalance,
-      WithdrawalLimiter withdrawalLimiter) {
-    super(outputter);
-    this.outputter = outputter;
-    this.account = account;
-    this.minimumBalance = minimumBalance;
-    this.withdrawalLimiter = withdrawalLimiter;
-  }
-
-  @Override
-  protected void handleAmount(BigDecimal amount) {
-    BigDecimal remainingWithdrawalLimit = withdrawalLimiter.remainingWithdrawalLimit();
-    if (amount.compareTo(remainingWithdrawalLimit) > 0) {
-      outputter.output(
-          String.format(
-              "you may not withdraw %s; you may withdraw %s more in this session",
-              amount, remainingWithdrawalLimit));
-      return;
-    }
-
-    BigDecimal newBalance = account.balance().subtract(amount);
-    if (newBalance.compareTo(minimumBalance) < 0) {
-      outputter.output(
-          String.format(
-              "you don't have sufficient funds to withdraw %s. "
-                  + "your balance is %s and the minimum balance is %s",
-              amount, account.balance(), minimumBalance));
-    } else {
-      account.withdraw(amount);
-      withdrawalLimiter.recordWithdrawal(amount);
-      outputter.output("your new balance is: " + account.balance());
-    }
-  }
-}
diff --git a/java/dagger/example/atm/WithdrawalLimiter.java b/java/dagger/example/atm/WithdrawalLimiter.java
deleted file mode 100644
index c473b68..0000000
--- a/java/dagger/example/atm/WithdrawalLimiter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.atm;
-
-import java.math.BigDecimal;
-import javax.inject.Inject;
-
-/** Maintains the withdrawal amount available within a user session. */
-@PerSession
-final class WithdrawalLimiter {
-  private BigDecimal remainingWithdrawalLimit;
-
-  @Inject
-  WithdrawalLimiter(@MaximumWithdrawal BigDecimal maximumWithdrawal) {
-    this.remainingWithdrawalLimit = maximumWithdrawal;
-  }
-
-  void recordDeposit(BigDecimal amount) {
-    remainingWithdrawalLimit = remainingWithdrawalLimit.add(amount);
-  }
-
-  void recordWithdrawal(BigDecimal amount) {
-    remainingWithdrawalLimit = remainingWithdrawalLimit.subtract(amount);
-  }
-
-  BigDecimal remainingWithdrawalLimit() {
-    return remainingWithdrawalLimit;
-  }
-}
diff --git a/java/dagger/example/atm/build.gradle b/java/dagger/example/atm/build.gradle
deleted file mode 100644
index 2e6d3f4..0000000
--- a/java/dagger/example/atm/build.gradle
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-plugins {
-  id 'java'
-  id 'application'
-}
-
-repositories {
-  mavenCentral()
-}
-
-sourceSets {
-  main {
-    java {
-      srcDir '.'
-    }
-  }
-}
-
-dependencies {
-  implementation 'com.google.dagger:dagger:2.23.2'
-  annotationProcessor 'com.google.dagger:dagger-compiler:2.23.2'
-}
-
-mainClassName = 'dagger.example.atm.CommandLineAtm'
-
-// Run with: `gradle run -q --console=plain`
-run {
-  standardInput = System.in
-}
diff --git a/java/dagger/example/atm/gradlew b/java/dagger/example/atm/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/java/dagger/example/atm/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/java/dagger/example/atm/gradlew.bat b/java/dagger/example/atm/gradlew.bat
deleted file mode 100644
index 9991c50..0000000
--- a/java/dagger/example/atm/gradlew.bat
+++ /dev/null
@@ -1,100 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem      http://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem  Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/java/dagger/example/atm/settings.gradle b/java/dagger/example/atm/settings.gradle
deleted file mode 100644
index a6f2e01..0000000
--- a/java/dagger/example/atm/settings.gradle
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-rootProject.name = 'dagger-tutorial-atm'
diff --git a/java/dagger/example/gradle/android/simple/app/build.gradle b/java/dagger/example/gradle/android/simple/app/build.gradle
deleted file mode 100644
index d8f6346..0000000
--- a/java/dagger/example/gradle/android/simple/app/build.gradle
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-apply plugin: 'com.android.application'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        applicationId "dagger.example.gradle.android.simple"
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-}
-
-dependencies {
-  implementation 'androidx.appcompat:appcompat:1.2.0'
-  implementation 'com.google.dagger:dagger:LOCAL-SNAPSHOT'
-  implementation 'com.google.dagger:dagger-android-support:LOCAL-SNAPSHOT'
-  annotationProcessor 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
-  annotationProcessor 'com.google.dagger:dagger-android-processor:LOCAL-SNAPSHOT'
-
-  // To help us catch usages of Guava APIs for Java 8 in the '-jre' variant.
-  annotationProcessor'com.google.guava:guava:28.1-android'
-}
diff --git a/java/dagger/example/gradle/android/simple/app/src/main/AndroidManifest.xml b/java/dagger/example/gradle/android/simple/app/src/main/AndroidManifest.xml
deleted file mode 100644
index cc666d2..0000000
--- a/java/dagger/example/gradle/android/simple/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="dagger.example.gradle.android.simple">
-
-  <application
-    android:name=".SimpleApplication"
-    android:label="@string/appName"
-    android:theme="@style/Theme.AppCompat.Light">
-    <activity android:name=".SimpleActivity" android:exported="true">
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN" />
-        <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
-    </activity>
-  </application>
-</manifest>
diff --git a/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/BuildModule.java b/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/BuildModule.java
deleted file mode 100644
index f6317c2..0000000
--- a/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/BuildModule.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.gradle.android.simple;
-
-import static android.os.Build.MODEL;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-final class BuildModule {
-  @Provides
-  @Model
-  static String provideModel() {
-    return MODEL;
-  }
-}
diff --git a/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/Model.java b/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/Model.java
deleted file mode 100644
index 30a973e..0000000
--- a/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/Model.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.gradle.android.simple;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifies bindings relating to {@link android.os.Build#MODEL}. */
-@Qualifier
-@Retention(RUNTIME)
-@Documented
-@interface Model {}
diff --git a/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/SimpleActivity.java b/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/SimpleActivity.java
deleted file mode 100644
index 734590a..0000000
--- a/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/SimpleActivity.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.gradle.android.simple;
-
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.TextView;
-import dagger.Binds;
-import dagger.Module;
-import dagger.Subcomponent;
-import dagger.android.AndroidInjector;
-import dagger.android.support.DaggerAppCompatActivity;
-import dagger.multibindings.ClassKey;
-import dagger.multibindings.IntoMap;
-import javax.inject.Inject;
-
-/**
- * The main activity of the application.
- *
- * <p>It can be injected with any binding from both {@link SimpleActivityComponent} and {@link
- * SimpleApplication.SimpleComponent}.
- */
-public class SimpleActivity extends DaggerAppCompatActivity {
-  @Subcomponent
-  interface SimpleActivityComponent extends AndroidInjector<SimpleActivity> {
-
-    @Subcomponent.Factory
-    interface Factory extends AndroidInjector.Factory<SimpleActivity> {}
-  }
-
-  @Module(subcomponents = SimpleActivityComponent.class)
-  abstract static class InjectorModule {
-
-    @Binds
-    @IntoMap
-    @ClassKey(SimpleActivity.class)
-    abstract AndroidInjector.Factory<?> bind(SimpleActivityComponent.Factory factory);
-  }
-
-  private static final String TAG = SimpleActivity.class.getSimpleName();
-
-  @Inject @Model String model;
-
-  @Inject
-  void logInjection() {
-    Log.i(TAG, "Injecting");
-  }
-
-  @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-
-    setContentView(R.layout.activity_main);
-
-    TextView greeting = (TextView) findViewById(R.id.greeting);
-    String text = getResources().getString(R.string.welcome, model);
-    greeting.setText(text);
-  }
-}
diff --git a/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/SimpleApplication.java b/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/SimpleApplication.java
deleted file mode 100644
index e2e34ea..0000000
--- a/java/dagger/example/gradle/android/simple/app/src/main/java/dagger/example/gradle/android/simple/SimpleApplication.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.gradle.android.simple;
-
-import android.util.Log;
-import dagger.Component;
-import dagger.android.AndroidInjectionModule;
-import dagger.android.AndroidInjector;
-import dagger.android.DaggerApplication;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/**
- * A simple, skeletal application that demonstrates a dependency-injected application using the
- * utilities in {@code dagger.android}.
- */
-public class SimpleApplication extends DaggerApplication {
-  private static final String TAG = SimpleApplication.class.getSimpleName();
-
-  @Singleton
-  @Component(
-      modules = {
-        AndroidInjectionModule.class,
-        SimpleActivity.InjectorModule.class,
-        BuildModule.class
-      }
-  )
-  interface SimpleComponent extends AndroidInjector<SimpleApplication> {
-    @Component.Factory
-    interface Factory extends AndroidInjector.Factory<SimpleApplication> {}
-  }
-
-  @Inject
-  void logInjection() {
-    Log.i(TAG, "Injecting " + SimpleApplication.class.getSimpleName());
-  }
-
-  @Override
-  public void onCreate() {
-    super.onCreate();
-  }
-
-  @Override
-  protected AndroidInjector<SimpleApplication> applicationInjector() {
-    return DaggerSimpleApplication_SimpleComponent.factory().create(this);
-  }
-}
diff --git a/java/dagger/example/gradle/android/simple/app/src/main/res/layout/activity_main.xml b/java/dagger/example/gradle/android/simple/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index 18a547b..0000000
--- a/java/dagger/example/gradle/android/simple/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:background="@android:color/background_light">
-
-  <TextView
-    android:id="@+id/greeting"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_alignParentTop="true"
-    android:textColor="@android:color/primary_text_light"
-    />
-</RelativeLayout>
diff --git a/java/dagger/example/gradle/android/simple/app/src/main/res/values/strings.xml b/java/dagger/example/gradle/android/simple/app/src/main/res/values/strings.xml
deleted file mode 100644
index f45fd41..0000000
--- a/java/dagger/example/gradle/android/simple/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-  <string name="appName">Simple Dagger Android</string>
-  <string name="welcome">Hello, %s!</string>
-</resources>
diff --git a/java/dagger/example/gradle/android/simple/build.gradle b/java/dagger/example/gradle/android/simple/build.gradle
deleted file mode 100644
index 50f8f0b..0000000
--- a/java/dagger/example/gradle/android/simple/build.gradle
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-buildscript {
-    repositories {
-        google()
-        jcenter()
-    }
-    dependencies {
-        classpath 'com.android.tools.build:gradle:4.1.1'
-    }
-}
-
-allprojects {
-    repositories {
-      google()
-      jcenter()
-      mavenCentral()
-      mavenLocal()
-    }
-}
-
diff --git a/java/dagger/example/gradle/android/simple/gradle.properties b/java/dagger/example/gradle/android/simple/gradle.properties
deleted file mode 100644
index 2d8d1e4..0000000
--- a/java/dagger/example/gradle/android/simple/gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-android.useAndroidX=true
\ No newline at end of file
diff --git a/java/dagger/example/gradle/android/simple/gradle/wrapper/gradle-wrapper.jar b/java/dagger/example/gradle/android/simple/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/java/dagger/example/gradle/android/simple/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/java/dagger/example/gradle/android/simple/gradle/wrapper/gradle-wrapper.properties b/java/dagger/example/gradle/android/simple/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/java/dagger/example/gradle/android/simple/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/java/dagger/example/gradle/android/simple/gradlew b/java/dagger/example/gradle/android/simple/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/java/dagger/example/gradle/android/simple/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/java/dagger/example/gradle/android/simple/settings.gradle b/java/dagger/example/gradle/android/simple/settings.gradle
deleted file mode 100644
index c5a07bc..0000000
--- a/java/dagger/example/gradle/android/simple/settings.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-include ':app'
-rootProject.name='Simple Dagger Android'
\ No newline at end of file
diff --git a/java/dagger/example/gradle/simple/SimpleApplication.java b/java/dagger/example/gradle/simple/SimpleApplication.java
deleted file mode 100644
index 11552f8..0000000
--- a/java/dagger/example/gradle/simple/SimpleApplication.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 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.example.gradle.simple;
-
-import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** A simple, skeletal application that defines a simple component. */
-public class SimpleApplication {
-  static final class Foo {
-    @Inject Foo() {}
-  }
-
-  @Module
-  static final class SimpleModule {
-    @Provides
-    static Foo provideFoo() {
-      return new Foo();
-    }
-  }
-
-  @Singleton
-  @Component(modules = { SimpleModule.class })
-  interface SimpleComponent {
-    Foo foo();
-  }
-
-  public static void main(String[] args) {
-    Foo foo = DaggerSimpleApplication_SimpleComponent.create().foo();
-  }
-}
diff --git a/java/dagger/example/gradle/simple/build.gradle b/java/dagger/example/gradle/simple/build.gradle
deleted file mode 100644
index c9e59ef..0000000
--- a/java/dagger/example/gradle/simple/build.gradle
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-plugins {
-  id 'java'
-  id 'application'
-}
-
-repositories {
-  mavenCentral()
-  mavenLocal()
-}
-
-sourceSets {
-  main {
-    java {
-      srcDir '.'
-    }
-  }
-}
-
-dependencies {
-  implementation 'com.google.dagger:dagger:LOCAL-SNAPSHOT'
-  annotationProcessor 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
-}
-
-mainClassName = 'dagger.example.gradle.simple.SimpleApplication'
\ No newline at end of file
diff --git a/java/dagger/example/gradle/simple/gradle/wrapper/gradle-wrapper.jar b/java/dagger/example/gradle/simple/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/java/dagger/example/gradle/simple/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/java/dagger/example/gradle/simple/gradle/wrapper/gradle-wrapper.properties b/java/dagger/example/gradle/simple/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/java/dagger/example/gradle/simple/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/java/dagger/example/gradle/simple/gradlew b/java/dagger/example/gradle/simple/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/java/dagger/example/gradle/simple/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/java/dagger/example/spi/BUILD b/java/dagger/example/spi/BUILD
index bd889c3..84b4a87 100644
--- a/java/dagger/example/spi/BUILD
+++ b/java/dagger/example/spi/BUILD
@@ -15,20 +15,17 @@
 # Description:
 #   An example of the dagger.spi.BindingGraphPlugin usage
 
-load("@rules_java//java:defs.bzl", "java_plugin")
-
 package(default_visibility = ["//:src"])
 
 java_plugin(
     name = "binding-graph-visualizer",
     srcs = glob(["*.java"]),
     deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:graph",
+        "//java/dagger/model",
         "//java/dagger/spi",
         "@google_bazel_common//third_party/java/auto:service",
         "@google_bazel_common//third_party/java/error_prone:annotations",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/javapoet",
     ],
 )
diff --git a/java/dagger/grpc/server/BUILD b/java/dagger/grpc/server/BUILD
index d9a2f97..1c57807 100644
--- a/java/dagger/grpc/server/BUILD
+++ b/java/dagger/grpc/server/BUILD
@@ -1,17 +1,10 @@
 # A framework supporting Dagger-injected gRPC servers.
 
-load("@rules_java//java:defs.bzl", "java_library")
-load(
-    "//:build_defs.bzl",
-    "DOCLINT_HTML_AND_SYNTAX",
-    "DOCLINT_REFERENCES",
-    "POM_VERSION",
-)
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-
 package(default_visibility = ["//:src"])
 
+load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "DOCLINT_REFERENCES")
+load("//tools:maven.bzl", "pom_file", "POM_VERSION")
+
 ANNOTATIONS_SRCS = [
     "CallScoped.java",
     "ForGrpcService.java",
@@ -41,13 +34,12 @@
     exports = [":annotations"],
     deps = [
         "//:dagger_with_compiler",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
         "@google_bazel_common//third_party/java/auto:value",
         "@google_bazel_common//third_party/java/grpc:context",
         "@google_bazel_common//third_party/java/grpc:core",
         "@google_bazel_common//third_party/java/grpc:netty",
         "@google_bazel_common//third_party/java/grpc:protobuf",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/jsr330_inject",
         "@google_bazel_common//third_party/java/protobuf",
     ],
@@ -72,6 +64,8 @@
     srcs = glob(["*.java"]),
 )
 
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+
 javadoc_library(
     name = "javadoc",
     srcs = [":javadoc-srcs"],
diff --git a/java/dagger/grpc/server/README.md b/java/dagger/grpc/server/README.md
index a864f36..5fe8d5c 100644
--- a/java/dagger/grpc/server/README.md
+++ b/java/dagger/grpc/server/README.md
@@ -7,4 +7,4 @@
 
 It is in development, and is planned for open-source release as part of Dagger.
 
-See user documentation at https://dagger.dev/dev-guide/grpc.
+See user documentation at https://dagger.dev/grpc.
diff --git a/java/dagger/grpc/server/processor/BUILD b/java/dagger/grpc/server/processor/BUILD
index dd33651..ce02b06 100644
--- a/java/dagger/grpc/server/processor/BUILD
+++ b/java/dagger/grpc/server/processor/BUILD
@@ -1,14 +1,8 @@
-load("@rules_java//java:defs.bzl", "java_library", "java_plugin")
-load(
-    "//:build_defs.bzl",
-    "DOCLINT_HTML_AND_SYNTAX",
-    "POM_VERSION",
-)
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-
 package(default_visibility = ["//:src"])
 
+load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
+load("//tools:maven.bzl", "pom_file", "POM_VERSION")
+
 java_library(
     name = "processor",
     srcs = glob(["*.java"]),
@@ -17,14 +11,12 @@
     deps = [
         "//:dagger_with_compiler",
         "//java/dagger/grpc/server:annotations",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:io",
+        "@google_bazel_common//third_party/java/auto:common",
         "@google_bazel_common//third_party/java/auto:service",
         "@google_bazel_common//third_party/java/google_java_format",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/javapoet",
         "@google_bazel_common//third_party/java/jsr250_annotations",
-        "@maven//:com_google_auto_auto_common",
     ],
 )
 
@@ -47,6 +39,8 @@
     srcs = glob(["*.java"]),
 )
 
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+
 javadoc_library(
     name = "javadoc",
     srcs = [":javadoc-srcs"],
diff --git a/java/dagger/grpc/server/processor/GrpcServiceProcessor.java b/java/dagger/grpc/server/processor/GrpcServiceProcessor.java
index 9b74454..e361fdb 100644
--- a/java/dagger/grpc/server/processor/GrpcServiceProcessor.java
+++ b/java/dagger/grpc/server/processor/GrpcServiceProcessor.java
@@ -40,7 +40,7 @@
 /**
  * Generates code from types annotated with {@link GrpcService @GrpcService}.
  *
- * @see <a href="https://dagger.dev/dev-guide/grpc">https://dagger.dev/dev-guide/grpc</a>
+ * @see <a href="https://dagger.dev/grpc">https://dagger.dev/grpc</a>
  */
 @AutoService(Processor.class)
 public class GrpcServiceProcessor extends BasicAnnotationProcessor implements ProcessingStep {
diff --git a/java/dagger/hilt/BUILD b/java/dagger/hilt/BUILD
deleted file mode 100644
index 94af18a..0000000
--- a/java/dagger/hilt/BUILD
+++ /dev/null
@@ -1,240 +0,0 @@
-# Copyright (C) 2020 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.
-
-load("//tools:maven.bzl", "gen_maven_artifact")
-load("//:build_defs.bzl", "POM_VERSION_ALPHA")
-
-# Description:
-#   A library that wraps the Dagger API to make DI usage and testing easier.
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "install_in",
-    srcs = ["InstallIn.java"],
-    exported_plugins = [
-        "//java/dagger/hilt/processor/internal/aggregateddeps:plugin",
-    ],
-    exports = [
-        "//java/dagger/hilt/processor/internal/aggregateddeps:annotation",
-    ],
-    deps = [
-        ":generates_root_input",
-        ":package_info",
-    ],
-)
-
-java_library(
-    name = "entry_point",
-    srcs = [
-        "EntryPoint.java",
-        "EntryPoints.java",
-    ],
-    exported_plugins = [
-        # This is required so that we can fail if @InstallIn is missing.
-        # TODO(bcorso): Consider using a separate processor to validate @EntryPoint.
-        "//java/dagger/hilt/processor/internal/aggregateddeps:plugin",
-    ],
-    deps = [
-        ":generates_root_input",
-        ":package_info",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:generated_component",
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-    ],
-)
-
-java_library(
-    name = "generates_root_input",
-    srcs = [
-        "GeneratesRootInput.java",
-    ],
-    exported_plugins = [
-        "//java/dagger/hilt/processor/internal/generatesrootinput:processor",
-    ],
-    exports = [
-        "//java/dagger/hilt/internal/generatesrootinput",
-    ],
-    deps = [
-        ":package_info",
-    ],
-)
-
-java_library(
-    name = "define_component",
-    srcs = [
-        "DefineComponent.java",
-    ],
-    exported_plugins = [
-        "//java/dagger/hilt/processor/internal/definecomponent:processor",
-    ],
-    exports = [
-        "//java/dagger/hilt/internal/definecomponent",
-    ],
-    deps = [
-        ":generates_root_input",
-        ":package_info",
-        "//java/dagger/hilt/internal/definecomponent",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-    deps = [
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-    ],
-)
-
-filegroup(
-    name = "javadoc-srcs",
-    srcs = [
-        ":hilt_android_filegroup",
-        ":hilt_android_testing_filegroup",
-        ":hilt_filegroup",
-        ":hilt_testing_filegroup",
-    ],
-)
-
-filegroup(
-    name = "hilt_filegroup",
-    srcs = glob(["*"]) + [
-        "//java/dagger/hilt/codegen:srcs_filegroup",
-        "//java/dagger/hilt/components:srcs_filegroup",
-        "//java/dagger/hilt/migration:srcs_filegroup",
-        "//java/dagger/hilt/internal:srcs_filegroup",
-        "//java/dagger/hilt/internal/aliasof:srcs_filegroup",
-        "//java/dagger/hilt/internal/definecomponent:srcs_filegroup",
-        "//java/dagger/hilt/internal/generatesrootinput:srcs_filegroup",
-    ],
-)
-
-filegroup(
-    name = "hilt_testing_filegroup",
-    srcs = [
-        "//java/dagger/hilt/testing:srcs_filegroup",
-    ],
-)
-
-filegroup(
-    name = "hilt_android_filegroup",
-    srcs = [
-        "//java/dagger/hilt/android:srcs_filegroup",
-        "//java/dagger/hilt/android/components:srcs_filegroup",
-        "//java/dagger/hilt/android/internal:srcs_filegroup",
-        "//java/dagger/hilt/android/internal/builders:srcs_filegroup",
-        "//java/dagger/hilt/android/internal/lifecycle:srcs_filegroup",
-        "//java/dagger/hilt/android/internal/managers:srcs_filegroup",
-        "//java/dagger/hilt/android/internal/migration:srcs_filegroup",
-        "//java/dagger/hilt/android/internal/modules:srcs_filegroup",
-        "//java/dagger/hilt/android/lifecycle:srcs_filegroup",
-        "//java/dagger/hilt/android/migration:srcs_filegroup",
-        "//java/dagger/hilt/android/plugin:srcs_filegroup",
-        "//java/dagger/hilt/android/qualifiers:srcs_filegroup",
-        "//java/dagger/hilt/android/scopes:srcs_filegroup",
-    ],
-)
-
-filegroup(
-    name = "hilt_android_testing_filegroup",
-    srcs = [
-        "//java/dagger/hilt/android/internal/testing:srcs_filegroup",
-        "//java/dagger/hilt/android/testing:srcs_filegroup",
-    ],
-)
-
-filegroup(
-    name = "hilt_processing_filegroup",
-    srcs = [
-        "//java/dagger/hilt/android/processor:srcs_filegroup",
-        "//java/dagger/hilt/android/processor/internal:srcs_filegroup",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:srcs_filegroup",
-        "//java/dagger/hilt/android/processor/internal/bindvalue:srcs_filegroup",
-        "//java/dagger/hilt/android/processor/internal/customtestapplication:srcs_filegroup",
-        "//java/dagger/hilt/android/processor/internal/uninstallmodules:srcs_filegroup",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:srcs_filegroup",
-        "//java/dagger/hilt/processor:srcs_filegroup",
-        "//java/dagger/hilt/processor/internal:srcs_filegroup",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:srcs_filegroup",
-        "//java/dagger/hilt/processor/internal/aliasof:srcs_filegroup",
-        "//java/dagger/hilt/processor/internal/definecomponent:srcs_filegroup",
-        "//java/dagger/hilt/processor/internal/disableinstallincheck:srcs_filegroup",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:srcs_filegroup",
-        "//java/dagger/hilt/processor/internal/originatingelement:srcs_filegroup",
-        "//java/dagger/hilt/processor/internal/root:srcs_filegroup",
-    ],
-)
-
-java_library(
-    name = "artifact-core-lib",
-    tags = ["maven_coordinates=com.google.dagger:hilt-core:" + POM_VERSION_ALPHA],
-    exports = [
-        ":define_component",
-        ":entry_point",
-        ":generates_root_input",
-        ":install_in",
-        ":package_info",
-        "//java/dagger:core",
-        "//java/dagger/hilt/components",
-        "//java/dagger/hilt/migration:alias_of",
-        "//java/dagger/hilt/migration:disable_install_in_check",
-    ],
-)
-
-gen_maven_artifact(
-    name = "artifact-core",
-    artifact_coordinates = "com.google.dagger:hilt-core:" + POM_VERSION_ALPHA,
-    artifact_name = "Hilt Core",
-    artifact_target = ":artifact-core-lib",
-    artifact_target_libs = [
-        "//java/dagger/hilt:define_component",
-        "//java/dagger/hilt:entry_point",
-        "//java/dagger/hilt:generates_root_input",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt:package_info",
-        "//java/dagger/hilt/codegen:originating_element",
-        "//java/dagger/hilt/codegen:package_info",
-        "//java/dagger/hilt/components",
-        "//java/dagger/hilt/components:package_info",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:generated_component",
-        "//java/dagger/hilt/internal:preconditions",
-        "//java/dagger/hilt/internal:unsafe_casts",
-        "//java/dagger/hilt/internal/aliasof",
-        "//java/dagger/hilt/internal/definecomponent",
-        "//java/dagger/hilt/internal/generatesrootinput",
-        "//java/dagger/hilt/migration:alias_of",
-        "//java/dagger/hilt/migration:disable_install_in_check",
-        "//java/dagger/hilt/migration:package_info",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:annotation",
-    ],
-    artifact_target_maven_deps = [
-        "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger",
-        "javax.inject:javax.inject",
-    ],
-    artifact_target_maven_deps_banned = [
-        "com.google.guava:guava",
-        "javax.annotation:jsr250-api",
-    ],
-    javadoc_exclude_packages = [
-        "dagger.hilt.internal",
-    ],
-    javadoc_root_packages = [
-        "dagger.hilt",
-    ],
-    javadoc_srcs = [
-        "//java/dagger/hilt:hilt_filegroup",
-    ],
-)
diff --git a/java/dagger/hilt/DefineComponent.java b/java/dagger/hilt/DefineComponent.java
deleted file mode 100644
index fcd572c..0000000
--- a/java/dagger/hilt/DefineComponent.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt;
-
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import dagger.hilt.internal.definecomponent.DefineComponentNoParent;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Defines a Hilt component.
- *
- * <p>Example defining a root component, {@code ParentComponent}:
- *
- * <pre><code>
- *   {@literal @}ParentScoped
- *   {@literal @}DefineComponent
- *   interface ParentComponent {}
- * </code></pre>
- *
- * <p>Example defining a child component, {@code ChildComponent}:
- *
- * <pre><code>
- *   {@literal @}ChildScoped
- *   {@literal @}DefineComponent(parent = ParentComponent.class)
- *   interface ChildComponent {}
- * </code></pre>
- */
-@Retention(CLASS)
-@Target(TYPE)
-@GeneratesRootInput
-public @interface DefineComponent {
-  /** Returns the parent of this component, if it exists. */
-  Class<?> parent() default DefineComponentNoParent.class;
-
-  /**
-   * Defines a builder for a Hilt component.
-   *
-   * <pre><code>
-   *   {@literal @}DefineComponent.Builder
-   *   interface ParentComponentBuilder {
-   *     ParentComponentBuilder seedData(SeedData seed);
-   *     ParentComponent build();
-   *   }
-   * </code></pre>
-   */
-  // TODO(bcorso): Consider making this a top-level class to hint that it doesn't need to be nested.
-  @Retention(CLASS)
-  @Target(TYPE)
-  @GeneratesRootInput
-  public @interface Builder {}
-}
diff --git a/java/dagger/hilt/EntryPoint.java b/java/dagger/hilt/EntryPoint.java
deleted file mode 100644
index e216e77..0000000
--- a/java/dagger/hilt/EntryPoint.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for marking an interface as an entry point into a generated component. This annotation
- * must be used with {@link dagger.hilt.InstallIn} to indicate which component(s) should have this
- * entry point. When assembling components, Hilt will make the indicated components extend the
- * interface marked with this annotation.
- *
- * <p>To use the annotated interface to access Dagger objects, use {@link dagger.hilt.EntryPoints}.
- *
- * <p>Example usage:
- *
- * <pre><code>
- *   {@literal @}EntryPoint
- *   {@literal @}InstallIn(SingletonComponent.class)
- *   public interface FooEntryPoint {
- *     Foo getFoo();
- *   }
- *
- *   Foo foo = EntryPoints.get(component, FooEntryPoint.class).getFoo();
- * </code></pre>
- *
- * @see <a href="https://dagger.dev/hilt/entry-points">Entry points</a>
- */
-@Retention(CLASS)
-@Target(ElementType.TYPE)
-@GeneratesRootInput
-public @interface EntryPoint {}
diff --git a/java/dagger/hilt/EntryPoints.java b/java/dagger/hilt/EntryPoints.java
deleted file mode 100644
index 32e2312..0000000
--- a/java/dagger/hilt/EntryPoints.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt;
-
-import dagger.hilt.internal.GeneratedComponent;
-import dagger.hilt.internal.GeneratedComponentManager;
-import javax.annotation.Nonnull;
-
-/** Static utility methods for accessing objects through entry points. */
-public final class EntryPoints {
-
-  /**
-   * Returns the entry point interface given a component or component manager. Note that this
-   * performs an unsafe cast and so callers should be sure that the given component/component
-   * manager matches the entry point interface that is given.
-   *
-   * @param component The Hilt-generated component instance. For convenience, also takes component
-   *     manager instances as well.
-   * @param entryPoint The interface marked with {@link dagger.hilt.EntryPoint}. The {@link
-   *     dagger.hilt.InstallIn} annotation on this entry point should match the component argument
-   *     above.
-   */
-  // Note that the input is not statically declared to be a Component or ComponentManager to make
-  // this method easier to use, since most code will use this with an Application or Activity type.
-  @Nonnull
-  public static <T> T get(Object component, Class<T> entryPoint) {
-    if (component instanceof GeneratedComponent) {
-      // Unsafe cast. There is no way for this method to know that the correct component was used.
-      return entryPoint.cast(component);
-    } else if (component instanceof GeneratedComponentManager) {
-      // Unsafe cast. There is no way for this method to know that the correct component was used.
-      return entryPoint.cast(((GeneratedComponentManager<?>) component).generatedComponent());
-    } else {
-      throw new IllegalStateException(
-          String.format(
-              "Given component holder %s does not implement %s or %s",
-              component.getClass(), GeneratedComponent.class, GeneratedComponentManager.class));
-    }
-  }
-
-  private EntryPoints() {}
-}
diff --git a/java/dagger/hilt/GeneratesRootInput.java b/java/dagger/hilt/GeneratesRootInput.java
deleted file mode 100644
index ffd786f..0000000
--- a/java/dagger/hilt/GeneratesRootInput.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/** For annotating annotations that generate input for the {@link GenerateComponents}. */
-// TODO(danysantiago): Rename to GenerateComponentsInput
-@Target(ElementType.ANNOTATION_TYPE)
-@Retention(RetentionPolicy.CLASS)
-public @interface GeneratesRootInput {}
diff --git a/java/dagger/hilt/InstallIn.java b/java/dagger/hilt/InstallIn.java
deleted file mode 100644
index 9148c82..0000000
--- a/java/dagger/hilt/InstallIn.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * An annotation that declares which component(s) the annotated class should be included in when
- * Hilt generates the components. This may only be used with classes annotated with
- * {@literal @}{@link dagger.Module} or {@literal @}{@link dagger.hilt.EntryPoint}.
- *
- * <p>Example usage for installing a module in the generated {@code ApplicationComponent}:
- *
- * <pre><code>
- *   {@literal @}Module
- *   {@literal @}InstallIn(SingletonComponent.class)
- *   public final class FooModule {
- *     {@literal @}Provides
- *     static Foo provideFoo() {
- *       return new Foo();
- *     }
- *   }
- * </code></pre>
- *
- * @see <a href="https://dagger.dev/hilt/modules">Hilt Modules</a>
- */
-@Retention(CLASS)
-@Target({ElementType.TYPE})
-@GeneratesRootInput
-public @interface InstallIn {
-  Class<?>[] value();
-}
diff --git a/java/dagger/hilt/README.md b/java/dagger/hilt/README.md
deleted file mode 100644
index 911e466..0000000
--- a/java/dagger/hilt/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Hilt
-
-Hilt provides a standard way to incorporate Dagger dependency injection into an
-Android application. For more information, see https://dagger.dev/hilt.
diff --git a/java/dagger/hilt/android/ActivityRetainedLifecycle.java b/java/dagger/hilt/android/ActivityRetainedLifecycle.java
deleted file mode 100644
index 5e2d7cd..0000000
--- a/java/dagger/hilt/android/ActivityRetainedLifecycle.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android;
-
-import android.app.Activity;
-import androidx.annotation.MainThread;
-import androidx.annotation.NonNull;
-
-/**
- * A <code>ActivityRetainedLifecycle</code> class is associated with the lifecycle of the {@link
- * dagger.hilt.android.components.ActivityRetainedComponent}.
- */
-public interface ActivityRetainedLifecycle {
-
-  /**
-   * Adds a new {@link OnClearedListener} for receiving a callback when the activity retained
-   * instances will no longer be needed and destroyed.
-   *
-   * @param listener The listener that should be added.
-   */
-  @MainThread
-  void addOnClearedListener(@NonNull OnClearedListener listener);
-
-  /**
-   * Removes a {@link OnClearedListener} previously added via {@link
-   * #addOnClearedListener(OnClearedListener)}.
-   *
-   * @param listener The listener that should be removed.
-   */
-  @MainThread
-  void removeOnClearedListener(@NonNull OnClearedListener listener);
-
-  /**
-   * Listener for receiving a callback for when the {@link
-   * dagger.hilt.android.components.ActivityRetainedComponent} will no longer be used and destroyed.
-   */
-  interface OnClearedListener {
-
-    /**
-     * Called when the activity retained instances will no longer be used and destroyed.
-     *
-     * <p>Specifically this will be invoked during {@link Activity#onDestroy()} when {@link
-     * Activity#isChangingConfigurations} is false.
-     */
-    void onCleared();
-  }
-}
diff --git a/java/dagger/hilt/android/AndroidEntryPoint.java b/java/dagger/hilt/android/AndroidEntryPoint.java
deleted file mode 100644
index 8c56116..0000000
--- a/java/dagger/hilt/android/AndroidEntryPoint.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Marks an Android component class to be setup for injection with the standard Hilt Dagger Android
- * components. Currently, this supports activities, fragments, views, services, and broadcast
- * receivers.
- *
- * <p>This annotation will generate a base class that the annotated class should extend, either
- * directly or via the Hilt Gradle Plugin. This base class will take care of injecting members into
- * the Android class as well as handling instantiating the proper Hilt components at the right point
- * in the lifecycle. The name of the base class will be "Hilt_<annotated class name>".
- *
- * <p>Example usage (with the Hilt Gradle Plugin):
- *
- * <pre><code>
- *   {@literal @}AndroidEntryPoint
- *   public final class FooActivity extends FragmentActivity {
- *     {@literal @}Inject Foo foo;
- *
- *     {@literal @}Override
- *     public void onCreate(Bundle savedInstanceState) {
- *       super.onCreate(savedInstanceState);  // The foo field is injected in super.onCreate()
- *     }
- *   }
- * </code></pre>
- *
- * <p>Example usage (without the Hilt Gradle Plugin):
- *
- * <pre><code>
- *   {@literal @}AndroidEntryPoint(FragmentActivity.class)
- *   public final class FooActivity extends Hilt_FooActivity {
- *     {@literal @}Inject Foo foo;
- *
- *     {@literal @}Override
- *     public void onCreate(Bundle savedInstanceState) {
- *       super.onCreate(savedInstanceState);  // The foo field is injected in super.onCreate()
- *     }
- *   }
- * </code></pre>
- *
- * @see HiltAndroidApp
- */
-@Target({ElementType.TYPE})
-@GeneratesRootInput
-public @interface AndroidEntryPoint {
-
-  /**
-   * The base class for the generated Hilt class. When applying the Hilt Gradle Plugin this value
-   * is not necessary and will be inferred from the current superclass.
-   */
-  Class<?> value() default Void.class;
-}
diff --git a/java/dagger/hilt/android/AndroidManifest.xml b/java/dagger/hilt/android/AndroidManifest.xml
deleted file mode 100644
index 3a7b087..0000000
--- a/java/dagger/hilt/android/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
- Copyright (C) 2020 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android">
-  <uses-sdk android:minSdkVersion="14" />
-</manifest>
diff --git a/java/dagger/hilt/android/BUILD b/java/dagger/hilt/android/BUILD
deleted file mode 100644
index 47d7e67..0000000
--- a/java/dagger/hilt/android/BUILD
+++ /dev/null
@@ -1,193 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   A library based on Hilt that provides standard components and automated injection for Android.
-load("//:build_defs.bzl", "POM_VERSION_ALPHA")
-load("//tools:maven.bzl", "gen_maven_artifact")
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "android_entry_point",
-    srcs = [
-        "AndroidEntryPoint.java",
-        "WithFragmentBindings.java",
-    ],
-    exported_plugins = [
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:plugin",
-    ],
-    exports = [
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/internal/builders",
-        "//java/dagger/hilt/android/internal/managers",
-        "//java/dagger/hilt/android/internal/managers:component_supplier",
-        "//java/dagger/hilt/android/internal/modules",
-        "//java/dagger/hilt/android/lifecycle",
-        "//java/dagger/hilt/codegen:originating_element",
-        "//java/dagger/hilt/internal:component_entry_point",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:generated_entry_point",
-        "//java/dagger/hilt/internal:preconditions",
-        "@maven//:androidx_annotation_annotation",
-        "@maven//:androidx_fragment_fragment",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-android_library(
-    name = "hilt_android_app",
-    srcs = ["HiltAndroidApp.java"],
-    exported_plugins = [
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:plugin",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:validation_plugin",
-        "//java/dagger/hilt/processor/internal/root:plugin",
-    ],
-    exports = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/internal/managers",
-        "//java/dagger/hilt/android/internal/managers:component_supplier",
-        "//java/dagger/hilt/android/internal/modules",
-        "//java/dagger/hilt/codegen:originating_element",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:generated_component",
-        "//java/dagger/hilt/internal:generated_entry_point",
-        "//java/dagger/hilt/migration:disable_install_in_check",
-        "@maven//:androidx_annotation_annotation",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-android_library(
-    name = "entry_point_accessors",
-    srcs = ["EntryPointAccessors.java"],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:entry_point",
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-        "@maven//:androidx_fragment_fragment",
-    ],
-)
-
-android_library(
-    name = "activity_retained_lifecycle",
-    srcs = ["ActivityRetainedLifecycle.java"],
-    deps = [
-        ":package_info",
-        "@maven//:androidx_annotation_annotation",
-    ],
-)
-
-android_library(
-    name = "artifact-lib",
-    tags = ["maven_coordinates=com.google.dagger:hilt-android:" + POM_VERSION_ALPHA],
-    exports = [
-        ":android_entry_point",
-        ":entry_point_accessors",
-        ":hilt_android_app",
-        ":package_info",
-        "//java/dagger/hilt:artifact-core-lib",
-        "//java/dagger/hilt/android/migration:optional_inject",
-        "//java/dagger/lint:lint-android-artifact-lib",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-    deps = [
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-    ],
-)
-
-gen_maven_artifact(
-    name = "artifact",
-    artifact_coordinates = "com.google.dagger:hilt-android:" + POM_VERSION_ALPHA,
-    artifact_name = "Hilt Android",
-    artifact_target = ":artifact-lib",
-    artifact_target_libs = [
-        ":entry_point_accessors",
-        "//java/dagger/hilt/android:activity_retained_lifecycle",
-        "//java/dagger/hilt/android:android_entry_point",
-        "//java/dagger/hilt/android:hilt_android_app",
-        "//java/dagger/hilt/android:package_info",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/components:view_model_component",
-        "//java/dagger/hilt/android/components:package_info",
-        "//java/dagger/hilt/android/internal",
-        "//java/dagger/hilt/android/internal/builders",
-        "//java/dagger/hilt/android/internal/lifecycle",
-        "//java/dagger/hilt/android/internal/managers",
-        "//java/dagger/hilt/android/internal/managers:component_supplier",
-        "//java/dagger/hilt/android/internal/migration:injected_by_hilt",
-        "//java/dagger/hilt/android/internal/modules",
-        "//java/dagger/hilt/android/lifecycle",
-        "//java/dagger/hilt/android/migration:optional_inject",
-        "//java/dagger/hilt/android/migration:package_info",
-        "//java/dagger/hilt/android/qualifiers",
-        "//java/dagger/hilt/android/qualifiers:package_info",
-        "//java/dagger/hilt/android/scopes",
-        "//java/dagger/hilt/android/scopes:activity_retained_scoped",
-        "//java/dagger/hilt/android/scopes:view_model_scoped",
-        "//java/dagger/hilt/android/scopes:package_info",
-        "//java/dagger/hilt/internal:component_entry_point",
-        "//java/dagger/hilt/internal:generated_entry_point",
-    ],
-    artifact_target_maven_deps = [
-        "androidx.activity:activity",
-        "androidx.annotation:annotation",
-        "androidx.fragment:fragment",
-        "androidx.lifecycle:lifecycle-viewmodel",
-        "androidx.lifecycle:lifecycle-viewmodel-savedstate",
-        "androidx.savedstate:savedstate",
-        "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger-lint-aar",
-        "com.google.dagger:dagger",
-        "com.google.dagger:hilt-core",
-        "javax.inject:javax.inject",
-    ],
-    artifact_target_maven_deps_banned = [
-        "com.google.guava:guava",
-        "javax.annotation:jsr250-api",
-    ],
-    javadoc_android_api_level = 30,
-    javadoc_exclude_packages = [
-        "dagger.hilt.android.internal",
-    ],
-    javadoc_root_packages = [
-        "dagger.hilt.android",
-    ],
-    javadoc_srcs = [
-        "//java/dagger/hilt:hilt_android_filegroup",
-    ],
-    manifest = "AndroidManifest.xml",
-    packaging = "aar",
-    proguard_specs = [
-        "//java/dagger/hilt/android/lifecycle:proguard-rules.pro",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/EntryPointAccessors.java b/java/dagger/hilt/android/EntryPointAccessors.java
deleted file mode 100644
index 6145af1..0000000
--- a/java/dagger/hilt/android/EntryPointAccessors.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android;
-
-import android.app.Activity;
-import android.content.Context;
-import androidx.fragment.app.Fragment;
-import android.view.View;
-import dagger.hilt.EntryPoints;
-import javax.annotation.Nonnull;
-
-/** Static utility methods for dealing with entry points for standard Android components. */
-public final class EntryPointAccessors {
-
-  /**
-   * Returns the entry point interface from an application. The context can be any context derived
-   * from the application context. May only be used with entry point interfaces installed in the
-   * ApplicationComponent.
-   */
-  @Nonnull
-  public static <T> T fromApplication(Context context, Class<T> entryPoint) {
-    return EntryPoints.get(context.getApplicationContext(), entryPoint);
-  }
-
-  /**
-   * Returns the entry point interface from an activity. May only be used with entry point
-   * interfaces installed in the ActivityComponent.
-   */
-  @Nonnull
-  public static <T> T fromActivity(Activity activity, Class<T> entryPoint) {
-    return EntryPoints.get(activity, entryPoint);
-  }
-
-  /**
-   * Returns the entry point interface from a fragment. May only be used with entry point interfaces
-   * installed in the FragmentComponent.
-   */
-  @Nonnull
-  public static <T> T fromFragment(Fragment fragment, Class<T> entryPoint) {
-    return EntryPoints.get(fragment, entryPoint);
-  }
-
-  /**
-   * Returns the entry point interface from a view. May only be used with entry point interfaces
-   * installed in the ViewComponent or ViewNoFragmentComponent.
-   */
-  @Nonnull
-  public static <T> T fromView(View view, Class<T> entryPoint) {
-    return EntryPoints.get(view, entryPoint);
-  }
-
-  private EntryPointAccessors() {}
-}
diff --git a/java/dagger/hilt/android/HiltAndroidApp.java b/java/dagger/hilt/android/HiltAndroidApp.java
deleted file mode 100644
index 0c2ca0f..0000000
--- a/java/dagger/hilt/android/HiltAndroidApp.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for marking the {@link android.app.Application} class where the Dagger components
- * should be generated. Since all components will be built in the same compilation as the annotated
- * application, all modules and entry points that should be installed in the component need to be
- * transitive compilation dependencies of the annotated application.
- *
- * <p>Usage of this annotation is similar to {@link dagger.hilt.android.AndroidEntryPoint} with the
- * only difference being that it only works on application classes and additionally triggers Dagger
- * component generation.
- *
- * <p>This annotation will generate a base class that the annotated class should extend, either
- * directly or via the Hilt Gradle Plugin. This base class will take care of injecting members into
- * the Android class as well as handling instantiating the proper Hilt components at the right point
- * in the lifecycle. The name of the base class will be "Hilt_<annotated class name>".
- *
- * <p>Example usage (with the Hilt Gradle Plugin):
- *
- * <pre><code>
- *   {@literal @}HiltAndroidApp
- *   public final class FooApplication extends Application {
- *     {@literal @}Inject Foo foo;
- *
- *     {@literal @}Override
- *     public void onCreate() {
- *       super.onCreate();  // The foo field is injected in super.onCreate()
- *     }
- *   }
- * </code></pre>
- *
- * <p>Example usage (without the Hilt Gradle Plugin):
- *
- * <pre><code>
- *   {@literal @}HiltAndroidApp(Application.class)
- *   public final class FooApplication extends Hilt_FooApplication {
- *     {@literal @}Inject Foo foo;
- *
- *     {@literal @}Override
- *     public void onCreate() {
- *       super.onCreate();  // The foo field is injected in super.onCreate()
- *     }
- *   }
- * </code></pre>
- *
- * @see AndroidEntryPoint
- */
-// Set the retention to RUNTIME because we check it via reflection in the HiltAndroidRule.
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@GeneratesRootInput
-public @interface HiltAndroidApp {
-  /**
-   * The base class for the generated Hilt application. When applying the Hilt Gradle Plugin this
-   * value is not necessary and will be inferred from the current superclass.
-   */
-  // TODO(erichang): It would be nice to make this Class<? extends Application> but then the default
-  // would have to be Application which would make the default actually valid even without the
-  // plugin. Maybe that is a good thing...but might be better to have users be explicit about the
-  // base class they want.
-  Class<?> value() default Void.class;
-}
diff --git a/java/dagger/hilt/android/WithFragmentBindings.java b/java/dagger/hilt/android/WithFragmentBindings.java
deleted file mode 100644
index 2b02498..0000000
--- a/java/dagger/hilt/android/WithFragmentBindings.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Makes a View annotated with {@link AndroidEntryPoint} have access to fragment bindings.
- *
- * <p>By default, views annotated with {@literal @}AndroidEntryPoint do not have access to fragment
- * bindings and must use this annotation if fragment bindings are required. When this annotation is
- * used, this view must always be attached through a fragment.
- */
-@Target({ElementType.TYPE})
-public @interface WithFragmentBindings {}
diff --git a/java/dagger/hilt/android/components/ActivityComponent.java b/java/dagger/hilt/android/components/ActivityComponent.java
deleted file mode 100644
index 78f48cc..0000000
--- a/java/dagger/hilt/android/components/ActivityComponent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.components;
-
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.scopes.ActivityScoped;
-
-/** A Hilt component that has the lifetime of the activity. */
-@ActivityScoped
-@DefineComponent(parent = ActivityRetainedComponent.class)
-public interface ActivityComponent {}
diff --git a/java/dagger/hilt/android/components/ActivityRetainedComponent.java b/java/dagger/hilt/android/components/ActivityRetainedComponent.java
deleted file mode 100644
index b3c340e..0000000
--- a/java/dagger/hilt/android/components/ActivityRetainedComponent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.components;
-
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.scopes.ActivityRetainedScoped;
-import dagger.hilt.components.SingletonComponent;
-
-/** A Hilt component that has the lifetime of a configuration surviving activity. */
-@ActivityRetainedScoped
-@DefineComponent(parent = SingletonComponent.class)
-public interface ActivityRetainedComponent {}
diff --git a/java/dagger/hilt/android/components/BUILD b/java/dagger/hilt/android/components/BUILD
deleted file mode 100644
index 3a307d1..0000000
--- a/java/dagger/hilt/android/components/BUILD
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Hilt Android components
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "components",
-    srcs = [
-        "ActivityComponent.java",
-        "ActivityRetainedComponent.java",
-        "FragmentComponent.java",
-        "ServiceComponent.java",
-        "ViewComponent.java",
-        "ViewWithFragmentComponent.java",
-    ],
-    exports = [
-        "//java/dagger/hilt/components",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:define_component",
-        "//java/dagger/hilt/android/scopes",
-        "//java/dagger/hilt/android/scopes:activity_retained_scoped",
-        "//java/dagger/hilt/components",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-    ],
-)
-
-android_library(
-    name = "view_model_component",
-    srcs = ["ViewModelComponent.java"],
-    deps = [
-        ":components",
-        ":package_info",
-        "//java/dagger/hilt:define_component",
-        "//java/dagger/hilt/android/scopes:view_model_scoped",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/components/FragmentComponent.java b/java/dagger/hilt/android/components/FragmentComponent.java
deleted file mode 100644
index 6b088e6..0000000
--- a/java/dagger/hilt/android/components/FragmentComponent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.components;
-
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.scopes.FragmentScoped;
-
-/** A Hilt component that has the lifetime of the fragment. */
-@FragmentScoped
-@DefineComponent(parent = ActivityComponent.class)
-public interface FragmentComponent {}
diff --git a/java/dagger/hilt/android/components/ServiceComponent.java b/java/dagger/hilt/android/components/ServiceComponent.java
deleted file mode 100644
index 0a3f6ea..0000000
--- a/java/dagger/hilt/android/components/ServiceComponent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.components;
-
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.scopes.ServiceScoped;
-import dagger.hilt.components.SingletonComponent;
-
-/** A Hilt component that has the lifetime of the service. */
-@ServiceScoped
-@DefineComponent(parent = SingletonComponent.class)
-public interface ServiceComponent {}
diff --git a/java/dagger/hilt/android/components/ViewComponent.java b/java/dagger/hilt/android/components/ViewComponent.java
deleted file mode 100644
index 1f5b420..0000000
--- a/java/dagger/hilt/android/components/ViewComponent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.components;
-
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.scopes.ViewScoped;
-
-/** A Hilt component that has the lifetime of the view. */
-@ViewScoped
-@DefineComponent(parent = ActivityComponent.class)
-public interface ViewComponent {}
diff --git a/java/dagger/hilt/android/components/ViewModelComponent.java b/java/dagger/hilt/android/components/ViewModelComponent.java
deleted file mode 100644
index 2ba2133..0000000
--- a/java/dagger/hilt/android/components/ViewModelComponent.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.components;
-
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.scopes.ViewModelScoped;
-
-/**
- * A Hilt component that has the lifetime of a single {@link androidx.lifecycle.ViewModel}.
- *
- * <p>This Hilt component is the source of {@link
- * dagger.hilt.android.lifecycle.HiltViewModel}-annotated {@link androidx.lifecycle.ViewModel}s
- * used by the {@link dagger.hilt.android.lifecycle.HiltViewModelFactory}. It contains a default
- * binding for the {@link androidx.lifecycle.SavedStateHandle} associated with the {@code
- * ViewModel} that can be used by other dependencies provided by the component.
- *
- * <p>Dependencies available in the {@link dagger.hilt.components.SingletonComponent} and {@link
- * ActivityRetainedComponent} are also available in this component since it is a child of {@code
- * ActivityRetainedComponent}.
- *
- * <p>Example usage:
- *
- * <pre>
- * &#64;Module
- * &#64;InstallIn(ViewModelComponent.class)
- * public final class ViewModelMovieModule {
- *     &#64;Provides
- *     public static MovieRepository provideRepo(SavedStateHandle handle) {
- *         return new MovieRepository(handle.getString("movie-id"));
- *     }
- * }
- * </pre>
- *
- * <p>Dependencies in the {@code ViewModelComponent} can be scoped using the {@link ViewModelScoped}
- * annotation. This allows for a single instance of a dependency to be provided across the
- * dependencies of a single {@link dagger.hilt.android.lifecycle.HiltViewModel}-annotated {@code
- * ViewModel}.
- *
- * @see dagger.hilt.android.lifecycle.HiltViewModel
- * @see dagger.hilt.android.scopes.ViewModelScoped
- */
-@ViewModelScoped
-@DefineComponent(parent = ActivityRetainedComponent.class)
-public interface ViewModelComponent {}
diff --git a/java/dagger/hilt/android/components/ViewWithFragmentComponent.java b/java/dagger/hilt/android/components/ViewWithFragmentComponent.java
deleted file mode 100644
index be5f2e8..0000000
--- a/java/dagger/hilt/android/components/ViewWithFragmentComponent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.components;
-
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.scopes.ViewScoped;
-
-/** A Hilt component that has the lifetime of the view. */
-@ViewScoped
-@DefineComponent(parent = FragmentComponent.class)
-public interface ViewWithFragmentComponent {}
diff --git a/java/dagger/hilt/android/components/package-info.java b/java/dagger/hilt/android/components/package-info.java
deleted file mode 100644
index 9ac3686..0000000
--- a/java/dagger/hilt/android/components/package-info.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains Hilt's built-in {@link dagger.Component}s for Android.
- *
- * @see <a href="https://dagger.dev/hilt/components.md">Hilt Components</a>
- */
-package dagger.hilt.android.components;
diff --git a/java/dagger/hilt/android/example/BUILD b/java/dagger/hilt/android/example/BUILD
deleted file mode 100644
index 2a4c194..0000000
--- a/java/dagger/hilt/android/example/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2017 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.
-#
-# Description:
-#   A skeletal application that demonstrates wiring for an injected Application and Activity.
-
-package(default_visibility = ["//:src"])
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(
-        ["**/*"],
-        # Exclude Gradle build folder to enable working along side Bazel
-        exclude = ["**/build/**"],
-    ),
-)
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/build.gradle b/java/dagger/hilt/android/example/gradle/simple/app/build.gradle
deleted file mode 100644
index b3687ee..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/build.gradle
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-apply plugin: 'com.android.application'
-apply plugin: 'dagger.hilt.android.plugin'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        applicationId "dagger.hilt.android.example.gradle.simple"
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-        testInstrumentationRunner "dagger.hilt.android.example.gradle.simple.SimpleEmulatorTestRunner"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-    testOptions {
-        unitTests.includeAndroidResources = true
-    }
-    sourceSets {
-        String sharedTestDir = 'src/sharedTest/java'
-        test {
-            java.srcDirs += sharedTestDir
-        }
-        androidTest {
-            java.srcDirs += sharedTestDir
-        }
-    }
-}
-
-dependencies {
-  implementation project(':feature')
-  implementation 'androidx.appcompat:appcompat:1.2.0'
-  implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-  annotationProcessor 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'
-
-  testImplementation 'com.google.truth:truth:1.0.1'
-  testImplementation 'junit:junit:4.13'
-  testImplementation 'org.robolectric:robolectric:4.5-alpha-3'
-  testImplementation 'androidx.core:core:1.3.2'
-  testImplementation 'androidx.test.ext:junit:1.1.2'
-  testImplementation 'androidx.test:runner:1.3.0'
-  testImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
-  testAnnotationProcessor 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'
-
-  androidTestImplementation 'com.google.truth:truth:1.0.1'
-  androidTestImplementation 'junit:junit:4.13'
-  androidTestImplementation 'androidx.test.ext:junit:1.1.2'
-  androidTestImplementation 'androidx.test:runner:1.3.0'
-  androidTestImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
-  androidTestAnnotationProcessor 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'
-
-  // To help us catch usages of Guava APIs for Java 8 in the '-jre' variant.
-  annotationProcessor'com.google.guava:guava:28.1-android'
-  testAnnotationProcessor'com.google.guava:guava:28.1-android'
-  androidTestAnnotationProcessor'com.google.guava:guava:28.1-android'
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SettingsActivityEmulatorTest.java b/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SettingsActivityEmulatorTest.java
deleted file mode 100644
index 28a7223..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SettingsActivityEmulatorTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.android.testing.UninstallModules;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** A simple test using Hilt. */
-@UninstallModules(ModelModule.class)
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class SettingsActivityEmulatorTest {
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @BindValue @Model String fakeModel = "FakeModel";
-
-  @Inject @Model String injectedModel;
-
-  @Test
-  public void testInjectedModel() throws Exception {
-    assertThat(injectedModel).isNull();
-    rule.inject();
-    assertThat(injectedModel).isEqualTo("FakeModel");
-  }
-
-  @Test
-  public void testActivityInject() throws Exception {
-    try (ActivityScenario<SettingsActivity> scenario =
-        ActivityScenario.launch(SettingsActivity.class)) {
-      scenario.onActivity(
-          activity ->
-              assertThat(activity.greeter.greet())
-                  .isEqualTo("ProdUser, you are on build FakeModel."));
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SimpleActivityEmulatorTest.java b/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SimpleActivityEmulatorTest.java
deleted file mode 100644
index cbf8f7f..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SimpleActivityEmulatorTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.android.testing.UninstallModules;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** A simple test using Hilt. */
-@UninstallModules(UserNameModule.class)
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class SimpleActivityEmulatorTest {
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @BindValue @UserName String fakeUserName = "FakeUser";
-
-  @Inject @UserName String injectedUserName;
-
-  @Test
-  public void testInjectedUserName() throws Exception {
-    assertThat(injectedUserName).isNull();
-    rule.inject();
-    assertThat(injectedUserName).isEqualTo("FakeUser");
-  }
-
-  @Test
-  public void testActivityInject() throws Exception {
-    try (ActivityScenario<SimpleActivity> scenario =
-        ActivityScenario.launch(SimpleActivity.class)) {
-      scenario.onActivity(
-          activity -> assertThat(activity.greeter.greet()).isEqualTo("Hello, FakeUser!"));
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SimpleEmulatorTestRunner.java b/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SimpleEmulatorTestRunner.java
deleted file mode 100644
index daf046b..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/androidTest/java/dagger/hilt/android/example/gradle/simple/SimpleEmulatorTestRunner.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import android.app.Application;
-import android.content.Context;
-import androidx.test.runner.AndroidJUnitRunner;
-import dagger.hilt.android.testing.HiltTestApplication;
-
-/** A custom runner to setup the emulator application class for tests. */
-public final class SimpleEmulatorTestRunner extends AndroidJUnitRunner {
-
-  @Override
-  public Application newApplication(ClassLoader cl, String className, Context context)
-      throws ClassNotFoundException, IllegalAccessException, InstantiationException {
-    return super.newApplication(cl, HiltTestApplication.class.getName(), context);
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/debug/AndroidManifest.xml b/java/dagger/hilt/android/example/gradle/simple/app/src/debug/AndroidManifest.xml
deleted file mode 100644
index 86460d8..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/debug/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="dagger.hilt.android.example.gradle.simple">
-
-  <application>
-    <activity
-        android:name=".Injection1Test$TestActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="false" />
-    <activity
-        android:name=".Injection2Test$TestActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="false"/>
-    <activity
-        android:name=".ActivityScenarioRuleTest$TestActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="false"/>
-  </application>
-</manifest>
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/AndroidManifest.xml b/java/dagger/hilt/android/example/gradle/simple/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 662c5b4..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="dagger.hilt.android.example.gradle.simple">
-
-  <application android:name=".SimpleApplication" android:label="@string/appName">
-    <activity
-        android:name=".SimpleActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="true">
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN" />
-        <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
-    </activity>
-    <activity
-        android:name=".SettingsActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="false">
-    </activity>
-  </application>
-</manifest>
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/Model.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/Model.java
deleted file mode 100644
index b4aec95..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/Model.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifies bindings relating to {@link android.os.Build#MODEL}. */
-@Qualifier
-@Retention(RUNTIME)
-@Documented
-@interface Model {}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/ModelModule.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/ModelModule.java
deleted file mode 100644
index d933c81..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/ModelModule.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static android.os.Build.MODEL;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.components.SingletonComponent;
-
-@Module
-@InstallIn(SingletonComponent.class)
-final class ModelModule {
-  @Provides
-  @Model
-  static String provideModel() {
-    return MODEL;
-  }
-
-  private ModelModule() {}
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SettingsActivity.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SettingsActivity.java
deleted file mode 100644
index f508e48..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SettingsActivity.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import android.os.Bundle;
-import android.widget.TextView;
-import androidx.appcompat.app.AppCompatActivity;
-import dagger.hilt.android.AndroidEntryPoint;
-import javax.inject.Inject;
-
-/** The settings activity of the application. */
-@AndroidEntryPoint
-public class SettingsActivity extends AppCompatActivity {
-  private static final String TAG = SettingsActivity.class.getSimpleName();
-
-  @Inject SettingsGreeter greeter;
-
-  @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-
-    setContentView(R.layout.activity_settings);
-
-    ((TextView) findViewById(R.id.settings_greeting)).setText(greeter.greet());
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SettingsGreeter.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SettingsGreeter.java
deleted file mode 100644
index 4f8ab14..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SettingsGreeter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import android.app.Activity;
-import javax.inject.Inject;
-
-/** A class that returns a greeting for {@link SettingsActivity}. */
-final class SettingsGreeter {
-  private final Activity activity;
-  private final String userName;
-  private final String model;
-
-  @Inject
-  SettingsGreeter(Activity activity, @UserName String userName, @Model String model) {
-    this.activity = activity;
-    this.userName = userName;
-    this.model = model;
-  }
-
-  public String greet() {
-    return activity.getResources().getString(R.string.settings_welcome, userName, model);
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleActivity.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleActivity.java
deleted file mode 100644
index 70e2e57..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleActivity.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.widget.Button;
-import android.widget.TextView;
-import androidx.appcompat.app.AppCompatActivity;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.example.gradle.simple.feature.FeatureActivity;
-import javax.inject.Inject;
-
-/** The main activity of the application. */
-@AndroidEntryPoint
-public class SimpleActivity extends AppCompatActivity {
-  private static final String TAG = SimpleActivity.class.getSimpleName();
-
-  @Inject SimpleGreeter greeter;
-
-  @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-
-    setContentView(R.layout.activity_main);
-
-    ((TextView) findViewById(R.id.greeting)).setText(greeter.greet());
-
-    Button featureButton = (Button) findViewById(R.id.goto_feature);
-    featureButton.setOnClickListener(
-        view -> startActivity(new Intent(this, FeatureActivity.class)));
-
-    Button settingsButton = (Button) findViewById(R.id.goto_settings);
-    settingsButton.setOnClickListener(
-        view -> startActivity(new Intent(this, SettingsActivity.class)));
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleApplication.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleApplication.java
deleted file mode 100644
index a163d8c..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleApplication.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import android.app.Application;
-import dagger.hilt.android.HiltAndroidApp;
-import javax.inject.Inject;
-
-/**
- * A simple, skeletal application that demonstrates a dependency-injected application using the
- * utilities in {@code Hilt} in Android.
- */
-@HiltAndroidApp
-public class SimpleApplication extends Application {
-
-  // Shows that we can inject SingletonComponent bindings into an application.
-  @Inject @Model String model;
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleGreeter.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleGreeter.java
deleted file mode 100644
index 6c35600..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/SimpleGreeter.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import android.app.Activity;
-import javax.inject.Inject;
-
-/** A class that returns a greeting for {@link SimpleActivity}. */
-final class SimpleGreeter {
-  private final Activity activity;
-  private final String userName;
-
-  @Inject
-  SimpleGreeter(Activity activity, @UserName String userName) {
-    this.activity = activity;
-    this.userName = userName;
-  }
-
-  public String greet() {
-    return activity.getResources().getString(R.string.welcome, userName);
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/UserName.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/UserName.java
deleted file mode 100644
index 173b163..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/UserName.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifies bindings relating to the user name. */
-@Qualifier
-@Retention(RUNTIME)
-@Documented
-@interface UserName {}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/UserNameModule.java b/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/UserNameModule.java
deleted file mode 100644
index 3969b73..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/java/dagger/hilt/android/example/gradle/simple/UserNameModule.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-
-@Module
-@InstallIn(ActivityComponent.class)
-final class UserNameModule {
-  @UserName
-  @Provides
-  static String provideUserName() {
-    return "ProdUser";
-  }
-
-  private UserNameModule() {}
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/layout/activity_main.xml b/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index 8a23af5..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:background="@android:color/background_light">
-
-  <TextView
-    android:id="@+id/greeting"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_alignParentTop="true"
-    android:textColor="@android:color/primary_text_light"
-    />
-
-  <Button
-    android:id="@+id/goto_settings"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_below="@id/greeting"
-    android:text="@string/navigateToSettings"
-    />
-
-  <Button
-    android:id="@+id/goto_feature"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_below="@id/goto_settings"
-    android:text="@string/navigateToFeature"
-    />
-</RelativeLayout>
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/layout/activity_settings.xml b/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/layout/activity_settings.xml
deleted file mode 100644
index 466856c..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/layout/activity_settings.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout
-     xmlns:android="http://schemas.android.com/apk/res/android"
-     android:layout_width="match_parent"
-     android:layout_height="match_parent">
-
-  <TextView
-    android:id="@+id/settings_greeting"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:text="@string/settings_welcome" />
-</FrameLayout>
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/values/strings.xml b/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/values/strings.xml
deleted file mode 100644
index f1b550c..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-  <!--The app name [CHAR_LIMIT=20]-->
-  <string name="appName">Simple Hilt Android</string>
-
-  <!--The greeting message [CHAR_LIMIT=100]-->
-  <string name="welcome">Hello, %1$s!</string>
-
-  <!--The feature button message [CHAR_LIMIT=100]-->
-  <string name="navigateToFeature">Navigate to a feature!</string>
-
-  <!--The settings button message [CHAR_LIMIT=100]-->
-  <string name="navigateToSettings">Navigate to settings!</string>
-
-  <!--The feature button message [CHAR_LIMIT=100]-->
-  <string name="settings_welcome">%1$s, you are on build %2$s.</string>
-</resources>
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/ActivityScenarioRuleTest.java b/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/ActivityScenarioRuleTest.java
deleted file mode 100644
index 7f1fcfc..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/ActivityScenarioRuleTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static androidx.lifecycle.Lifecycle.State.RESUMED;
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.test.ext.junit.rules.ActivityScenarioRule;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests that {@link ActivityScenarioRule} works with Hilt tests. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class ActivityScenarioRuleTest {
-  private static final String STR_VALUE = "STR_VALUE";
-
-  /** An activity to test injection. */
-  @AndroidEntryPoint
-  public static final class TestActivity extends AppCompatActivity {
-    @Inject String str;
-  }
-
-  @Rule(order = 0) public HiltAndroidRule hiltRule = new HiltAndroidRule(this);
-
-  @Rule(order = 1)
-  public ActivityScenarioRule<TestActivity> scenarioRule =
-      new ActivityScenarioRule<>(TestActivity.class);
-
-  @BindValue String str = STR_VALUE;
-
-  @Test
-  public void testState() {
-    assertThat(scenarioRule.getScenario().getState()).isEqualTo(RESUMED);
-  }
-
-  @Test
-  public void testInjection() {
-    scenarioRule
-        .getScenario()
-        .onActivity(activity -> assertThat(activity.str).isEqualTo(STR_VALUE));
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/BindValueTest.java b/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/BindValueTest.java
deleted file mode 100644
index 7abe3c2..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/BindValueTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.google.common.collect.ImmutableSet;
-import dagger.MapKey;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.testing.BindElementsIntoSet;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.BindValueIntoMap;
-import dagger.hilt.android.testing.BindValueIntoSet;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.components.SingletonComponent;
-import java.util.Map;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** A simple test using Hilt. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class BindValueTest {
-  private static final String BIND_VALUE_STRING = "BIND_VALUE_STRING";
-  private static final String TEST_QUALIFIER = "TEST_QUALIFIER";
-
-  private static final String SET_STRING_1 = "SetString1";
-  private static final String SET_STRING_2 = "SetString2";
-  private static final String SET_STRING_3 = "SetString3";
-
-  private static final String KEY_1 = "Key1";
-  private static final String KEY_2 = "Key2";
-  private static final String VALUE_1 = "Value1";
-  private static final String VALUE_2 = "Value2";
-  private static final String VALUE_3 = "Value3";
-
-  private static final Integer SET_INT_1 = 1;
-  private static final Integer SET_INT_2 = 2;
-  private static final Integer SET_INT_3 = 3;
-
-  @EntryPoint
-  @InstallIn(SingletonComponent.class)
-  interface BindValueEntryPoint {
-    @Named(TEST_QUALIFIER)
-    String bindValueString();
-
-    Set<String> getStringSet();
-  }
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @BindValue
-  @Named(TEST_QUALIFIER)
-  String bindValueString = BIND_VALUE_STRING;
-
-  @BindElementsIntoSet Set<String> bindElementsSet1 = ImmutableSet.of(SET_STRING_1);
-  @BindElementsIntoSet Set<String> bindElementsSet2 = ImmutableSet.of(SET_STRING_2);
-
-  @BindValueIntoMap
-  @MyMapKey(KEY_1)
-  String boundValue1 = VALUE_1;
-
-  @BindValueIntoMap
-  @MyMapKey(KEY_2)
-  String boundValue2 = VALUE_2;
-
-  @BindValueIntoSet Integer bindValueSetInt1 = SET_INT_1;
-  @BindValueIntoSet Integer bindValueSetInt2 = SET_INT_2;
-
-  @Inject Set<String> stringSet;
-  @Inject Provider<Set<String>> providedStringSet;
-  @Inject Provider<Map<String, String>> mapProvider;
-  @Inject Set<Integer> intSet;
-  @Inject Provider<Set<Integer>> providedIntSet;
-
-  @Test
-  public void testBindValueFieldIsProvided() throws Exception {
-    assertThat(bindValueString).isEqualTo(BIND_VALUE_STRING);
-    assertThat(getBinding()).isEqualTo(BIND_VALUE_STRING);
-  }
-
-  @Test
-  public void testBindValueIsMutable() throws Exception {
-    bindValueString = "newValue";
-    assertThat(getBinding()).isEqualTo("newValue");
-  }
-
-  @Test
-  public void testElementsIntoSet() throws Exception {
-    rule.inject();
-    // basic check that initial/default values are properly injected
-    assertThat(providedStringSet.get()).containsExactly(SET_STRING_1, SET_STRING_2);
-    // Test empty sets (something that cannot be done with @BindValueIntoSet)
-    bindElementsSet1 = ImmutableSet.of();
-    bindElementsSet2 = ImmutableSet.of();
-    assertThat(providedStringSet.get()).isEmpty();
-    // Test multiple elements in set.
-    bindElementsSet1 = ImmutableSet.of(SET_STRING_1, SET_STRING_2, SET_STRING_3);
-    assertThat(providedStringSet.get()).containsExactly(SET_STRING_1, SET_STRING_2, SET_STRING_3);
-  }
-
-  @Test
-  public void testBindValueIntoMap() throws Exception {
-    rule.inject();
-    Map<String, String> oldMap = mapProvider.get();
-    assertThat(oldMap).containsExactly(KEY_1, VALUE_1, KEY_2, VALUE_2);
-    boundValue1 = VALUE_3;
-    Map<String, String> newMap = mapProvider.get();
-    assertThat(oldMap).containsExactly(KEY_1, VALUE_1, KEY_2, VALUE_2);
-    assertThat(newMap).containsExactly(KEY_1, VALUE_3, KEY_2, VALUE_2);
-  }
-
-  @Test
-  public void testBindValueIntoSet() throws Exception {
-    rule.inject();
-    // basic check that initial/default values are properly injected
-    assertThat(providedIntSet.get()).containsExactly(SET_INT_1, SET_INT_2);
-    bindValueSetInt1 = SET_INT_3;
-    // change the value for bindValueSetString from 1 to 3
-    assertThat(providedIntSet.get()).containsExactly(SET_INT_2, SET_INT_3);
-  }
-
-  @MapKey
-  @interface MyMapKey {
-    String value();
-  }
-
-  private static String getBinding() {
-    return EntryPoints.get(getApplicationContext(), BindValueEntryPoint.class).bindValueString();
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/BroadcastReceiverTest.java b/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/BroadcastReceiverTest.java
deleted file mode 100644
index 7585bbb..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/BroadcastReceiverTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.platform.app.InstrumentationRegistry;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** A injection test of Broadcast receivers */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public class BroadcastReceiverTest {
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @BindValue final String valueToInject = "test value";
-
-  @Test
-  public void verifyReceiverInjectedValue() throws InterruptedException {
-    Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-
-    TestReceiverOne receiver = new TestReceiverOne();
-    IntentFilter intentFilter = new IntentFilter("test-action");
-    context.registerReceiver(receiver, intentFilter);
-
-    Intent intent = new Intent();
-    intent.setAction("test-action");
-    context.sendBroadcast(intent);
-
-    receiver.latch.await(2, TimeUnit.SECONDS);
-    assertThat(receiver.injectedValue).isNotEmpty();
-  }
-
-  @Test
-  public void verifyBaseReceiverInjectedValue() throws InterruptedException {
-    Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-
-    TestReceiverTwo receiver = new TestReceiverTwo();
-    IntentFilter intentFilter = new IntentFilter("test-action");
-    context.registerReceiver(receiver, intentFilter);
-
-    Intent intent = new Intent();
-    intent.setAction("test-action");
-    context.sendBroadcast(intent);
-
-    receiver.latch.await(2, TimeUnit.SECONDS);
-    assertThat(receiver.injectedValue).isNotEmpty();
-  }
-
-  @Test
-  public void verifyBaseReceiverIsNotDoubleInjected() throws InterruptedException {
-    Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-
-    TestReceiverThree receiver = new TestReceiverThree();
-    IntentFilter intentFilter = new IntentFilter("test-action");
-    context.registerReceiver(receiver, intentFilter);
-
-    Intent intent = new Intent();
-    intent.setAction("test-action");
-    context.sendBroadcast(intent);
-
-    receiver.latch.await(2, TimeUnit.SECONDS);
-    assertThat(receiver.injectedValue).isNotEmpty();
-    assertThat(receiver.onReceiveCalled).isEqualTo(1);
-  }
-
-  @Test
-  public void verifyComplexReceiverInjectedValue() throws InterruptedException {
-    Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-
-    TestReceiverFour receiver = new TestReceiverFour();
-    IntentFilter intentFilter = new IntentFilter("test-action");
-    context.registerReceiver(receiver, intentFilter);
-
-    Intent intent = new Intent();
-    intent.setAction("test-action");
-    context.sendBroadcast(intent);
-
-    receiver.latch.await(2, TimeUnit.SECONDS);
-    assertThat(receiver.injectedValue).isNotEmpty();
-  }
-
-  /** Test receiver */
-  @AndroidEntryPoint
-  static class TestReceiverOne extends BroadcastReceiver {
-
-    final CountDownLatch latch = new CountDownLatch(1);
-
-    @Inject
-    String injectedValue;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-      latch.countDown();
-    }
-  }
-
-  /** Test receiver */
-  @AndroidEntryPoint
-  static class TestReceiverTwo extends BaseReceiverAbstractMethod {
-
-    final CountDownLatch latch = new CountDownLatch(1);
-
-    @Inject
-    String injectedValue;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-      latch.countDown();
-    }
-  }
-
-  /** Test receiver */
-  @AndroidEntryPoint
-  static class TestReceiverThree extends BaseReceiverConcreteMethod {
-
-    final CountDownLatch latch = new CountDownLatch(1);
-
-    @Inject
-    String injectedValue;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-      super.onReceive(context, intent);
-      latch.countDown();
-    }
-  }
-
-  /** Complex-ish test receiver */
-  @AndroidEntryPoint
-  static class TestReceiverFour extends BroadcastReceiver {
-
-    final CountDownLatch latch = new CountDownLatch(1);
-
-    @Inject String injectedValue;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-      // Weird code, but it tests that the exception table and stack table frames are correctly
-      // updated in a transformation.
-      boolean var0;
-      if (context != null) {
-        var0 = false;
-        Object var1 = context.getClass();
-        try {
-          throw new IllegalStateException();
-        } catch (IllegalStateException ex) {
-          var0 = true;
-        }
-      } else {
-        BroadcastReceiver myself = this;
-        var0 = false;
-      }
-      latch.countDown();
-    }
-  }
-
-  /** Base test receiver */
-  abstract static class BaseReceiverAbstractMethod extends BroadcastReceiver {
-
-  }
-
-  /** Base test receiver */
-  abstract static class BaseReceiverConcreteMethod extends BroadcastReceiver {
-
-    int onReceiveCalled = 0;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-      onReceiveCalled++;
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/Injection1Test.java b/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/Injection1Test.java
deleted file mode 100644
index 0ebd150..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/Injection1Test.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.components.SingletonComponent;
-import javax.inject.Inject;
-import javax.inject.Named;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests basic injection APIs, and that bindings don't conflict with {@link Injection2Test}. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class Injection1Test {
-  private static final String APPLICATION_QUALIFIER = "APPLICATION_QUALIFIER";
-  private static final String ACTIVITY_QUALIFIER = "ACTIVITY_QUALIFIER";
-  private static final String APPLICATION_VALUE = "Injection1Test_ApplicationValue";
-  private static final String ACTIVITY_VALUE = "Injection1Test_ActivityValue";
-
-  @Module
-  @InstallIn(SingletonComponent.class)
-  interface TestApplicationModule {
-    @Provides
-    @Named(APPLICATION_QUALIFIER)
-    static String provideString() {
-      return APPLICATION_VALUE;
-    }
-  }
-
-  @Module
-  @InstallIn(ActivityComponent.class)
-  interface TestActivityModule {
-    @Provides
-    @Named(ACTIVITY_QUALIFIER)
-    static String provideString() {
-      return ACTIVITY_VALUE;
-    }
-  }
-
-  /** Test activity used to test activity injection */
-  @AndroidEntryPoint
-  public static final class TestActivity extends AppCompatActivity {
-    @Inject @Named(ACTIVITY_QUALIFIER) String activityValue;
-  }
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @Inject @Named(APPLICATION_QUALIFIER) String applicationValue;
-
-  @Test
-  public void testApplicationInjection() throws Exception {
-    assertThat(applicationValue).isNull();
-    rule.inject();
-    assertThat(applicationValue).isEqualTo(APPLICATION_VALUE);
-  }
-
-  @Test
-  public void testActivityInjection() throws Exception {
-    try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
-      scenario.onActivity(activity -> assertThat(activity.activityValue).isEqualTo(ACTIVITY_VALUE));
-    }
-  }
-
-  @Test
-  public void testSuperClassTransformation() {
-    try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
-      scenario.onActivity(
-          activity ->
-              assertThat(activity.getClass().getSuperclass().getSimpleName())
-                  .isEqualTo("Hilt_Injection1Test_TestActivity"));
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/Injection2Test.java b/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/Injection2Test.java
deleted file mode 100644
index 51d60b2..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/Injection2Test.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.components.SingletonComponent;
-import javax.inject.Inject;
-import javax.inject.Named;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests basic injection APIs, and that bindings don't conflict with {@link Injection1Test}. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class Injection2Test {
-  private static final String APPLICATION_QUALIFIER = "APPLICATION_QUALIFIER";
-  private static final String ACTIVITY_QUALIFIER = "ACTIVITY_QUALIFIER";
-  private static final String APPLICATION_VALUE = "Injection2Test_ApplicationValue";
-  private static final String ACTIVITY_VALUE = "Injection2Test_ActivityValue";
-
-  @Module
-  @InstallIn(SingletonComponent.class)
-  interface TestApplicationModule {
-    @Provides
-    @Named(APPLICATION_QUALIFIER)
-    static String provideString() {
-      return APPLICATION_VALUE;
-    }
-  }
-
-  @Module
-  @InstallIn(ActivityComponent.class)
-  interface TestActivityModule {
-    @Provides
-    @Named(ACTIVITY_QUALIFIER)
-    static String provideString() {
-      return ACTIVITY_VALUE;
-    }
-  }
-
-  /** Test activity used to test activity injection */
-  @AndroidEntryPoint
-  public static final class TestActivity extends AppCompatActivity {
-    @Inject @Named(ACTIVITY_QUALIFIER) String activityValue;
-  }
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @Inject @Named(APPLICATION_QUALIFIER) String applicationValue;
-
-  @Test
-  public void testApplicationInjection() throws Exception {
-    assertThat(applicationValue).isNull();
-    rule.inject();
-    assertThat(applicationValue).isEqualTo(APPLICATION_VALUE);
-  }
-
-  @Test
-  public void testActivityInjection() throws Exception {
-    try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
-      scenario.onActivity(activity -> assertThat(activity.activityValue).isEqualTo(ACTIVITY_VALUE));
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/ModuleTest.java b/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/ModuleTest.java
deleted file mode 100644
index 73daf8f..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/sharedTest/java/dagger/hilt/android/example/gradle/simple/ModuleTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static org.junit.Assert.assertEquals;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.Binds;
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.components.SingletonComponent;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-import javax.inject.Inject;
-import javax.inject.Qualifier;
-import javax.inject.Singleton;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests basic functionality of using modules in test. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class ModuleTest {
-  @Rule public final HiltAndroidRule rules = new HiltAndroidRule(this);
-
-  /** Qualifier for distinguishing test Strings, */
-  @Qualifier
-  @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
-  public @interface TestQualifier {
-    int value();
-  }
-
-  @Inject
-  @TestQualifier(1)
-  String testString1;
-
-  @Inject
-  @TestQualifier(2)
-  String testString2;
-
-  @Inject
-  @TestQualifier(3)
-  String testString3;
-
-  @Inject
-  @TestQualifier(4)
-  String testString4;
-
-  @Inject FooImpl fooImpl;
-  @Inject Foo foo;
-
-  /**
-   * Module which is used to test if non-static test modules get registered in the component
-   * correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public final class NonStaticModuleNonStaticProvides {
-    @Provides
-    @TestQualifier(1)
-    String provideString() {
-      return "1";
-    }
-  }
-
-  /**
-   * Module which is used to test if static test modules get registered in the component correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public static final class StaticModuleStaticProvides {
-    @Provides
-    @TestQualifier(2)
-    static String provideString() {
-      return "2";
-    }
-
-    private StaticModuleStaticProvides() {}
-  }
-
-  /**
-   * Module which is used to test if static test modules with a non-static methods get registered in
-   * the component correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public static final class StaticModuleNonStaticProvidesDefaultConstructor {
-    @Provides
-    @TestQualifier(3)
-    String provideString() {
-      return "3";
-    }
-  }
-
-  /**
-   * Module which is used to test if abstract test modules get registered in the component
-   * correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public abstract static class AbstractModuleStaticProvides {
-    @Provides
-    @TestQualifier(4)
-    static String provideString() {
-      return "4";
-    }
-
-    private AbstractModuleStaticProvides() {}
-  }
-
-  /**
-   * Module which is used to test if abstract test modules with a binds method get registered in the
-   * component correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public abstract static class AbstractModuleBindsMethod {
-    @Binds
-    abstract Foo foo(FooImpl fooImpl);
-  }
-
-  interface Foo {}
-
-  @Singleton
-  static final class FooImpl implements Foo {
-    @Inject
-    FooImpl() {}
-  }
-
-  @Test
-  public void testInjection() throws Exception {
-    rules.inject();
-    assertEquals("1", testString1);
-    assertEquals("2", testString2);
-    assertEquals("3", testString3);
-    assertEquals("4", testString4);
-    assertEquals(fooImpl, foo);
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/test/java/dagger/hilt/android/example/gradle/simple/SettingsActivityTest.java b/java/dagger/hilt/android/example/gradle/simple/app/src/test/java/dagger/hilt/android/example/gradle/simple/SettingsActivityTest.java
deleted file mode 100644
index f1e5f27..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/test/java/dagger/hilt/android/example/gradle/simple/SettingsActivityTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Build;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.android.testing.HiltTestApplication;
-import dagger.hilt.android.testing.UninstallModules;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-/** A simple test using Hilt. */
-@UninstallModules(ModelModule.class)
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-// Robolectric requires Java9 to run API 29 and above, so use API 28 instead
-@Config(sdk = Build.VERSION_CODES.P, application = HiltTestApplication.class)
-public final class SettingsActivityTest {
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @BindValue @Model String fakeModel = "FakeModel";
-
-  @Inject @Model String injectedModel;
-
-  @Test
-  public void testInjectedModel() throws Exception {
-    assertThat(injectedModel).isNull();
-    rule.inject();
-    assertThat(injectedModel).isEqualTo("FakeModel");
-  }
-
-  @Test
-  public void testActivityInject() throws Exception {
-    try (ActivityScenario<SettingsActivity> scenario =
-        ActivityScenario.launch(SettingsActivity.class)) {
-      scenario.onActivity(
-          activity ->
-              assertThat(activity.greeter.greet())
-                  .isEqualTo("ProdUser, you are on build FakeModel."));
-    }
-  }
-
-  @Test
-  public void testSuperClassTransformation() {
-    try (ActivityScenario<SettingsActivity> scenario =
-        ActivityScenario.launch(SettingsActivity.class)) {
-      scenario.onActivity(
-          activity ->
-              assertThat(activity.getClass().getSuperclass().getSimpleName())
-                  .isEqualTo("Hilt_SettingsActivity"));
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/test/java/dagger/hilt/android/example/gradle/simple/SimpleActivityTest.java b/java/dagger/hilt/android/example/gradle/simple/app/src/test/java/dagger/hilt/android/example/gradle/simple/SimpleActivityTest.java
deleted file mode 100644
index 29b5f70..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/test/java/dagger/hilt/android/example/gradle/simple/SimpleActivityTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Build;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.android.testing.HiltTestApplication;
-import dagger.hilt.android.testing.UninstallModules;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-/** A simple test using Hilt. */
-@UninstallModules(UserNameModule.class)
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-// Robolectric requires Java9 to run API 29 and above, so use API 28 instead
-@Config(sdk = Build.VERSION_CODES.P, application = HiltTestApplication.class)
-public final class SimpleActivityTest {
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @BindValue @UserName String fakeUserName = "FakeUser";
-
-  @Inject @UserName String injectedUserName;
-
-  @Test
-  public void testInjectedUserName() throws Exception {
-    assertThat(injectedUserName).isNull();
-    rule.inject();
-    assertThat(injectedUserName).isEqualTo("FakeUser");
-  }
-
-  @Test
-  public void testActivityInject() throws Exception {
-    try (ActivityScenario<SimpleActivity> scenario =
-        ActivityScenario.launch(SimpleActivity.class)) {
-      scenario.onActivity(
-          activity -> assertThat(activity.greeter.greet()).isEqualTo("Hello, FakeUser!"));
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/app/src/test/resources/dagger/hilt/android/example/gradle/simple/robolectric.properties b/java/dagger/hilt/android/example/gradle/simple/app/src/test/resources/dagger/hilt/android/example/gradle/simple/robolectric.properties
deleted file mode 100644
index 0234ffe..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/app/src/test/resources/dagger/hilt/android/example/gradle/simple/robolectric.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sdk=28
-application=dagger.hilt.android.testing.HiltTestApplication
\ No newline at end of file
diff --git a/java/dagger/hilt/android/example/gradle/simple/build.gradle b/java/dagger/hilt/android/example/gradle/simple/build.gradle
deleted file mode 100644
index c0916a4..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/build.gradle
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-buildscript {
-    ext {
-        kotlin_version = '1.3.61'
-        agp_version = "4.2.0-beta04"
-    }
-    repositories {
-        google()
-        jcenter()
-        mavenLocal()
-    }
-    dependencies {
-        classpath "com.android.tools.build:gradle:$agp_version"
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-        classpath 'com.google.dagger:hilt-android-gradle-plugin:LOCAL-SNAPSHOT'
-    }
-}
-
-allprojects {
-    repositories {
-      google()
-      jcenter()
-      mavenCentral()
-      mavenLocal()
-    }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/feature/build.gradle b/java/dagger/hilt/android/example/gradle/simple/feature/build.gradle
deleted file mode 100644
index 462aefc..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/feature/build.gradle
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-apply plugin: 'com.android.library'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-kapt'
-apply plugin: 'dagger.hilt.android.plugin'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-}
-
-kapt {
- correctErrorTypes true
-}
-
-dependencies {
-    // This is api instead of implementation since Kotlin modules here consumed
-    // by the app need to expose @kotlin.Metadata
-    api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-
-    implementation 'androidx.appcompat:appcompat:1.2.0'
-    implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-    kapt 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/AndroidManifest.xml b/java/dagger/hilt/android/example/gradle/simple/feature/src/main/AndroidManifest.xml
deleted file mode 100644
index f7919a9..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.example.gradle.simple.feature">
-  <application>
-    <activity
-        android:name=".FeatureActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="true"/>
-  </application>
-</manifest>
diff --git a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureActivity.kt b/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureActivity.kt
deleted file mode 100644
index 03b9ae9..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureActivity.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple.feature
-
-import android.os.Bundle
-import android.widget.Button
-import android.widget.TextView
-import androidx.appcompat.app.AppCompatActivity
-import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class FeatureActivity : AppCompatActivity() {
-  @Inject lateinit var counter: FeatureCounter
-
-  override fun onCreate(savedInstanceState: Bundle?) {
-    super.onCreate(savedInstanceState)
-
-    setContentView(R.layout.activity_feature)
-
-    findViewById<Button>(R.id.feature_button).setOnClickListener {
-      counter.count++
-      updateCountText()
-    }
-
-    updateCountText()
-  }
-
-  private fun updateCountText() {
-    findViewById<TextView>(R.id.feature_count).text = "The count: ${counter.count}"
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureCounter.kt b/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureCounter.kt
deleted file mode 100644
index 0fd3db3..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureCounter.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple.feature
-
-class FeatureCounter(var count: Int)
diff --git a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureModule.kt b/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureModule.kt
deleted file mode 100644
index 84ca99a..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/java/dagger/hilt/android/example/gradle/simple/feature/FeatureModule.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simple.feature
-
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.components.ActivityRetainedComponent
-import dagger.hilt.android.scopes.ActivityRetainedScoped
-
-@Module
-@InstallIn(ActivityRetainedComponent::class)
-object FeatureModule {
-  @Provides
-  @ActivityRetainedScoped
-  fun provideData() = FeatureCounter(0)
-}
diff --git a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/res/layout/activity_feature.xml b/java/dagger/hilt/android/example/gradle/simple/feature/src/main/res/layout/activity_feature.xml
deleted file mode 100644
index bf52431..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/feature/src/main/res/layout/activity_feature.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@android:color/background_light">
-
-  <TextView
-      android:id="@+id/feature_count"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:layout_alignParentTop="true"
-      android:textColor="@android:color/primary_text_light"
-      />
-
-  <Button
-      android:id="@+id/feature_button"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_below="@id/feature_count"
-      android:text="Count++"
-      />
-</RelativeLayout>
diff --git a/java/dagger/hilt/android/example/gradle/simple/gradle.properties b/java/dagger/hilt/android/example/gradle/simple/gradle.properties
deleted file mode 100644
index 646c51b..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/gradle.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-android.useAndroidX=true
-android.enableJetifier=true
diff --git a/java/dagger/hilt/android/example/gradle/simple/gradle/wrapper/gradle-wrapper.jar b/java/dagger/hilt/android/example/gradle/simple/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/java/dagger/hilt/android/example/gradle/simple/gradle/wrapper/gradle-wrapper.properties b/java/dagger/hilt/android/example/gradle/simple/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/java/dagger/hilt/android/example/gradle/simple/gradlew b/java/dagger/hilt/android/example/gradle/simple/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/java/dagger/hilt/android/example/gradle/simple/settings.gradle b/java/dagger/hilt/android/example/gradle/simple/settings.gradle
deleted file mode 100644
index 2ae0b0a..0000000
--- a/java/dagger/hilt/android/example/gradle/simple/settings.gradle
+++ /dev/null
@@ -1,3 +0,0 @@
-rootProject.name='Simple Hilt Android'
-include ':app'
-include ':feature'
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/build.gradle b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/build.gradle
deleted file mode 100644
index bff4797..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/build.gradle
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'dagger.hilt.android.plugin'
-apply plugin: 'kotlin-kapt'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        applicationId "dagger.hilt.android.example.gradle.simpleKotlin"
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-    testOptions {
-        unitTests.includeAndroidResources = true
-    }
-}
-
-dependencies {
-    implementation fileTree(dir: "libs", include: ["*.jar"])
-    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation 'androidx.appcompat:appcompat:1.2.0'
-
-    implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-    kapt 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'
-
-    testImplementation 'com.google.truth:truth:1.0.1'
-    testImplementation 'junit:junit:4.13'
-    testImplementation 'org.robolectric:robolectric:4.5-alpha-3'
-    testImplementation 'androidx.core:core:1.3.2'
-    // TODO(bcorso): This multidex dep shouldn't be required -- it's a dep for the generated code.
-    testImplementation 'androidx.multidex:multidex:2.0.0'
-    testImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
-    kaptTest 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'
-}
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/debug/AndroidManifest.xml b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/debug/AndroidManifest.xml
deleted file mode 100644
index 081c7ad..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/debug/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.example.gradle.simpleKotlin">
-
-  <application>
-    <activity android:name=".SimpleTest$TestActivity" android:exported="false"/>
-  </application>
-</manifest>
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/AndroidManifest.xml b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 2e274ab..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.example.gradle.simpleKotlin">
-
-    <application
-        android:name=".KotlinApplication"
-        android:allowBackup="true"
-        android:label="@string/app_name"
-        android:supportsRtl="true"
-        android:theme="@style/Theme.AppCompat.Light">
-        <activity android:name=".MainActivity" android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/ActivityModule.kt b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/ActivityModule.kt
deleted file mode 100644
index 8a85040..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/ActivityModule.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simpleKotlin
-
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.components.ActivityComponent
-
-@Module
-@InstallIn(ActivityComponent::class)
-object ActivityModule {
-  @UserName
-  @Provides
-  fun provideUserName(): String {
-    return "Android User"
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/ApplicationModule.kt b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/ApplicationModule.kt
deleted file mode 100644
index 9ee904d..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/ApplicationModule.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simpleKotlin
-
-import android.os.Build
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.components.SingletonComponent
-
-@Module
-@InstallIn(SingletonComponent::class)
-object ApplicationModule {
-  @Provides
-  @Model
-  fun provideModel(): String {
-    return Build.MODEL
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/KotlinApplication.kt b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/KotlinApplication.kt
deleted file mode 100644
index 765fb36..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/KotlinApplication.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simpleKotlin
-
-import android.app.Application
-import dagger.hilt.android.HiltAndroidApp
-import javax.inject.Inject
-
-@HiltAndroidApp
-class KotlinApplication : Application() {
-  // Shows that we can inject SingletonComponent bindings into an application.
-  @Inject
-  @Model
-  @JvmField
-  var model: String? = null
-}
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/MainActivity.kt b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/MainActivity.kt
deleted file mode 100644
index 564f05a..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/MainActivity.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simpleKotlin
-
-import android.os.Bundle
-import android.view.View
-import android.widget.TextView
-import androidx.appcompat.app.AppCompatActivity
-import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class MainActivity : AppCompatActivity() {
-  // Shows that we can inject Application/Activity bindings into an activity.
-  @JvmField
-  @Model
-  @Inject
-  var model: String? = null
-
-  @JvmField
-  @UserName
-  @Inject
-  var name: String? = null
-
-  override fun onCreate(savedInstanceState: Bundle?) {
-    super.onCreate(savedInstanceState)
-    setContentView(R.layout.activity_main)
-    val greeting = findViewById<View>(R.id.greeting) as TextView
-    val text = resources.getString(R.string.welcome, name, model)
-    greeting.text = text
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/Model.kt b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/Model.kt
deleted file mode 100644
index 4fe168d..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/Model.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simpleKotlin
-
-import javax.inject.Qualifier
-
-/** Qualifies bindings relating to [android.os.Build.MODEL].  */
-@Qualifier
-@Retention(AnnotationRetention.RUNTIME)
-internal annotation class Model
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/UserName.kt b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/UserName.kt
deleted file mode 100644
index a061ab5..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/java/dagger/hilt/android/example/gradle/simpleKotlin/UserName.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simpleKotlin
-
-import javax.inject.Qualifier
-
-/** Qualifies bindings relating to the user name.  */
-@Qualifier
-@Retention(AnnotationRetention.RUNTIME)
-internal annotation class UserName
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/res/layout/activity_main.xml b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index 0d7637d..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:background="@android:color/background_light">
-
-  <TextView
-    android:id="@+id/greeting"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_alignParentTop="true"
-    android:textColor="@android:color/primary_text_light"
-    />
-</RelativeLayout>
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/res/values/strings.xml b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/res/values/strings.xml
deleted file mode 100644
index c1e4f27..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<resources>
-    <!--The app name [CHAR_LIMIT=40]-->
-    <string name="app_name">Simple Hilt Kotlin Android App</string>
-
-    <!--The greeting message [CHAR_LIMIT=100]-->
-    <string name="welcome">Hello, %1$s! You are on build %2$s.</string>
-</resources>
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/test/java/dagger/hilt/android/example/gradle/simpleKotlin/SimpleTest.kt b/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/test/java/dagger/hilt/android/example/gradle/simpleKotlin/SimpleTest.kt
deleted file mode 100644
index d52ff71..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/app/src/test/java/dagger/hilt/android/example/gradle/simpleKotlin/SimpleTest.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simpleKotlin
-
-import android.os.Build
-import androidx.appcompat.app.AppCompatActivity
-import androidx.test.core.app.ActivityScenario
-import com.google.common.truth.Truth.assertThat
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import dagger.hilt.android.testing.HiltTestApplication
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.RobolectricTestRunner
-import org.robolectric.annotation.Config
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
-@HiltAndroidTest
-@RunWith(RobolectricTestRunner::class)
-// Robolectric requires Java9 to run API 29 and above, so use API 28 instead
-@Config(sdk = [Build.VERSION_CODES.P], application = HiltTestApplication::class)
-class SimpleTest {
-  @Rule
-  @JvmField
-  var rule = HiltAndroidRule(this)
-
-  @AndroidEntryPoint
-  class TestActivity : AppCompatActivity()
-
-  @Test
-  fun verifyMainActivity() {
-    ActivityScenario.launch(MainActivity::class.java).use { scenario ->
-      scenario.onActivity { activity ->
-        assertThat(activity::class.java.getSuperclass()?.getSimpleName())
-          .isEqualTo("Hilt_MainActivity")
-        assertThat(activity.model).isNotNull()
-        assertThat(activity.name).isNotNull()
-      }
-    }
-  }
-
-  @Test
-  fun verifyTestActivity() {
-    ActivityScenario.launch(TestActivity::class.java).use { scenario ->
-      scenario.onActivity { activity ->
-        assertThat(activity::class.java.getSuperclass()?.getSimpleName())
-          .isEqualTo("Hilt_SimpleTest_TestActivity")
-      }
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/build.gradle b/java/dagger/hilt/android/example/gradle/simpleKotlin/build.gradle
deleted file mode 100644
index 7a02482..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/build.gradle
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-buildscript {
-    ext {
-        kotlin_version = '1.3.61'
-        agp_version = "4.2.0-beta04"
-    }
-    repositories {
-        google()
-        jcenter()
-        mavenLocal()
-    }
-    dependencies {
-        classpath "com.android.tools.build:gradle:$agp_version"
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-        classpath 'com.google.dagger:hilt-android-gradle-plugin:LOCAL-SNAPSHOT'
-    }
-}
-
-allprojects {
-    repositories {
-      google()
-      jcenter()
-      mavenCentral()
-      mavenLocal()
-    }
-}
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle.properties b/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle.properties
deleted file mode 100644
index 646c51b..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-android.useAndroidX=true
-android.enableJetifier=true
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle/wrapper/gradle-wrapper.jar b/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle/wrapper/gradle-wrapper.properties b/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/gradlew b/java/dagger/hilt/android/example/gradle/simpleKotlin/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/java/dagger/hilt/android/example/gradle/simpleKotlin/settings.gradle b/java/dagger/hilt/android/example/gradle/simpleKotlin/settings.gradle
deleted file mode 100644
index e42f9d1..0000000
--- a/java/dagger/hilt/android/example/gradle/simpleKotlin/settings.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-rootProject.name='Simple Kotlin Hilt Android'
-include ':app'
diff --git a/java/dagger/hilt/android/internal/BUILD b/java/dagger/hilt/android/internal/BUILD
deleted file mode 100644
index 57c84e3..0000000
--- a/java/dagger/hilt/android/internal/BUILD
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Internal Hilt Android utitlies
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "internal",
-    srcs = ["ThreadUtil.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/internal/ThreadUtil.java b/java/dagger/hilt/android/internal/ThreadUtil.java
deleted file mode 100644
index d5b11f5..0000000
--- a/java/dagger/hilt/android/internal/ThreadUtil.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal;
-
-import android.os.Looper;
-
-/** Thread utility methods. */
-public final class ThreadUtil {
-
-  private static Thread mainThread;
-
-  private ThreadUtil() {}
-
-  /** Returns true if the current thread is the Main thread. */
-  public static boolean isMainThread() {
-    if (mainThread == null) {
-      mainThread = Looper.getMainLooper().getThread();
-    }
-    return Thread.currentThread() == mainThread;
-  }
-
-  /** Checks that the current thread is the Main thread. Otherwise throws an exception. */
-  public static void ensureMainThread() {
-    if (!isMainThread()) {
-      throw new IllegalStateException("Must be called on the Main thread.");
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/internal/builders/ActivityComponentBuilder.java b/java/dagger/hilt/android/internal/builders/ActivityComponentBuilder.java
deleted file mode 100644
index 5ea09db..0000000
--- a/java/dagger/hilt/android/internal/builders/ActivityComponentBuilder.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.builders;
-
-import android.app.Activity;
-import dagger.BindsInstance;
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.components.ActivityComponent;
-
-/** Interface for creating an {@link ActivityComponent}. */
-@DefineComponent.Builder
-public interface ActivityComponentBuilder {
-  ActivityComponentBuilder activity(
-      @BindsInstance
-          Activity activity);
-
-  ActivityComponent build();
-}
diff --git a/java/dagger/hilt/android/internal/builders/ActivityRetainedComponentBuilder.java b/java/dagger/hilt/android/internal/builders/ActivityRetainedComponentBuilder.java
deleted file mode 100644
index 110b3fe..0000000
--- a/java/dagger/hilt/android/internal/builders/ActivityRetainedComponentBuilder.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.builders;
-
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.components.ActivityRetainedComponent;
-
-/** Interface for creating a {@link ActivityRetainedComponent}. */
-@DefineComponent.Builder
-public interface ActivityRetainedComponentBuilder {
-  ActivityRetainedComponent build();
-}
diff --git a/java/dagger/hilt/android/internal/builders/BUILD b/java/dagger/hilt/android/internal/builders/BUILD
deleted file mode 100644
index 0e282be..0000000
--- a/java/dagger/hilt/android/internal/builders/BUILD
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Hilt Android component builders
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "builders",
-    srcs = glob(["*.java"]),
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:define_component",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/components:view_model_component",
-        "@maven//:androidx_activity_activity",
-        "@maven//:androidx_fragment_fragment",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/internal/builders/FragmentComponentBuilder.java b/java/dagger/hilt/android/internal/builders/FragmentComponentBuilder.java
deleted file mode 100644
index 11cc89f..0000000
--- a/java/dagger/hilt/android/internal/builders/FragmentComponentBuilder.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.builders;
-
-import androidx.fragment.app.Fragment;
-import dagger.BindsInstance;
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.components.FragmentComponent;
-
-/** Interface for creating a {@link FragmentComponent}. */
-@DefineComponent.Builder
-public interface FragmentComponentBuilder {
-  FragmentComponentBuilder fragment(@BindsInstance Fragment fragment);
-  FragmentComponent build();
-}
diff --git a/java/dagger/hilt/android/internal/builders/ServiceComponentBuilder.java b/java/dagger/hilt/android/internal/builders/ServiceComponentBuilder.java
deleted file mode 100644
index 9b95d12..0000000
--- a/java/dagger/hilt/android/internal/builders/ServiceComponentBuilder.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.builders;
-
-import android.app.Service;
-import dagger.BindsInstance;
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.components.ServiceComponent;
-
-/** Interface for creating a {@link ServiceComponent}. */
-@DefineComponent.Builder
-public interface ServiceComponentBuilder {
-  ServiceComponentBuilder service(@BindsInstance Service service);
-  ServiceComponent build();
-}
diff --git a/java/dagger/hilt/android/internal/builders/ViewComponentBuilder.java b/java/dagger/hilt/android/internal/builders/ViewComponentBuilder.java
deleted file mode 100644
index f2e37b6..0000000
--- a/java/dagger/hilt/android/internal/builders/ViewComponentBuilder.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.builders;
-
-import android.view.View;
-import dagger.BindsInstance;
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.components.ViewComponent;
-
-/** Interface for creating a {@link ViewComponent}. */
-@DefineComponent.Builder
-public interface ViewComponentBuilder {
-  ViewComponentBuilder view(@BindsInstance View view);
-
-  ViewComponent build();
-}
diff --git a/java/dagger/hilt/android/internal/builders/ViewModelComponentBuilder.java b/java/dagger/hilt/android/internal/builders/ViewModelComponentBuilder.java
deleted file mode 100644
index e9acbb9..0000000
--- a/java/dagger/hilt/android/internal/builders/ViewModelComponentBuilder.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.builders;
-
-import androidx.lifecycle.SavedStateHandle;
-import dagger.BindsInstance;
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.components.ViewModelComponent;
-
-/** Interface for creating a {@link ViewModelComponent}. */
-@DefineComponent.Builder
-public interface ViewModelComponentBuilder {
-  ViewModelComponentBuilder savedStateHandle(@BindsInstance SavedStateHandle handle);
-
-  ViewModelComponent build();
-}
diff --git a/java/dagger/hilt/android/internal/builders/ViewWithFragmentComponentBuilder.java b/java/dagger/hilt/android/internal/builders/ViewWithFragmentComponentBuilder.java
deleted file mode 100644
index b15a8cc..0000000
--- a/java/dagger/hilt/android/internal/builders/ViewWithFragmentComponentBuilder.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.builders;
-
-import android.view.View;
-import dagger.BindsInstance;
-import dagger.hilt.DefineComponent;
-import dagger.hilt.android.components.ViewWithFragmentComponent;
-
-/** Interface for creating a {@link ViewWithFragmentComponent}. */
-@DefineComponent.Builder
-public interface ViewWithFragmentComponentBuilder {
-  ViewWithFragmentComponentBuilder view(@BindsInstance View view);
-
-  ViewWithFragmentComponent build();
-}
diff --git a/java/dagger/hilt/android/internal/lifecycle/BUILD b/java/dagger/hilt/android/internal/lifecycle/BUILD
deleted file mode 100644
index b3ecfc2..0000000
--- a/java/dagger/hilt/android/internal/lifecycle/BUILD
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Hilt lifecycle ViewModel hooks.
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "lifecycle",
-    srcs = glob(["*.java"]),
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:entry_point",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/components:view_model_component",
-        "//java/dagger/hilt/android/internal/builders",
-        "//java/dagger/hilt/android/qualifiers",
-        "@maven//:androidx_activity_activity",
-        "@maven//:androidx_annotation_annotation",
-        "@maven//:androidx_fragment_fragment",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
-        "@maven//:androidx_savedstate_savedstate",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/internal/lifecycle/DefaultActivityViewModelFactory.java b/java/dagger/hilt/android/internal/lifecycle/DefaultActivityViewModelFactory.java
deleted file mode 100644
index becce8c..0000000
--- a/java/dagger/hilt/android/internal/lifecycle/DefaultActivityViewModelFactory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.lifecycle;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import javax.inject.Qualifier;
-
-/** Qualifier for the default view model factory used by @AndroidEntryPoint annotated activities. */
-@Qualifier
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
-public @interface DefaultActivityViewModelFactory {}
diff --git a/java/dagger/hilt/android/internal/lifecycle/DefaultFragmentViewModelFactory.java b/java/dagger/hilt/android/internal/lifecycle/DefaultFragmentViewModelFactory.java
deleted file mode 100644
index 9967053..0000000
--- a/java/dagger/hilt/android/internal/lifecycle/DefaultFragmentViewModelFactory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.lifecycle;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import javax.inject.Qualifier;
-
-/** Qualifier for the default view model factory used by @AndroidEntryPoint annotated fragments. */
-@Qualifier
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
-public @interface DefaultFragmentViewModelFactory {}
diff --git a/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java b/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java
deleted file mode 100644
index 427822d..0000000
--- a/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.lifecycle;
-
-import android.app.Application;
-import androidx.lifecycle.SavedStateViewModelFactory;
-import androidx.lifecycle.ViewModelProvider;
-import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.activity.ComponentActivity;
-import androidx.savedstate.SavedStateRegistryOwner;
-import dagger.Module;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.hilt.android.components.FragmentComponent;
-import dagger.hilt.android.internal.builders.ViewModelComponentBuilder;
-import dagger.multibindings.Multibinds;
-import java.util.Set;
-import javax.inject.Inject;
-
-/**
- * Modules and entry points for the default view model factory used by activities and fragments
- * annotated with @AndroidEntryPoint.
- *
- * <p>Entry points are used to acquire the factory because injected fields in the generated
- * activities and fragments are ignored by Dagger when using the transform due to the generated
- * class not being part of the hierarchy during compile time.
- */
-public final class DefaultViewModelFactories {
-
-  /**
-   * Retrieves the default view model factory for the activity.
-   *
-   * <p>Do not use except in Hilt generated code!
-   */
-  public static ViewModelProvider.Factory getActivityFactory(ComponentActivity activity) {
-    return EntryPoints.get(activity, ActivityEntryPoint.class)
-        .getHiltInternalFactoryFactory()
-        .fromActivity(activity);
-  }
-
-  /**
-   * Retrieves the default view model factory for the activity.
-   *
-   * <p>Do not use except in Hilt generated code!
-   */
-  public static ViewModelProvider.Factory getFragmentFactory(Fragment fragment) {
-    return EntryPoints.get(fragment, FragmentEntryPoint.class)
-        .getHiltInternalFactoryFactory()
-        .fromFragment(fragment);
-  }
-
-  /** Internal factory for the Hilt ViewModel Factory. */
-  public static final class InternalFactoryFactory {
-
-    private final Application application;
-    private final Set<String> keySet;
-    private final ViewModelComponentBuilder viewModelComponentBuilder;
-    @Nullable private final ViewModelProvider.Factory defaultActivityFactory;
-    @Nullable private final ViewModelProvider.Factory defaultFragmentFactory;
-
-    @Inject
-    InternalFactoryFactory(
-            Application application,
-        @HiltViewModelMap.KeySet Set<String> keySet,
-        ViewModelComponentBuilder viewModelComponentBuilder,
-        // These default factory bindings are temporary for the transition of deprecating
-        // the Hilt ViewModel extension for the built-in support
-        @DefaultActivityViewModelFactory Set<ViewModelProvider.Factory> defaultActivityFactorySet,
-        @DefaultFragmentViewModelFactory Set<ViewModelProvider.Factory> defaultFragmentFactorySet) {
-      this.application = application;
-      this.keySet = keySet;
-      this.viewModelComponentBuilder = viewModelComponentBuilder;
-      this.defaultActivityFactory = getFactoryFromSet(defaultActivityFactorySet);
-      this.defaultFragmentFactory = getFactoryFromSet(defaultFragmentFactorySet);
-    }
-
-    ViewModelProvider.Factory fromActivity(ComponentActivity activity) {
-      return getHiltViewModelFactory(activity,
-          activity.getIntent() != null ? activity.getIntent().getExtras() : null,
-          defaultActivityFactory);
-    }
-
-    ViewModelProvider.Factory fromFragment(Fragment fragment) {
-      return getHiltViewModelFactory(fragment, fragment.getArguments(), defaultFragmentFactory);
-    }
-
-    private ViewModelProvider.Factory getHiltViewModelFactory(
-        SavedStateRegistryOwner owner,
-        @Nullable Bundle defaultArgs,
-        @Nullable ViewModelProvider.Factory extensionDelegate) {
-      ViewModelProvider.Factory delegate = extensionDelegate == null
-          ? new SavedStateViewModelFactory(application, owner, defaultArgs)
-          : extensionDelegate;
-      return new HiltViewModelFactory(
-          owner, defaultArgs, keySet, delegate, viewModelComponentBuilder);
-    }
-
-    @Nullable
-    private static ViewModelProvider.Factory getFactoryFromSet(Set<ViewModelProvider.Factory> set) {
-      // A multibinding set is used instead of BindsOptionalOf because Optional is not available in
-      // Android until API 24 and we don't want to have Guava as a transitive dependency.
-      if (set.isEmpty()) {
-        return null;
-      }
-      if (set.size() > 1) {
-        throw new IllegalStateException(
-            "At most one default view model factory is expected. Found " + set);
-      }
-      ViewModelProvider.Factory factory = set.iterator().next();
-      if (factory == null) {
-        throw new IllegalStateException("Default view model factory must not be null.");
-      }
-      return factory;
-    }
-  }
-
-  /** The activity module to declare the optional factories. */
-  @Module
-  @InstallIn(ActivityComponent.class)
-  interface ActivityModule {
-    @Multibinds
-    @HiltViewModelMap.KeySet
-    abstract Set<String> viewModelKeys();
-
-    @Multibinds
-    @DefaultActivityViewModelFactory
-    Set<ViewModelProvider.Factory> defaultActivityViewModelFactory();
-
-    @Multibinds
-    @DefaultFragmentViewModelFactory
-    Set<ViewModelProvider.Factory> defaultFragmentViewModelFactory();
-  }
-
-  /** The activity entry point to retrieve the factory. */
-  @EntryPoint
-  @InstallIn(ActivityComponent.class)
-  public interface ActivityEntryPoint {
-    InternalFactoryFactory getHiltInternalFactoryFactory();
-  }
-
-  /** The fragment entry point to retrieve the factory. */
-  @EntryPoint
-  @InstallIn(FragmentComponent.class)
-  public interface FragmentEntryPoint {
-    InternalFactoryFactory getHiltInternalFactoryFactory();
-  }
-
-  private DefaultViewModelFactories() {}
-}
diff --git a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java b/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java
deleted file mode 100644
index 3b0d3bc..0000000
--- a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.lifecycle;
-
-import androidx.lifecycle.AbstractSavedStateViewModelFactory;
-import androidx.lifecycle.SavedStateHandle;
-import androidx.lifecycle.ViewModel;
-import androidx.lifecycle.ViewModelProvider;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.savedstate.SavedStateRegistryOwner;
-import dagger.Module;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ViewModelComponent;
-import dagger.hilt.android.internal.builders.ViewModelComponentBuilder;
-import dagger.multibindings.Multibinds;
-import java.util.Map;
-import java.util.Set;
-import javax.inject.Provider;
-
-/**
- * View Model Provider Factory for the Hilt Extension.
- *
- * <p>A provider for this factory will be installed in the {@link
- * dagger.hilt.android.components.ActivityComponent} and {@link
- * dagger.hilt.android.components.FragmentComponent}. An instance of this factory will also be the
- * default factory by activities and fragments annotated with {@link
- * dagger.hilt.android.AndroidEntryPoint}.
- */
-public final class HiltViewModelFactory implements ViewModelProvider.Factory {
-
-  /** Hilt entry point for getting the multi-binding map of ViewModels. */
-  @EntryPoint
-  @InstallIn(ViewModelComponent.class)
-  public interface ViewModelFactoriesEntryPoint {
-    @HiltViewModelMap
-    Map<String, Provider<ViewModel>> getHiltViewModelMap();
-  }
-
-  /** Hilt module for providing the empty multi-binding map of ViewModels. */
-  @Module
-  @InstallIn(ViewModelComponent.class)
-  interface ViewModelModule {
-    @Multibinds
-    @HiltViewModelMap
-    Map<String, ViewModel> hiltViewModelMap();
-  }
-
-  private final Set<String> hiltViewModelKeys;
-  private final ViewModelProvider.Factory delegateFactory;
-  private final AbstractSavedStateViewModelFactory hiltViewModelFactory;
-
-  public HiltViewModelFactory(
-      @NonNull SavedStateRegistryOwner owner,
-      @Nullable Bundle defaultArgs,
-      @NonNull Set<String> hiltViewModelKeys,
-      @NonNull ViewModelProvider.Factory delegateFactory,
-      @NonNull ViewModelComponentBuilder viewModelComponentBuilder) {
-    this.hiltViewModelKeys = hiltViewModelKeys;
-    this.delegateFactory = delegateFactory;
-    this.hiltViewModelFactory =
-        new AbstractSavedStateViewModelFactory(owner, defaultArgs) {
-          @NonNull
-          @Override
-          @SuppressWarnings("unchecked")
-          protected <T extends ViewModel> T create(
-              @NonNull String key, @NonNull Class<T> modelClass, @NonNull SavedStateHandle handle) {
-            ViewModelComponent component =
-                viewModelComponentBuilder.savedStateHandle(handle).build();
-            Provider<? extends ViewModel> provider =
-                EntryPoints.get(component, ViewModelFactoriesEntryPoint.class)
-                    .getHiltViewModelMap()
-                    .get(modelClass.getName());
-            if (provider == null) {
-              throw new IllegalStateException(
-                  "Expected the @HiltViewModel-annotated class '"
-                      + modelClass.getName()
-                      + "' to be available in the multi-binding of "
-                      + "@HiltViewModelMap but none was found.");
-            }
-            return (T) provider.get();
-          }
-        };
-  }
-
-  @NonNull
-  @Override
-  public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
-    if (hiltViewModelKeys.contains(modelClass.getName())) {
-      return hiltViewModelFactory.create(modelClass);
-    } else {
-      return delegateFactory.create(modelClass);
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelMap.java b/java/dagger/hilt/android/internal/lifecycle/HiltViewModelMap.java
deleted file mode 100644
index 5d54e9c..0000000
--- a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelMap.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.lifecycle;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import javax.inject.Qualifier;
-
-/**
- * Internal qualifier for the multibinding map of ViewModels used by the {@link
- * dagger.hilt.android.lifecycle.HiltViewModelFactory}.
- */
-@Qualifier
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD, ElementType.PARAMETER})
-public @interface HiltViewModelMap {
-
-  /** Internal qualifier for the multibinding set of class names annotated with @ViewModelInject. */
-  @Qualifier
-  @Retention(RetentionPolicy.CLASS)
-  @Target({ElementType.METHOD, ElementType.PARAMETER})
-  @interface KeySet {}
-}
diff --git a/java/dagger/hilt/android/internal/managers/ActivityComponentManager.java b/java/dagger/hilt/android/internal/managers/ActivityComponentManager.java
deleted file mode 100644
index ef7aa3b..0000000
--- a/java/dagger/hilt/android/internal/managers/ActivityComponentManager.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.managers;
-
-import android.app.Activity;
-import android.app.Application;
-import androidx.activity.ComponentActivity;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityRetainedComponent;
-import dagger.hilt.android.internal.builders.ActivityComponentBuilder;
-import dagger.hilt.internal.GeneratedComponentManager;
-
-/**
- * Do not use except in Hilt generated code!
- *
- * <p>A manager for the creation of components that live in the Activity.
- *
- * <p>Note: This class is not typed since its type in generated code is always <?> or <Object>. This
- * is mainly due to the fact that we don't know the components at the time of generation, and
- * because even the injector interface type is not a valid type if we have a hilt base class.
- *
- */
-public class ActivityComponentManager implements GeneratedComponentManager<Object> {
-  /** Entrypoint for {@link ActivityComponentBuilder}. */
-  @EntryPoint
-  @InstallIn(ActivityRetainedComponent.class)
-  public interface ActivityComponentBuilderEntryPoint {
-    ActivityComponentBuilder activityComponentBuilder();
-  }
-
-  private volatile Object component;
-  private final Object componentLock = new Object();
-
-  protected final Activity activity;
-
-  private final GeneratedComponentManager<ActivityRetainedComponent>
-      activityRetainedComponentManager;
-
-  public ActivityComponentManager(Activity activity) {
-    this.activity = activity;
-    this.activityRetainedComponentManager =
-        new ActivityRetainedComponentManager((ComponentActivity) activity);
-  }
-
-  @Override
-  public Object generatedComponent() {
-    if (component == null) {
-      synchronized (componentLock) {
-        if (component == null) {
-          component = createComponent();
-        }
-      }
-    }
-    return component;
-  }
-
-  protected Object createComponent() {
-    if (!(activity.getApplication() instanceof GeneratedComponentManager)) {
-      if (Application.class.equals(activity.getApplication().getClass())) {
-        throw new IllegalStateException(
-                "Hilt Activity must be attached to an @HiltAndroidApp Application. "
-                + "Did you forget to specify your Application's class name in your manifest's "
-                + "<application />'s android:name attribute?");
-      }
-      throw new IllegalStateException(
-              "Hilt Activity must be attached to an @AndroidEntryPoint Application. Found: "
-              + activity.getApplication().getClass());
-    }
-
-    return EntryPoints.get(
-            activityRetainedComponentManager, ActivityComponentBuilderEntryPoint.class)
-        .activityComponentBuilder()
-        .activity(activity)
-        .build();
-  }
-}
diff --git a/java/dagger/hilt/android/internal/managers/ActivityRetainedComponentManager.java b/java/dagger/hilt/android/internal/managers/ActivityRetainedComponentManager.java
deleted file mode 100644
index 2d4a72b..0000000
--- a/java/dagger/hilt/android/internal/managers/ActivityRetainedComponentManager.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.managers;
-
-import androidx.lifecycle.ViewModel;
-import androidx.lifecycle.ViewModelProvider;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.activity.ComponentActivity;
-import dagger.Binds;
-import dagger.Module;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.ActivityRetainedLifecycle;
-import dagger.hilt.android.components.ActivityRetainedComponent;
-import dagger.hilt.android.internal.ThreadUtil;
-import dagger.hilt.android.internal.builders.ActivityRetainedComponentBuilder;
-import dagger.hilt.android.scopes.ActivityRetainedScoped;
-import dagger.hilt.components.SingletonComponent;
-import dagger.hilt.internal.GeneratedComponentManager;
-import java.util.HashSet;
-import java.util.Set;
-import javax.inject.Inject;
-
-/** A manager for the creation of components that survives activity configuration changes. */
-final class ActivityRetainedComponentManager
-    implements GeneratedComponentManager<ActivityRetainedComponent> {
-
-  /** Entry point for {@link ActivityRetainedComponentBuilder}. */
-  @EntryPoint
-  @InstallIn(SingletonComponent.class)
-  public interface ActivityRetainedComponentBuilderEntryPoint {
-    ActivityRetainedComponentBuilder retainedComponentBuilder();
-  }
-
-  /** Entry point for {@link Lifecycle}. */
-  @EntryPoint
-  @InstallIn(ActivityRetainedComponent.class)
-  public interface ActivityRetainedLifecycleEntryPoint {
-    ActivityRetainedLifecycle getActivityRetainedLifecycle();
-  }
-
-  static final class ActivityRetainedComponentViewModel extends ViewModel {
-    private final ActivityRetainedComponent component;
-
-    ActivityRetainedComponentViewModel(ActivityRetainedComponent component) {
-      this.component = component;
-    }
-
-    ActivityRetainedComponent getComponent() {
-      return component;
-    }
-
-    @Override
-    protected void onCleared() {
-      super.onCleared();
-      ActivityRetainedLifecycle lifecycle =
-          EntryPoints.get(component, ActivityRetainedLifecycleEntryPoint.class)
-              .getActivityRetainedLifecycle();
-      ((ActivityRetainedComponentManager.Lifecycle) lifecycle).dispatchOnCleared();
-    }
-  }
-
-  private final ViewModelProvider viewModelProvider;
-
-  @Nullable private volatile ActivityRetainedComponent component;
-  private final Object componentLock = new Object();
-
-  ActivityRetainedComponentManager(ComponentActivity activity) {
-    this.viewModelProvider =
-        new ViewModelProvider(
-            activity,
-            new ViewModelProvider.Factory() {
-              @NonNull
-              @Override
-              @SuppressWarnings("unchecked")
-              public <T extends ViewModel> T create(@NonNull Class<T> aClass) {
-                ActivityRetainedComponent component =
-                    EntryPoints.get(
-                            activity.getApplication(),
-                            ActivityRetainedComponentBuilderEntryPoint.class)
-                        .retainedComponentBuilder()
-                        .build();
-                return (T) new ActivityRetainedComponentViewModel(component);
-              }
-            });
-  }
-
-  @Override
-  public ActivityRetainedComponent generatedComponent() {
-    if (component == null) {
-      synchronized (componentLock) {
-        if (component == null) {
-          component = createComponent();
-        }
-      }
-    }
-    return component;
-  }
-
-  private ActivityRetainedComponent createComponent() {
-    return viewModelProvider.get(ActivityRetainedComponentViewModel.class).getComponent();
-  }
-
-  /** The default implementation of {@link ActivityRetainedLifecycle}. */
-  @ActivityRetainedScoped
-  static final class Lifecycle implements ActivityRetainedLifecycle {
-
-    private final Set<OnClearedListener> listeners = new HashSet<>();
-    private boolean onClearedDispatched = false;
-
-    @Inject
-    Lifecycle() {}
-
-    @Override
-    public void addOnClearedListener(@NonNull OnClearedListener listener) {
-      ThreadUtil.ensureMainThread();
-      throwIfOnClearedDispatched();
-      listeners.add(listener);
-    }
-
-    @Override
-    public void removeOnClearedListener(@NonNull OnClearedListener listener) {
-      ThreadUtil.ensureMainThread();
-      throwIfOnClearedDispatched();
-      listeners.remove(listener);
-    }
-
-    void dispatchOnCleared() {
-      ThreadUtil.ensureMainThread();
-      onClearedDispatched = true;
-      for (OnClearedListener listener : listeners) {
-        listener.onCleared();
-      }
-    }
-
-    private void throwIfOnClearedDispatched() {
-      if (onClearedDispatched) {
-        throw new IllegalStateException(
-            "There was a race between the call to add/remove an OnClearedListener and onCleared(). "
-                + "This can happen when posting to the Main thread from a background thread, "
-                + "which is not supported.");
-      }
-    }
-  }
-
-  @Module
-  @InstallIn(ActivityRetainedComponent.class)
-  abstract static class LifecycleModule {
-    @Binds
-    abstract ActivityRetainedLifecycle bind(Lifecycle impl);
-  }
-}
diff --git a/java/dagger/hilt/android/internal/managers/ApplicationComponentManager.java b/java/dagger/hilt/android/internal/managers/ApplicationComponentManager.java
deleted file mode 100644
index bb645db..0000000
--- a/java/dagger/hilt/android/internal/managers/ApplicationComponentManager.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.managers;
-
-import dagger.hilt.internal.GeneratedComponentManager;
-
-/**
- * Do not use except in Hilt generated code!
- *
- * <p>A manager for the creation of components that live in the Application.
- */
-public final class ApplicationComponentManager implements GeneratedComponentManager<Object> {
-  private volatile Object component;
-  private final Object componentLock = new Object();
-  private final ComponentSupplier componentCreator;
-
-  public ApplicationComponentManager(ComponentSupplier componentCreator) {
-    this.componentCreator = componentCreator;
-  }
-
-  @Override
-  public Object generatedComponent() {
-    if (component == null) {
-      synchronized (componentLock) {
-        if (component == null) {
-          component = componentCreator.get();
-        }
-      }
-    }
-    return component;
-  }
-}
diff --git a/java/dagger/hilt/android/internal/managers/BUILD b/java/dagger/hilt/android/internal/managers/BUILD
deleted file mode 100644
index 3bc8df1..0000000
--- a/java/dagger/hilt/android/internal/managers/BUILD
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Internal Hilt Android managers
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "component_supplier",
-    srcs = ["ComponentSupplier.java"],
-)
-
-android_library(
-    name = "managers",
-    srcs = [
-        "ActivityComponentManager.java",
-        "ActivityRetainedComponentManager.java",
-        "ApplicationComponentManager.java",
-        "BroadcastReceiverComponentManager.java",
-        "FragmentComponentManager.java",
-        "ServiceComponentManager.java",
-        "ViewComponentManager.java",
-    ],
-    deps = [
-        ":component_supplier",
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:entry_point",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android:activity_retained_lifecycle",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/components:view_model_component",
-        "//java/dagger/hilt/android/internal",
-        "//java/dagger/hilt/android/internal/builders",
-        "//java/dagger/hilt/android/scopes:activity_retained_scoped",
-        "//java/dagger/hilt/android/scopes:view_model_scoped",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:preconditions",
-        "@maven//:androidx_activity_activity",
-        "@maven//:androidx_annotation_annotation",
-        "@maven//:androidx_fragment_fragment",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/internal/managers/BroadcastReceiverComponentManager.java b/java/dagger/hilt/android/internal/managers/BroadcastReceiverComponentManager.java
deleted file mode 100644
index 471c31c..0000000
--- a/java/dagger/hilt/android/internal/managers/BroadcastReceiverComponentManager.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.managers;
-
-import android.app.Application;
-import android.content.Context;
-import dagger.hilt.internal.GeneratedComponentManager;
-import dagger.hilt.internal.Preconditions;
-
-/**
- * Do not use except in Hilt generated code!
- *
- * <p>A manager for the creation of components that live in the BroadcastReceiver.
- */
-public final class BroadcastReceiverComponentManager {
-  @SuppressWarnings("unchecked")
-  public static Object generatedComponent(Context context) {
-    Application application = (Application) context.getApplicationContext();
-
-    Preconditions.checkArgument(
-        application instanceof GeneratedComponentManager,
-        "Hilt BroadcastReceiver must be attached to an @AndroidEntryPoint Application. "
-            + "Found: %s",
-        application.getClass());
-
-    return ((GeneratedComponentManager<?>) application).generatedComponent();
-  }
-
-  private BroadcastReceiverComponentManager() {}
-}
diff --git a/java/dagger/hilt/android/internal/managers/ComponentSupplier.java b/java/dagger/hilt/android/internal/managers/ComponentSupplier.java
deleted file mode 100644
index de702a9..0000000
--- a/java/dagger/hilt/android/internal/managers/ComponentSupplier.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.managers;
-
-/**
- * Interface for supplying a component. This is separate from the Supplier interface so that
- * optimizers can strip this method (and therefore all the Dagger code) from the main dex even if a
- * Supplier is referenced in code kept in the main dex.
- */
-public interface ComponentSupplier {
-  Object get();
-}
diff --git a/java/dagger/hilt/android/internal/managers/FragmentComponentManager.java b/java/dagger/hilt/android/internal/managers/FragmentComponentManager.java
deleted file mode 100644
index 40dd60a..0000000
--- a/java/dagger/hilt/android/internal/managers/FragmentComponentManager.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.managers;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.os.Bundle;
-import androidx.fragment.app.Fragment;
-import android.view.LayoutInflater;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.hilt.android.internal.builders.FragmentComponentBuilder;
-import dagger.hilt.internal.GeneratedComponentManager;
-import dagger.hilt.internal.Preconditions;
-
-/**
- * Do not use except in Hilt generated code!
- *
- * <p>A manager for the creation of components that live in the Fragment.
- *
- * <p>Note: This class is not typed since its type in generated code is always <?> or <Object>. This
- * is mainly due to the fact that we don't know the components at the time of generation, and
- * because even the injector interface type is not a valid type if we have a hilt base class.
- *
- */
-public class FragmentComponentManager implements GeneratedComponentManager<Object> {
-  /** Entrypoint for {@link FragmentComponentBuilder}. */
-  @EntryPoint
-  @InstallIn(ActivityComponent.class)
-  public interface FragmentComponentBuilderEntryPoint {
-    FragmentComponentBuilder fragmentComponentBuilder();
-  }
-
-  private volatile Object component;
-  private final Object componentLock = new Object();
-  private final Fragment fragment;
-
-  public FragmentComponentManager(Fragment fragment) {
-    this.fragment = fragment;
-  }
-
-  @Override
-  public Object generatedComponent() {
-    if (component == null) {
-      synchronized (componentLock) {
-        if (component == null) {
-          component = createComponent();
-        }
-      }
-    }
-    return component;
-  }
-
-  private Object createComponent() {
-    Preconditions.checkNotNull(
-        fragment.getHost(),
-    "Hilt Fragments must be attached before creating the component.");
-    Preconditions.checkState(
-        fragment.getHost() instanceof GeneratedComponentManager,
-        "Hilt Fragments must be attached to an @AndroidEntryPoint Activity. Found: %s",
-        fragment.getHost().getClass());
-
-    validate(fragment);
-
-    return EntryPoints.get(fragment.getHost(), FragmentComponentBuilderEntryPoint.class)
-        .fragmentComponentBuilder()
-        .fragment(fragment)
-        .build();
-  }
-
-  /** Returns the fragments bundle, creating a new one if none exists. */
-  public static final void initializeArguments(Fragment fragment) {
-    Preconditions.checkNotNull(fragment);
-    if (fragment.getArguments() == null) {
-      fragment.setArguments(new Bundle());
-    }
-  }
-
-  public static final Context findActivity(Context context) {
-    while (context instanceof ContextWrapper
-        && !(context instanceof Activity)) {
-      context = ((ContextWrapper) context).getBaseContext();
-    }
-    return context;
-  }
-
-  public static ContextWrapper createContextWrapper(Context base, Fragment fragment) {
-    return new ViewComponentManager.FragmentContextWrapper(base, fragment);
-  }
-
-  public static ContextWrapper createContextWrapper(
-      LayoutInflater baseInflater, Fragment fragment) {
-    return new ViewComponentManager.FragmentContextWrapper(baseInflater, fragment);
-  }
-
-  /** Called immediately before component creation to allow validation on the Fragment. */
-  protected void validate(Fragment fragment) {
-  }
-}
diff --git a/java/dagger/hilt/android/internal/managers/ServiceComponentManager.java b/java/dagger/hilt/android/internal/managers/ServiceComponentManager.java
deleted file mode 100644
index d5e7f15..0000000
--- a/java/dagger/hilt/android/internal/managers/ServiceComponentManager.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.managers;
-
-import android.app.Application;
-import android.app.Service;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.internal.builders.ServiceComponentBuilder;
-import dagger.hilt.components.SingletonComponent;
-import dagger.hilt.internal.GeneratedComponentManager;
-import dagger.hilt.internal.Preconditions;
-
-/**
- * Do not use except in Hilt generated code!
- *
- * <p>A manager for the creation of components that live in the Service.
- *
- * <p>Note: This class is not typed since its type in generated code is always <?> or <Object>. This
- * is mainly due to the fact that we don't know the components at the time of generation, and
- * because even the injector interface type is not a valid type if we have a hilt base class.
- */
-public final class ServiceComponentManager implements GeneratedComponentManager<Object> {
-  /** Entrypoint for {@link ServiceComponentBuilder}. */
-  @EntryPoint
-  @InstallIn(SingletonComponent.class)
-  public interface ServiceComponentBuilderEntryPoint {
-    ServiceComponentBuilder serviceComponentBuilder();
-  }
-
-  private final Service service;
-  private Object component;
-
-  public ServiceComponentManager(Service service) {
-    this.service = service;
-  }
-
-  // This isn't ever really publicly exposed on a service so it should be fine without
-  // synchronization.
-  @Override
-  public Object generatedComponent() {
-    if (component == null) {
-      component = createComponent();
-    }
-    return component;
-  }
-
-  private Object createComponent() {
-    Application application = service.getApplication();
-    Preconditions.checkState(
-        application instanceof GeneratedComponentManager,
-        "Hilt service must be attached to an @AndroidEntryPoint Application. Found: %s",
-        application.getClass());
-
-    return EntryPoints.get(application, ServiceComponentBuilderEntryPoint.class)
-        .serviceComponentBuilder()
-        .service(service)
-        .build();
-  }
-}
diff --git a/java/dagger/hilt/android/internal/managers/ViewComponentManager.java b/java/dagger/hilt/android/internal/managers/ViewComponentManager.java
deleted file mode 100644
index cb2ece0..0000000
--- a/java/dagger/hilt/android/internal/managers/ViewComponentManager.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.managers;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import androidx.fragment.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.hilt.android.components.FragmentComponent;
-import dagger.hilt.android.internal.builders.ViewComponentBuilder;
-import dagger.hilt.android.internal.builders.ViewWithFragmentComponentBuilder;
-import dagger.hilt.internal.GeneratedComponentManager;
-import dagger.hilt.internal.Preconditions;
-
-/**
- * Do not use except in Hilt generated code!
- *
- * <p>A manager for the creation of components that live in the View.
- *
- * <p>Note: This class is not typed since its type in generated code is always <?> or <Object>. This
- * is mainly due to the fact that we don't know the components at the time of generation, and
- * because even the injector interface type is not a valid type if we have a hilt base class.
- */
-public final class ViewComponentManager implements GeneratedComponentManager<Object> {
-  /** Entrypoint for {@link ViewWithFragmentComponentBuilder}. */
-  @EntryPoint
-  @InstallIn(FragmentComponent.class)
-  public interface ViewWithFragmentComponentBuilderEntryPoint {
-    ViewWithFragmentComponentBuilder viewWithFragmentComponentBuilder();
-  }
-
-  /** Entrypoint for {@link ViewComponentBuilder}. */
-  @EntryPoint
-  @InstallIn(ActivityComponent.class)
-  public interface ViewComponentBuilderEntryPoint {
-    ViewComponentBuilder viewComponentBuilder();
-  }
-
-  private volatile Object component;
-  private final Object componentLock = new Object();
-  private final boolean hasFragmentBindings;
-  private final View view;
-
-  public ViewComponentManager(View view, boolean hasFragmentBindings) {
-    this.view = view;
-    this.hasFragmentBindings = hasFragmentBindings;
-  }
-
-  @Override
-  public Object generatedComponent() {
-    if (component == null) {
-      synchronized (componentLock) {
-        if (component == null) {
-          component = createComponent();
-        }
-      }
-    }
-    return component;
-  }
-
-  private Object createComponent() {
-    GeneratedComponentManager<?> componentManager =
-        getParentComponentManager(/*allowMissing=*/ false);
-    if (hasFragmentBindings) {
-      return EntryPoints.get(componentManager, ViewWithFragmentComponentBuilderEntryPoint.class)
-          .viewWithFragmentComponentBuilder()
-          .view(view)
-          .build();
-    } else {
-      return EntryPoints.get(componentManager, ViewComponentBuilderEntryPoint.class)
-          .viewComponentBuilder()
-          .view(view)
-          .build();
-    }
-  }
-
-  /* Returns the component manager of the parent or null if not found. */
-  public GeneratedComponentManager<?> maybeGetParentComponentManager() {
-    return getParentComponentManager(/*allowMissing=*/ true);
-  }
-
-  private GeneratedComponentManager<?> getParentComponentManager(boolean allowMissing) {
-    if (hasFragmentBindings) {
-      Context context = getParentContext(FragmentContextWrapper.class, allowMissing);
-      if (context instanceof FragmentContextWrapper) {
-
-        FragmentContextWrapper fragmentContextWrapper = (FragmentContextWrapper) context;
-        return (GeneratedComponentManager<?>) fragmentContextWrapper.fragment;
-      } else if (allowMissing) {
-        // We didn't find anything, so return null if we're not supposed to fail.
-        // The rest of the logic is just about getting a good error message.
-        return null;
-      }
-
-      // Check if there was a valid parent component, just not a Fragment, to give a more
-      // specific error.
-      Context parent = getParentContext(GeneratedComponentManager.class, allowMissing);
-      Preconditions.checkState(
-          !(parent instanceof GeneratedComponentManager),
-          "%s, @WithFragmentBindings Hilt view must be attached to an "
-              + "@AndroidEntryPoint Fragment. "
-              + "Was attached to context %s",
-          view.getClass(),
-          parent.getClass().getName());
-    } else {
-      Context context = getParentContext(GeneratedComponentManager.class, allowMissing);
-      if (context instanceof GeneratedComponentManager) {
-        return (GeneratedComponentManager<?>) context;
-      } else if (allowMissing) {
-        return null;
-      }
-    }
-
-    // Couldn't find any parent components to descend from.
-    throw new IllegalStateException(
-        String.format(
-            "%s, Hilt view must be attached to an @AndroidEntryPoint Fragment or Activity.",
-            view.getClass()));
-
-  }
-
-  private Context getParentContext(Class<?> parentType, boolean allowMissing) {
-    Context context = unwrap(view.getContext(), parentType);
-    if (context == unwrap(context.getApplicationContext(), GeneratedComponentManager.class)) {
-      // If we searched for a type but ended up on the application context, just return null
-      // as this is never what we are looking for
-      Preconditions.checkState(
-          allowMissing,
-          "%s, Hilt view cannot be created using the application context. "
-             + "Use a Hilt Fragment or Activity context.",
-          view.getClass());
-      return null;
-    }
-    return context;
-  }
-
-  private static Context unwrap(Context context, Class<?> target) {
-    while (context instanceof ContextWrapper && !target.isInstance(context)) {
-      context = ((ContextWrapper) context).getBaseContext();
-    }
-    return context;
-  }
-
-  /**
-   * Do not use except in Hilt generated code!
-   *
-   * <p>A wrapper class to expose the {@link Fragment} to the views they're inflating.
-   */
-  // This is only non-final for the account override
-  public static final class FragmentContextWrapper extends ContextWrapper {
-    private LayoutInflater baseInflater;
-    private LayoutInflater inflater;
-    public final Fragment fragment;
-
-    public FragmentContextWrapper(Context base, Fragment fragment) {
-      super(Preconditions.checkNotNull(base));
-      this.baseInflater = null;
-      this.fragment = Preconditions.checkNotNull(fragment);
-    }
-
-    public FragmentContextWrapper(LayoutInflater baseInflater, Fragment fragment) {
-      super(Preconditions.checkNotNull(Preconditions.checkNotNull(baseInflater).getContext()));
-      this.baseInflater = baseInflater;
-      this.fragment = Preconditions.checkNotNull(fragment);
-    }
-
-    @Override
-    public Object getSystemService(String name) {
-      if (!LAYOUT_INFLATER_SERVICE.equals(name)) {
-        return getBaseContext().getSystemService(name);
-      }
-      if (inflater == null) {
-        if (baseInflater == null) {
-          baseInflater =
-              (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
-        }
-        inflater = baseInflater.cloneInContext(this);
-      }
-      return inflater;
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/internal/migration/BUILD b/java/dagger/hilt/android/internal/migration/BUILD
deleted file mode 100644
index b877f6f..0000000
--- a/java/dagger/hilt/android/internal/migration/BUILD
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Internal classes for migration
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "injected_by_hilt",
-    srcs = ["InjectedByHilt.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/internal/migration/InjectedByHilt.java b/java/dagger/hilt/android/internal/migration/InjectedByHilt.java
deleted file mode 100644
index 087a7ee..0000000
--- a/java/dagger/hilt/android/internal/migration/InjectedByHilt.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.migration;
-
-/**
- * Do not use except in Hilt generated code!
- */
-public interface InjectedByHilt {
-  /** Returns true if this class was injected by Hilt. */
-  boolean wasInjectedByHilt();
-}
diff --git a/java/dagger/hilt/android/internal/modules/ActivityModule.java b/java/dagger/hilt/android/internal/modules/ActivityModule.java
deleted file mode 100644
index 080e203..0000000
--- a/java/dagger/hilt/android/internal/modules/ActivityModule.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.modules;
-
-import android.app.Activity;
-import android.content.Context;
-import androidx.fragment.app.FragmentActivity;
-import dagger.Binds;
-import dagger.Module;
-import dagger.Provides;
-import dagger.Reusable;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.hilt.android.qualifiers.ActivityContext;
-
-/** Provides convenience bindings for activities. */
-@Module
-@InstallIn(ActivityComponent.class)
-abstract class ActivityModule {
-  @Binds
-  @ActivityContext
-  abstract Context provideContext(Activity activity);
-
-  @Provides
-  @Reusable
-  static FragmentActivity provideFragmentActivity(Activity activity) {
-    try {
-      return (FragmentActivity) activity;
-    } catch (ClassCastException e) {
-      throw new IllegalStateException("Expected activity to be a FragmentActivity: " + activity, e);
-    }
-  }
-
-  private ActivityModule() {}
-}
diff --git a/java/dagger/hilt/android/internal/modules/ApplicationContextModule.java b/java/dagger/hilt/android/internal/modules/ApplicationContextModule.java
deleted file mode 100644
index af4ebc2..0000000
--- a/java/dagger/hilt/android/internal/modules/ApplicationContextModule.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.internal.modules;
-
-import android.app.Application;
-import android.content.Context;
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.qualifiers.ApplicationContext;
-import dagger.hilt.components.SingletonComponent;
-
-/** Provides a binding for an Android BinderFragment Context. */
-@Module
-@InstallIn(SingletonComponent.class)
-public final class ApplicationContextModule {
-  private final Context applicationContext;
-
-  public ApplicationContextModule(Context applicationContext) {
-    this.applicationContext = applicationContext;
-  }
-
-  @Provides
-  @ApplicationContext
-  Context provideContext() {
-    return applicationContext;
-  }
-
-  @Provides
-  Application provideApplication() {
-    return (Application) applicationContext.getApplicationContext();
-  }
-}
diff --git a/java/dagger/hilt/android/internal/modules/BUILD b/java/dagger/hilt/android/internal/modules/BUILD
deleted file mode 100644
index a36e237..0000000
--- a/java/dagger/hilt/android/internal/modules/BUILD
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Hilt android modules for standard components.
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "modules",
-    srcs = glob(["*.java"]),
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/qualifiers",
-        "@maven//:androidx_activity_activity",
-        "@maven//:androidx_annotation_annotation",
-        "@maven//:androidx_fragment_fragment",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/internal/testing/BUILD b/java/dagger/hilt/android/internal/testing/BUILD
deleted file mode 100644
index b0bc361..0000000
--- a/java/dagger/hilt/android/internal/testing/BUILD
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Internal Hilt android testing libraries
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "test_injector",
-    testonly = 1,
-    srcs = [
-        "TestApplicationInjector.java",
-        "TestInjector.java",
-    ],
-)
-
-android_library(
-    name = "internal_test_root",
-    srcs = [
-        "InternalTestRoot.java",
-    ],
-    deps = [
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-android_library(
-    name = "test_application_component_manager",
-    testonly = 1,
-    srcs = ["TestApplicationComponentManager.java"],
-    deps = [
-        ":test_component_data",
-        ":test_injector",
-        "//java/dagger/hilt/android/testing:on_component_ready_runner",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:preconditions",
-        "@maven//:junit_junit",
-    ],
-)
-
-android_library(
-    name = "test_component_data",
-    testonly = 1,
-    srcs = [
-        "TestComponentData.java",
-        "TestComponentDataSupplier.java",
-    ],
-    deps = [
-        ":test_injector",
-        "//java/dagger/hilt/internal:component_manager",
-    ],
-)
-
-android_library(
-    name = "test_application_component_manager_holder",
-    testonly = 1,
-    srcs = ["TestApplicationComponentManagerHolder.java"],
-)
-
-android_library(
-    name = "mark_that_rules_ran_rule",
-    testonly = 1,
-    srcs = ["MarkThatRulesRanRule.java"],
-    deps = [
-        ":test_application_component_manager",
-        ":test_application_component_manager_holder",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:preconditions",
-        "@maven//:androidx_test_core",
-        "@maven//:junit_junit",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["**/*"]),
-)
diff --git a/java/dagger/hilt/android/internal/testing/InternalTestRoot.java b/java/dagger/hilt/android/internal/testing/InternalTestRoot.java
deleted file mode 100644
index c3bbf0c..0000000
--- a/java/dagger/hilt/android/internal/testing/InternalTestRoot.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.testing;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import android.app.Application;
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/** Annotation that generates a Hilt test application. */
-@Retention(CLASS)
-@Target({ElementType.TYPE})
-@GeneratesRootInput
-public @interface InternalTestRoot {
-
-  /** Returns the test class. */
-  Class<?> testClass();
-
-  /** Returns the base {@link Application} class.  */
-  Class<? extends Application> applicationBaseClass();
-}
diff --git a/java/dagger/hilt/android/internal/testing/MarkThatRulesRanRule.java b/java/dagger/hilt/android/internal/testing/MarkThatRulesRanRule.java
deleted file mode 100644
index 17c40b3..0000000
--- a/java/dagger/hilt/android/internal/testing/MarkThatRulesRanRule.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.testing;
-
-import static dagger.hilt.internal.Preconditions.checkNotNull;
-import static dagger.hilt.internal.Preconditions.checkState;
-
-import android.content.Context;
-import androidx.test.core.app.ApplicationProvider;
-import dagger.hilt.internal.GeneratedComponentManager;
-import java.lang.annotation.Annotation;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-/**
- * A Junit {@code TestRule} that's installed in all Hilt tests.
- *
- * <p>This rule enforces that a Hilt TestRule has run. The Dagger component will not be created
- * without this test rule.
- */
-public final class MarkThatRulesRanRule implements TestRule {
-  private static final String HILT_ANDROID_APP = "dagger.hilt.android.HiltAndroidApp";
-  private static final String HILT_ANDROID_TEST = "dagger.hilt.android.testing.HiltAndroidTest";
-
-  private final Context context = ApplicationProvider.getApplicationContext();
-  private final Object testInstance;
-  private final boolean autoAddModule;
-
-  private final AtomicBoolean started = new AtomicBoolean(false);
-
-  public MarkThatRulesRanRule(Object testInstance) {
-    this.autoAddModule = true;
-    this.testInstance = checkNotNull(testInstance);
-    checkState(
-        hasAnnotation(testInstance, HILT_ANDROID_TEST),
-        "Expected %s to be annotated with @HiltAndroidTest.",
-        testInstance.getClass().getName());
-    checkState(
-        context instanceof GeneratedComponentManager,
-        "Hilt test, %s, must use a Hilt test application but found %s. To fix, configure the test "
-            + "to use HiltTestApplication or a custom Hilt test application generated with "
-            + "@CustomTestApplication.",
-        testInstance.getClass().getName(),
-        context.getClass().getName());
-    checkState(
-        !hasAnnotation(context, HILT_ANDROID_APP),
-        "Hilt test, %s, cannot use a @HiltAndroidApp application but found %s. To fix, configure "
-            + "the test to use HiltTestApplication or a custom Hilt test application generated "
-            +  "with @CustomTestApplication.",
-        testInstance.getClass().getName(),
-        context.getClass().getName());
-  }
-
-  public void delayComponentReady() {
-    checkState(!started.get(), "Called delayComponentReady after test execution started");
-    getTestApplicationComponentManager().delayComponentReady();
-  }
-
-  public void componentReady() {
-    checkState(started.get(), "Called componentReady before test execution started");
-    getTestApplicationComponentManager().componentReady();
-  }
-
-  public void inject() {
-    getTestApplicationComponentManager().inject();
-  }
-
-  @Override
-  public Statement apply(final Statement base, Description description) {
-    started.set(true);
-    checkState(
-        description.getTestClass().isInstance(testInstance),
-        "HiltAndroidRule was constructed with an argument that was not an instance of the test"
-            + " class");
-    return new Statement() {
-      @Override
-      public void evaluate() throws Throwable {
-
-        TestApplicationComponentManager componentManager = getTestApplicationComponentManager();
-        try {
-          // This check is required to check that state hasn't been set before this rule runs. This
-          // prevents cases like setting state in Application.onCreate for Gradle emulator tests
-          // that will get cleared after running the first test case.
-          componentManager.checkStateIsCleared();
-          componentManager.setAutoAddModule(autoAddModule);
-          if (testInstance != null) {
-            componentManager.setTestInstance(testInstance);
-          }
-          componentManager.setHasHiltTestRule(description);
-          base.evaluate();
-          componentManager.verifyDelayedComponentWasMadeReady();
-        } finally {
-          componentManager.clearState();
-        }
-      }
-    };
-  }
-
-  private TestApplicationComponentManager getTestApplicationComponentManager() {
-    checkState(
-        context instanceof TestApplicationComponentManagerHolder,
-        "The context is not an instance of TestApplicationComponentManagerHolder: %s",
-        context);
-    Object componentManager = ((TestApplicationComponentManagerHolder) context).componentManager();
-    checkState(
-        componentManager instanceof TestApplicationComponentManager,
-        "Expected TestApplicationComponentManagerHolder to return an instance of"
-            + "TestApplicationComponentManager");
-    return (TestApplicationComponentManager) componentManager;
-  }
-
-  private static boolean hasAnnotation(Object obj, String annotationName) {
-    for (Annotation annotation : obj.getClass().getAnnotations()) {
-      if (annotation.annotationType().getName().contentEquals(annotationName)) {
-        return true;
-      }
-    }
-    return false;
-  }
-}
diff --git a/java/dagger/hilt/android/internal/testing/TestApplicationComponentManager.java b/java/dagger/hilt/android/internal/testing/TestApplicationComponentManager.java
deleted file mode 100644
index 1878870..0000000
--- a/java/dagger/hilt/android/internal/testing/TestApplicationComponentManager.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.testing;
-
-import android.app.Application;
-import dagger.hilt.android.testing.OnComponentReadyRunner;
-import dagger.hilt.android.testing.OnComponentReadyRunner.OnComponentReadyRunnerHolder;
-import dagger.hilt.internal.GeneratedComponentManager;
-import dagger.hilt.internal.Preconditions;
-import java.lang.reflect.InvocationTargetException;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicReference;
-import org.junit.runner.Description;
-
-/**
- * Do not use except in Hilt generated code!
- *
- * <p>A manager for the creation of components that live in the test Application.
- */
-public final class TestApplicationComponentManager
-    implements GeneratedComponentManager<Object>, OnComponentReadyRunnerHolder {
-
-  // This is a generated class that we always generate in a known location.
-  private static final String TEST_COMPONENT_DATA_SUPPLIER_IMPL =
-      "dagger.hilt.android.internal.testing.TestComponentDataSupplierImpl";
-
-  private final Application application;
-  private final Map<Class<?>, TestComponentData> testComponentDataSupplier;
-
-  private final AtomicReference<Object> component = new AtomicReference<>();
-  private final AtomicReference<Description> hasHiltTestRule = new AtomicReference<>();
-  private final Map<Class<?>, Object> registeredModules = new ConcurrentHashMap<>();
-  private final AtomicReference<Boolean> autoAddModuleEnabled = new AtomicReference<>();
-  private final AtomicReference<DelayedComponentState> delayedComponentState =
-      new AtomicReference<>(DelayedComponentState.NOT_DELAYED);
-  private volatile Object testInstance;
-  private volatile OnComponentReadyRunner onComponentReadyRunner = new OnComponentReadyRunner();
-
-  /**
-   * Represents the state of Component readiness. There are two valid transition sequences.
-   *
-   * <ul>
-   *   <li>Typical test (no HiltAndroidRule#delayComponentReady): {@code NOT_DELAYED -> INJECTED}
-   *   <li>Using HiltAndroidRule#delayComponentReady: {@code NOT_DELAYED -> COMPONENT_DELAYED ->
-   *       COMPONENT_READY -> INJECTED}
-   * </ul>
-   */
-  private enum DelayedComponentState {
-    // Valid transitions: COMPONENT_DELAYED, INJECTED
-    NOT_DELAYED,
-    // Valid transitions: COMPONENT_READY
-    COMPONENT_DELAYED,
-    // Valid transitions: INJECTED
-    COMPONENT_READY,
-    // Terminal state
-    INJECTED
-  }
-
-  public TestApplicationComponentManager(Application application) {
-    this.application = application;
-    try {
-      this.testComponentDataSupplier =
-          Class.forName(TEST_COMPONENT_DATA_SUPPLIER_IMPL)
-              .asSubclass(TestComponentDataSupplier.class)
-              .getDeclaredConstructor()
-              .newInstance()
-              .get();
-    } catch (ClassNotFoundException
-        | NoSuchMethodException
-        | IllegalAccessException
-        | InstantiationException
-        | InvocationTargetException e) {
-      throw new RuntimeException(
-          "Hilt classes generated from @HiltAndroidTest are missing. Check that you have annotated "
-              + "your test class with @HiltAndroidTest and that the processor is running over your "
-              + "test",
-          e);
-    }
-  }
-
-  @Override
-  public Object generatedComponent() {
-    if (component.get() == null) {
-      Preconditions.checkState(
-          hasHiltTestRule(),
-      "The component was not created. Check that you have added the HiltAndroidRule.");
-      if (!registeredModules.keySet().containsAll(requiredModules())) {
-        Set<Class<?>> difference = new HashSet<>(requiredModules());
-        difference.removeAll(registeredModules.keySet());
-        throw new IllegalStateException(
-            "The component was not created. Check that you have "
-                + "registered all test modules:\n\tUnregistered: "
-                + difference);
-      }
-      Preconditions.checkState(
-          bindValueReady(), "The test instance has not been set. Did you forget to call #bind()?");
-      throw new IllegalStateException(
-          "The component has not been created. "
-              + "Check that you have called #inject()? Otherwise, "
-              + "there is a race between injection and component creation. Make sure there is a "
-              + "happens-before edge between the HiltAndroidRule/registering"
-              + " all test modules and the first injection.");
-    }
-    return component.get();
-  }
-
-  @Override
-  public OnComponentReadyRunner getOnComponentReadyRunner() {
-    return onComponentReadyRunner;
-  }
-
-  /** For framework use only! This flag must be set before component creation. */
-  void setHasHiltTestRule(Description description) {
-    Preconditions.checkState(
-        // Some exempted tests set the test rule multiple times. Use CAS to avoid setting twice.
-        hasHiltTestRule.compareAndSet(null, description),
-        "The hasHiltTestRule flag has already been set!");
-    tryToCreateComponent();
-  }
-
-  void checkStateIsCleared() {
-    Preconditions.checkState(
-        component.get() == null,
-        "The Hilt component cannot be set before Hilt's test rule has run.");
-    Preconditions.checkState(
-        hasHiltTestRule.get() == null,
-        "The Hilt test rule cannot be set before Hilt's test rule has run.");
-    Preconditions.checkState(
-        autoAddModuleEnabled.get() == null,
-        "The Hilt autoAddModuleEnabled cannot be set before Hilt's test rule has run.");
-    Preconditions.checkState(
-        testInstance == null,
-        "The Hilt BindValue instance cannot be set before Hilt's test rule has run.");
-    Preconditions.checkState(
-        registeredModules.isEmpty(),
-        "The Hilt registered modules cannot be set before Hilt's test rule has run.");
-    Preconditions.checkState(
-        onComponentReadyRunner.isEmpty(),
-        "The Hilt onComponentReadyRunner cannot add listeners before Hilt's test rule has run.");
-    DelayedComponentState state = delayedComponentState.get();
-    switch (state) {
-      case NOT_DELAYED:
-      case COMPONENT_DELAYED:
-        // Expected
-        break;
-      case COMPONENT_READY:
-        throw new IllegalStateException("Called componentReady before test execution started");
-      case INJECTED:
-        throw new IllegalStateException("Called inject before test execution started");
-    }
-  }
-
-  void clearState() {
-    component.set(null);
-    hasHiltTestRule.set(null);
-    testInstance = null;
-    registeredModules.clear();
-    autoAddModuleEnabled.set(null);
-    delayedComponentState.set(DelayedComponentState.NOT_DELAYED);
-    onComponentReadyRunner = new OnComponentReadyRunner();
-  }
-
-  public Description getDescription() {
-    return hasHiltTestRule.get();
-  }
-
-  public Object getTestInstance() {
-    Preconditions.checkState(
-        testInstance != null,
-        "The test instance has not been set.");
-    return testInstance;
-  }
-
-  /** For framework use only! This method should be called when a required module is installed. */
-  public <T> void registerModule(Class<T> moduleClass, T module) {
-    Preconditions.checkNotNull(moduleClass);
-    Preconditions.checkState(
-        testComponentData().daggerRequiredModules().contains(moduleClass),
-        "Found unknown module class: %s",
-        moduleClass.getName());
-    if (requiredModules().contains(moduleClass)) {
-      Preconditions.checkState(
-          // Some exempted tests register modules multiple times.
-          !registeredModules.containsKey(moduleClass),
-          "Module is already registered: %s",
-          moduleClass.getName());
-
-      registeredModules.put(moduleClass, module);
-      tryToCreateComponent();
-    }
-  }
-
-  void delayComponentReady() {
-    switch (delayedComponentState.getAndSet(DelayedComponentState.COMPONENT_DELAYED)) {
-      case NOT_DELAYED:
-        // Expected
-        break;
-      case COMPONENT_DELAYED:
-        throw new IllegalStateException("Called delayComponentReady() twice");
-      case COMPONENT_READY:
-        throw new IllegalStateException("Called delayComponentReady() after componentReady()");
-      case INJECTED:
-        throw new IllegalStateException("Called delayComponentReady() after inject()");
-    }
-  }
-
-  void componentReady() {
-    switch (delayedComponentState.getAndSet(DelayedComponentState.COMPONENT_READY)) {
-      case NOT_DELAYED:
-        throw new IllegalStateException(
-            "Called componentReady(), even though delayComponentReady() was not used.");
-      case COMPONENT_DELAYED:
-        // Expected
-        break;
-      case COMPONENT_READY:
-        throw new IllegalStateException("Called componentReady() multiple times");
-      case INJECTED:
-        throw new IllegalStateException("Called componentReady() after inject()");
-    }
-    tryToCreateComponent();
-  }
-
-  void inject() {
-    switch (delayedComponentState.getAndSet(DelayedComponentState.INJECTED)) {
-      case NOT_DELAYED:
-      case COMPONENT_READY:
-        // Expected
-        break;
-      case COMPONENT_DELAYED:
-        throw new IllegalStateException("Called inject() before calling componentReady()");
-      case INJECTED:
-        throw new IllegalStateException("Called inject() multiple times");
-    }
-    Preconditions.checkNotNull(testInstance);
-    testInjector().injectTest(testInstance);
-  }
-
-  void verifyDelayedComponentWasMadeReady() {
-    Preconditions.checkState(
-        delayedComponentState.get() != DelayedComponentState.COMPONENT_DELAYED,
-        "Used delayComponentReady(), but never called componentReady()");
-  }
-
-  private void tryToCreateComponent() {
-    if (hasHiltTestRule()
-        && registeredModules.keySet().containsAll(requiredModules())
-        && bindValueReady()
-        && delayedComponentReady()) {
-      Preconditions.checkState(
-          autoAddModuleEnabled.get() !=  null,
-          "Component cannot be created before autoAddModuleEnabled is set.");
-      Preconditions.checkState(
-          component.compareAndSet(
-              null,
-              componentSupplier().get(registeredModules, testInstance, autoAddModuleEnabled.get())),
-          "Tried to create the component more than once! "
-              + "There is a race between registering the HiltAndroidRule and registering"
-              + " all test modules. Make sure there is a happens-before edge between the two.");
-      onComponentReadyRunner.setComponentManager((GeneratedComponentManager) application);
-    }
-  }
-
-  void setTestInstance(Object testInstance) {
-    Preconditions.checkNotNull(testInstance);
-    Preconditions.checkState(this.testInstance == null, "The test instance was already set!");
-    this.testInstance = testInstance;
-  }
-
-  void setAutoAddModule(boolean autoAddModule) {
-    Preconditions.checkState(
-        autoAddModuleEnabled.get() == null, "autoAddModuleEnabled is already set!");
-    autoAddModuleEnabled.set(autoAddModule);
-  }
-
-  private Set<Class<?>> requiredModules() {
-    return autoAddModuleEnabled.get()
-        ? testComponentData().hiltRequiredModules()
-        : testComponentData().daggerRequiredModules();
-  }
-
-  private boolean waitForBindValue() {
-    return testComponentData().waitForBindValue();
-  }
-
-  private TestInjector<Object> testInjector() {
-    return testComponentData().testInjector();
-  }
-
-  private TestComponentData.ComponentSupplier componentSupplier() {
-    return testComponentData().componentSupplier();
-  }
-
-  private TestComponentData testComponentData() {
-    return testComponentDataSupplier.get(testClass());
-  }
-
-  private Class<?> testClass() {
-    Preconditions.checkState(
-        hasHiltTestRule(),
-    "Test must have an HiltAndroidRule.");
-    return hasHiltTestRule.get().getTestClass();
-  }
-
-  private boolean bindValueReady() {
-    return !waitForBindValue() || testInstance != null;
-  }
-
-  private boolean delayedComponentReady() {
-    return delayedComponentState.get() != DelayedComponentState.COMPONENT_DELAYED;
-  }
-
-  private boolean hasHiltTestRule() {
-    return hasHiltTestRule.get() != null;
-  }
-}
diff --git a/java/dagger/hilt/android/internal/testing/TestApplicationComponentManagerHolder.java b/java/dagger/hilt/android/internal/testing/TestApplicationComponentManagerHolder.java
deleted file mode 100644
index a8695c4..0000000
--- a/java/dagger/hilt/android/internal/testing/TestApplicationComponentManagerHolder.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.testing;
-
-/** For use by Hilt internally only! Returns the component manager. */
-public interface TestApplicationComponentManagerHolder {
-  // Returns {@link Object} so that we do not expose {@code TestApplicationComponentManager} to
-  // clients. Framework code should explicitly cast to {@code TestApplicationComponentManager}.
-  Object componentManager();
-}
diff --git a/java/dagger/hilt/android/internal/testing/TestApplicationInjector.java b/java/dagger/hilt/android/internal/testing/TestApplicationInjector.java
deleted file mode 100644
index c7ff5c9..0000000
--- a/java/dagger/hilt/android/internal/testing/TestApplicationInjector.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.testing;
-
-/**
- * Interface to expose a method for members injection for use in tests.
- */
-public interface TestApplicationInjector<T> {
-  void injectApp(T t);
-}
diff --git a/java/dagger/hilt/android/internal/testing/TestComponentData.java b/java/dagger/hilt/android/internal/testing/TestComponentData.java
deleted file mode 100644
index 4eed6fb..0000000
--- a/java/dagger/hilt/android/internal/testing/TestComponentData.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.testing;
-
-import dagger.hilt.internal.Preconditions;
-import java.util.Map;
-import java.util.Set;
-
-/** Contains the data needed to create a test's component. */
-public final class TestComponentData {
-  private final ComponentSupplier componentSupplier;
-  private final TestInjector<Object> testInjector;
-  private final Set<Class<?>> daggerRequiredModules;
-  private final Set<Class<?>> hiltRequiredModules;
-  private final boolean waitForBindValue;
-
-  public TestComponentData(
-      boolean waitForBindValue,
-      TestInjector<Object> testInjector,
-      Set<Class<?>> daggerRequiredModules,
-      Set<Class<?>> hiltRequiredModules,
-      ComponentSupplier componentSupplier) {
-    Preconditions.checkState(
-        daggerRequiredModules.containsAll(hiltRequiredModules),
-        "Hilt required modules should be subset of Dagger required modules.");
-    this.componentSupplier = componentSupplier;
-    this.testInjector = testInjector;
-    this.daggerRequiredModules = daggerRequiredModules;
-    this.waitForBindValue = waitForBindValue;
-    this.hiltRequiredModules = hiltRequiredModules;
-  }
-
-  /** Returns the {@link ComponentSupplier}. */
-  public ComponentSupplier componentSupplier() {
-    return componentSupplier;
-  }
-
-  /** Returns the {@link TestInjector}. */
-  public TestInjector<Object> testInjector() {
-    return testInjector;
-  }
-
-  /** Returns the set of modules that Dagger cannot create instances of itself */
-  public Set<Class<?>> daggerRequiredModules() {
-    return daggerRequiredModules;
-  }
-
-  /**
-   * Returns a subset of {@link #daggerRequiredModules} that filters out the modules Hilt can
-   * instantiate itself.
-   */
-  public Set<Class<?>> hiltRequiredModules() {
-    return hiltRequiredModules;
-  }
-
-  /** Returns true if creation of the component needs to wait for bind() to be called. */
-  public boolean waitForBindValue() {
-    return waitForBindValue;
-  }
-
-  /** Returns the component using the given registered modules. */
-  public interface ComponentSupplier {
-    Object get(Map<Class<?>, ?> registeredModules, Object testInstance, Boolean autoAddModule);
-  }
-}
diff --git a/java/dagger/hilt/android/internal/testing/TestComponentDataSupplier.java b/java/dagger/hilt/android/internal/testing/TestComponentDataSupplier.java
deleted file mode 100644
index e39073f..0000000
--- a/java/dagger/hilt/android/internal/testing/TestComponentDataSupplier.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.testing;
-
-import java.util.Map;
-
-/** Stores the {@link TestComponentData} for all Hilt test classes. */
-public abstract class TestComponentDataSupplier {
-
-  /** Returns a map of {@link TestComponentData} keyed by test class. */
-  protected abstract Map<Class<?>, TestComponentData> get();
-}
diff --git a/java/dagger/hilt/android/internal/testing/TestInjector.java b/java/dagger/hilt/android/internal/testing/TestInjector.java
deleted file mode 100644
index 7055f91..0000000
--- a/java/dagger/hilt/android/internal/testing/TestInjector.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.internal.testing;
-
-/**
- * Interface to expose a method for members injection for use in tests.
- */
-public interface TestInjector<T> {
-  void injectTest(T t);
-}
diff --git a/java/dagger/hilt/android/lifecycle/BUILD b/java/dagger/hilt/android/lifecycle/BUILD
deleted file mode 100644
index fd80510..0000000
--- a/java/dagger/hilt/android/lifecycle/BUILD
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Hilt ViewModel integration.
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "lifecycle",
-    srcs = glob(["*.java"]),
-    exported_plugins = [
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor",
-    ],
-    proguard_specs = ["proguard-rules.pro"],
-    exports = [
-        "//java/dagger/hilt/android/components:view_model_component",
-        "//java/dagger/hilt/android/internal/lifecycle",
-    ],
-    deps = [
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/lifecycle/HiltViewModel.java b/java/dagger/hilt/android/lifecycle/HiltViewModel.java
deleted file mode 100644
index 198ec8a..0000000
--- a/java/dagger/hilt/android/lifecycle/HiltViewModel.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.lifecycle;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Identifies a {@link androidx.lifecycle.ViewModel} for construction injection.
- *
- * <p>The {@code ViewModel} annotated with {@link HiltViewModel} will be available for creation by
- * the {@link dagger.hilt.android.lifecycle.HiltViewModelFactory} and can be retrieved by default in
- * an {@code Activity} or {@code Fragment} annotated with {@link
- * dagger.hilt.android.AndroidEntryPoint}. The {@code HiltViewModel} containing a constructor
- * annotated with {@link javax.inject.Inject} will have its dependencies defined in the constructor
- * parameters injected by Dagger's Hilt.
- *
- * <p>Example:
- *
- * <pre>
- * &#64;HiltViewModel
- * public class DonutViewModel extends ViewModel {
- *     &#64;Inject
- *     public DonutViewModel(SavedStateHandle handle, RecipeRepository repository) {
- *         // ...
- *     }
- * }
- * </pre>
- *
- * <pre>
- * &#64;AndroidEntryPoint
- * public class CookingActivity extends AppCompatActivity {
- *     public void onCreate(Bundle savedInstanceState) {
- *         DonutViewModel vm = new ViewModelProvider(this).get(DonutViewModel.class);
- *     }
- * }
- * </pre>
- *
- * <p>Exactly one constructor in the {@code ViewModel} must be annotated with {@code Inject}.
- *
- * <p>Only dependencies available in the {@link dagger.hilt.android.components.ViewModelComponent}
- * can be injected into the {@code ViewModel}.
- *
- * <p>
- *
- * @see dagger.hilt.android.components.ViewModelComponent
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.CLASS)
-@GeneratesRootInput
-public @interface HiltViewModel {}
diff --git a/java/dagger/hilt/android/lifecycle/proguard-rules.pro b/java/dagger/hilt/android/lifecycle/proguard-rules.pro
deleted file mode 100644
index edd3d3d..0000000
--- a/java/dagger/hilt/android/lifecycle/proguard-rules.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-# Keep class names of Hilt injected ViewModels since their name are used as a multibinding map key.
--keepnames @dagger.hilt.android.lifecycle.HiltViewModel class * extends androidx.lifecycle.ViewModel
diff --git a/java/dagger/hilt/android/migration/BUILD b/java/dagger/hilt/android/migration/BUILD
deleted file mode 100644
index ade47c3..0000000
--- a/java/dagger/hilt/android/migration/BUILD
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Helpers for migrating to Hilt.
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "optional_inject",
-    srcs = [
-        "OptionalInject.java",
-        "OptionalInjectCheck.java",
-    ],
-    exports = [
-        "//java/dagger/hilt/android/internal/migration:injected_by_hilt",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt/android/internal/migration:injected_by_hilt",
-        "//java/dagger/hilt/internal:preconditions",
-        "@maven//:androidx_activity_activity",
-        "@maven//:androidx_annotation_annotation",
-        "@maven//:androidx_fragment_fragment",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-    deps = [
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["**/*"]),
-)
diff --git a/java/dagger/hilt/android/migration/OptionalInject.java b/java/dagger/hilt/android/migration/OptionalInject.java
deleted file mode 100644
index 14c1387..0000000
--- a/java/dagger/hilt/android/migration/OptionalInject.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.migration;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * When placed on an {@link dagger.hilt.android.AndroidEntryPoint}-annotated activity / fragment /
- * view / etc, allows injection to occur optionally based on whether or not the application is using
- * Hilt.
- *
- * <p>When using this annotation, you can use {@link OptionalInjectCheck#wasInjectedByHilt} to check
- * at runtime if the annotated class was injected by Hilt. Additionally, this annotation will also
- * cause a method, {@code wasInjectedByHilt} to be generated in the Hilt base class as well, that
- * behaves the same as {@link OptionalInjectCheck#wasInjectedByHilt}. The method is available to
- * users that extend the Hilt base class directly and don't use the Gradle plugin.
- *
- * <p>Example usage:
- *
- * <pre><code>
- * {@literal @}OptionalInject
- * {@literal @}AndroidEntryPoint
- * public final class MyFragment extends Fragment {
- *
- *   {@literal @}Inject Foo foo;
- *
- *   {@literal @}Override
- *   public void onAttach(Activity activity) {
- *     // Injection will happen here, but only if the Activity and the Application are also
- *     // AndroidEntryPoints and were injected by Hilt.
- *     super.onAttach(activity);
- *     if (!OptionalInjectCheck.wasInjectedByHilt(this)) {
- *       // Get Dagger components the previous way and inject.
- *     }
- *   }
- * }
- * </code></pre>
- *
- * <p>This is useful for libraries that have to support Hilt users as well as non-Hilt users.
- * Injection will happen if the parent type (e.g. the activity of a fragment) is an {@link
- * dagger.hilt.android.AndroidEntryPoint} annotated class and if that parent was also injected via
- * Hilt.
- *
- * @see OptionalInjectCheck
- * @see <a href="https://dagger.dev/hilt/optional-inject">Optional injection</a>
- */
-@Target(ElementType.TYPE)
-public @interface OptionalInject {}
diff --git a/java/dagger/hilt/android/migration/OptionalInjectCheck.java b/java/dagger/hilt/android/migration/OptionalInjectCheck.java
deleted file mode 100644
index f9d0ad8..0000000
--- a/java/dagger/hilt/android/migration/OptionalInjectCheck.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.migration;
-
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
-import android.view.View;
-import androidx.activity.ComponentActivity;
-import dagger.hilt.android.internal.migration.InjectedByHilt;
-import dagger.hilt.internal.Preconditions;
-
-/**
- * Utility methods for validating if an {@link dagger.hilt.android.AndroidEntryPoint}-annotated
- * class that is also annotated with {@link OptionalInject} was injected by Hilt.
- *
- * @see OptionalInject
- */
-public final class OptionalInjectCheck {
-
-  /**
-   * Returns true if the Activity was injected by Hilt.
-   *
-   * @throws IllegalArgumentException if the given instance is not an AndroidEntryPoint nor is
-   *     annotated with {@link OptionalInject}.
-   */
-  public static boolean wasInjectedByHilt(@NonNull ComponentActivity activity) {
-    return check(activity);
-  }
-
-  /**
-   * Returns true if the BroadcastReceiver was injected by Hilt.
-   *
-   * @throws IllegalArgumentException if the given instance is not an AndroidEntryPoint nor is
-   *     annotated with {@link OptionalInject}.
-   */
-  public static boolean wasInjectedByHilt(@NonNull BroadcastReceiver broadcastReceiver) {
-    return check(broadcastReceiver);
-  }
-
-  /**
-   * Returns true if the Fragment was injected by Hilt.
-   *
-   * @throws IllegalArgumentException if the given instance is not an AndroidEntryPoint nor is
-   *     annotated with {@link OptionalInject}.
-   */
-  public static boolean wasInjectedByHilt(@NonNull Fragment fragment) {
-    return check(fragment);
-  }
-
-  /**
-   * Returns true if the Service was injected by Hilt.
-   *
-   * @throws IllegalArgumentException if the given instance is not an AndroidEntryPoint nor is
-   *     annotated with {@link OptionalInject}.
-   */
-  public static boolean wasInjectedByHilt(@NonNull Service service) {
-    return check(service);
-  }
-
-  /**
-   * Returns true if the View was injected by Hilt.
-   *
-   * @throws IllegalArgumentException if the given instance is not an AndroidEntryPoint nor is
-   *     annotated with {@link OptionalInject}.
-   */
-  public static boolean wasInjectedByHilt(@NonNull View view) {
-    return check(view);
-  }
-
-  private static boolean check(@NonNull Object obj) {
-    Preconditions.checkNotNull(obj);
-    Preconditions.checkArgument(
-        obj instanceof InjectedByHilt,
-        "'%s' is not an optionally injected android entry point. Check that you have annotated"
-            + " the class with both @AndroidEntryPoint and @OptionalInject.",
-        obj.getClass());
-    return ((InjectedByHilt) obj).wasInjectedByHilt();
-  }
-
-  private OptionalInjectCheck() {}
-}
diff --git a/java/dagger/hilt/android/migration/package-info.java b/java/dagger/hilt/android/migration/package-info.java
deleted file mode 100644
index e37225a..0000000
--- a/java/dagger/hilt/android/migration/package-info.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains Android APIs to help migrating a codebase to Hilt.
- *
- * @see <a href="https://dagger.dev/hilt/migration">Migration to Hilt</a>
- */
-@ParametersAreNonnullByDefault
-package dagger.hilt.android.migration;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/java/dagger/hilt/android/package-info.java b/java/dagger/hilt/android/package-info.java
deleted file mode 100644
index 894f7ab..0000000
--- a/java/dagger/hilt/android/package-info.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains Hilt APIs for Android applications.
- *
- * <p>Hilt provides a standard way to incorporate Dagger dependency injection into an Android
- * application.
- *
- * @see <a href="https://dagger.dev/hilt">Hilt Developer Docs</a>
- */
-@ParametersAreNonnullByDefault
-package dagger.hilt.android;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/java/dagger/hilt/android/plugin/BUILD b/java/dagger/hilt/android/plugin/BUILD
deleted file mode 100644
index 7fd2c83..0000000
--- a/java/dagger/hilt/android/plugin/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2020 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.
-#
-# Description:
-#   A Gradle plugin that performs a transform.
-
-package(default_visibility = ["//:src"])
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(
-        ["**/*"],
-        # Exclude Gradle build folder to enable working along side Bazel
-        exclude = ["**/build/**"],
-    ),
-)
diff --git a/java/dagger/hilt/android/plugin/build.gradle b/java/dagger/hilt/android/plugin/build.gradle
deleted file mode 100644
index 274ecbe..0000000
--- a/java/dagger/hilt/android/plugin/build.gradle
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-buildscript {
-  repositories {
-    google()
-    jcenter()
-  }
-}
-
-plugins {
-  id 'org.jetbrains.kotlin.jvm' version '1.4.20'
-  id 'java-gradle-plugin'
-  id 'maven-publish'
-}
-
-repositories {
-  google()
-  jcenter()
-}
-
-configurations {
-  additionalTestPlugin {
-    canBeConsumed = false
-    canBeResolved = true
-    extendsFrom implementation
-  }
-}
-
-dependencies {
-  implementation gradleApi()
-  compileOnly 'com.android.tools.build:gradle:4.2.0-beta04'
-  // TODO(danysantiago): Make compileOnly to avoid dep for non-Kotlin projects.
-  implementation 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.20'
-  implementation 'org.javassist:javassist:3.26.0-GA'
-  implementation 'org.ow2.asm:asm:9.0'
-
-  testImplementation gradleTestKit()
-  testImplementation 'junit:junit:4.12'
-  testImplementation 'com.google.truth:truth:1.0.1'
-  additionalTestPlugin 'com.android.tools.build:gradle:4.2.0-beta04'
-}
-
-// Configure the generating task of plugin-under-test-metadata.properties to
-// include additional dependencies for the injected plugin classpath that
-// are not present in the main runtime dependencies. This allows us to test
-// the desired AGP version while keeping a compileOnly dep on the main source.
-tasks.withType(PluginUnderTestMetadata.class).named("pluginUnderTestMetadata").configure {
-  it.pluginClasspath.from(configurations.additionalTestPlugin)
-}
-
-compileKotlin {
-  kotlinOptions {
-    jvmTarget = "1.8"
-  }
-}
-
-// Create sources Jar from main kotlin sources
-tasks.register("sourcesJar", Jar).configure {
-  group = JavaBasePlugin.DOCUMENTATION_GROUP
-  description = "Assembles sources JAR"
-  classifier = "sources"
-  from(sourceSets["main"].allSource)
-}
-
-// Create javadoc Jar. The jar is empty since we don't really have docs
-// for this plugin but this is required to upload to Sonatype.
-// https://central.sonatype.org/pages/requirements.html#supply-javadoc-and-sources
-tasks.register("javadocJar", Jar).configure {
-  group = JavaBasePlugin.DOCUMENTATION_GROUP
-  description = "Assembles javadoc JAR"
-  classifier = "javadoc"
-}
-
-// Disable Gradle metadata publication.
-tasks.withType(GenerateModuleMetadata) {
-  enabled = false
-}
-
-// TODO(danysantiago): Use POM template in tools/ to avoid duplicating lines.
-publishing {
-  publications {
-    plugin(MavenPublication) {
-      artifactId = 'hilt-android-gradle-plugin'
-      def publishVersion = findProperty("PublishVersion")
-      version = (publishVersion != null) ? publishVersion : "LOCAL-SNAPSHOT"
-      from components.kotlin
-      artifact(sourcesJar)
-      artifact(javadocJar)
-      pom {
-        name = 'Hilt Android Gradle Plugin'
-        description = 'A fast dependency injector for Android and Java.'
-        url = 'https://github.com/google/dagger'
-        scm {
-          url = 'https://github.com/google/dagger/'
-          connection = 'scm:git:git://github.com/google/dagger.git'
-          developerConnection = 'scm:git:ssh://git@github.com/google/dagger.git'
-          tag = 'HEAD'
-        }
-        issueManagement {
-          system = 'GitHub Issues'
-          url = 'https://github.com/google/dagger/issues'
-        }
-        licenses {
-          license {
-            name = 'Apache 2.0'
-            url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
-          }
-        }
-        organization {
-          name = 'Google, Inc.'
-          url = 'https://www.google.com'
-        }
-        withXml {
-          def projectNode = asNode()
-          // Adds:
-          // <parent>
-          //   <groupId>org.sonatype.oss</groupId>
-          //   <artifactId>oss-parent</artifactId>
-          //   <version>7</version>
-          // </parent>
-          def parentNode = projectNode.appendNode('parent')
-          parentNode.appendNode('groupId', 'org.sonatype.oss')
-          parentNode.appendNode('artifactId', 'oss-parent')
-          parentNode.appendNode('version', '7')
-          // Adds scm->tag because for some reason the DSL API does not.
-          // <scm>
-          //   <tag>HEAD</tag>
-          // </scm>
-          projectNode.get('scm').first().appendNode('tag', 'HEAD')
-        }
-      }
-    }
-  }
-  // Publish to build output repository.
-  repositories {
-    maven {
-      url = uri("$buildDir/repo")
-    }
-  }
-}
-
-group='com.google.dagger'
diff --git a/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.jar b/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.properties b/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/java/dagger/hilt/android/plugin/gradlew b/java/dagger/hilt/android/plugin/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/java/dagger/hilt/android/plugin/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassTransformer.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassTransformer.kt
deleted file mode 100644
index e066f48..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassTransformer.kt
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.plugin
-
-import dagger.hilt.android.plugin.util.isClassFile
-import dagger.hilt.android.plugin.util.isJarFile
-import java.io.File
-import java.io.FileInputStream
-import java.util.zip.ZipInputStream
-import javassist.ClassPool
-import javassist.CtClass
-import javassist.Modifier
-import javassist.bytecode.Bytecode
-import javassist.bytecode.CodeIterator
-import javassist.bytecode.Opcode
-import org.slf4j.LoggerFactory
-
-typealias CodeArray = javassist.bytecode.ByteArray // Avoids conflict with Kotlin's stdlib ByteArray
-
-/**
- * A helper class for performing the transform.
- *
- * Create it with the list of all available source directories along with the root output directory
- * and use [AndroidEntryPointClassTransformer.transformFile] or
- * [AndroidEntryPointClassTransformer.transformJarContents] to perform the actual transformation.
- */
-internal class AndroidEntryPointClassTransformer(
-  val taskName: String,
-  allInputs: List<File>,
-  private val sourceRootOutputDir: File,
-  private val copyNonTransformed: Boolean
-) {
-  private val logger = LoggerFactory.getLogger(AndroidEntryPointClassTransformer::class.java)
-
-  // A ClassPool created from the given input files, this allows us to use the higher
-  // level Javaassit APIs, but requires class parsing/loading.
-  private val classPool: ClassPool = ClassPool(true).also { pool ->
-    allInputs.forEach {
-      pool.appendClassPath(it.path)
-    }
-  }
-
-  init {
-    sourceRootOutputDir.mkdirs()
-  }
-
-  /**
-   * Transforms the classes inside the jar and copies re-written class files if and only if they are
-   * transformed.
-   *
-   * @param inputFile The jar file to transform, must be a jar.
-   * @return true if at least one class within the jar was transformed.
-   */
-  fun transformJarContents(inputFile: File): Boolean {
-    require(inputFile.isJarFile()) {
-      "Invalid file, '$inputFile' is not a jar."
-    }
-    // Validate transform is not applied to a jar when copying is enabled, meaning the transformer
-    // is being used in the Android transform API pipeline which does not need to transform jars
-    // and handles copying them.
-    check(!copyNonTransformed) {
-      "Transforming a jar is not supported with 'copyNonTransformed'."
-    }
-    var transformed = false
-    ZipInputStream(FileInputStream(inputFile)).use { input ->
-      var entry = input.nextEntry
-      while (entry != null) {
-        if (entry.isClassFile()) {
-          val clazz = classPool.makeClass(input, false)
-          transformed = transformClassToOutput(clazz) || transformed
-        }
-        entry = input.nextEntry
-      }
-    }
-    return transformed
-  }
-
-  /**
-   * Transform a single class file.
-   *
-   * @param inputFile The file to transform, must be a class file.
-   * @return true if the class file was transformed.
-   */
-  fun transformFile(inputFile: File): Boolean {
-    check(inputFile.isClassFile()) {
-      "Invalid file, '$inputFile' is not a class."
-    }
-    val clazz = inputFile.inputStream().use { classPool.makeClass(it, false) }
-    return transformClassToOutput(clazz)
-  }
-
-  private fun transformClassToOutput(clazz: CtClass): Boolean {
-    val transformed = transformClass(clazz)
-    if (transformed || copyNonTransformed) {
-      clazz.writeFile(sourceRootOutputDir.path)
-    }
-    return transformed
-  }
-
-  private fun transformClass(clazz: CtClass): Boolean {
-    if (ANDROID_ENTRY_POINT_ANNOTATIONS.none { clazz.hasAnnotation(it) }) {
-      // Not a Android entry point annotated class, don't do anything.
-      return false
-    }
-
-    // TODO(danysantiago): Handle classes with '$' in their name if they do become an issue.
-    val superclassName = clazz.classFile.superclass
-    val entryPointSuperclassName =
-      clazz.packageName + ".Hilt_" + clazz.simpleName.replace("$", "_")
-    logger.info(
-      "[$taskName] Transforming ${clazz.name} to extend $entryPointSuperclassName instead of " +
-        "$superclassName."
-    )
-    val entryPointSuperclass = classPool.get(entryPointSuperclassName)
-    clazz.superclass = entryPointSuperclass
-    transformSuperMethodCalls(clazz, superclassName, entryPointSuperclassName)
-
-    // Check if Hilt generated class is a BroadcastReceiver with the marker field which means
-    // a super.onReceive invocation has to be inserted in the implementation.
-    if (entryPointSuperclass.declaredFields.any { it.name == "onReceiveBytecodeInjectionMarker" }) {
-      transformOnReceive(clazz, entryPointSuperclassName)
-    }
-
-    return true
-  }
-
-  /**
-   * Iterates over each declared method, finding in its bodies super calls. (e.g. super.onCreate())
-   * and rewrites the method reference of the invokespecial instruction to one that uses the new
-   * superclass.
-   *
-   * The invokespecial instruction is emitted for code that between other things also invokes a
-   * method of a superclass of the current class. The opcode invokespecial takes two operands, each
-   * of 8 bit, that together represent an address in the constant pool to a method reference. The
-   * method reference is computed at compile-time by looking the direct superclass declaration, but
-   * at runtime the code behaves like invokevirtual, where as the actual method invoked is looked up
-   * based on the class hierarchy.
-   *
-   * However, it has been observed that on APIs 19 to 22 the Android Runtime (ART) jumps over the
-   * direct superclass and into the method reference class, causing unexpected behaviours.
-   * Therefore, this method performs the additional transformation to rewrite direct super call
-   * invocations to use a method reference whose class in the pool is the new superclass. Note that
-   * this is not necessary for constructor calls since the Javassist library takes care of those.
-   *
-   * @see: https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html#jvms-6.5.invokespecial
-   * @see: https://source.android.com/devices/tech/dalvik/dalvik-bytecode
-   */
-  private fun transformSuperMethodCalls(
-    clazz: CtClass,
-    oldSuperclassName: String,
-    newSuperclassName: String
-  ) {
-    val constantPool = clazz.classFile.constPool
-    clazz.declaredMethods
-      .filter {
-        it.methodInfo.isMethod &&
-          !Modifier.isStatic(it.modifiers) &&
-          !Modifier.isAbstract(it.modifiers) &&
-          !Modifier.isNative(it.modifiers)
-      }
-      .forEach { method ->
-        val codeAttr = method.methodInfo.codeAttribute
-        val code = codeAttr.code
-        codeAttr.iterator().forEachInstruction { index, opcode ->
-          // We are only interested in 'invokespecial' instructions.
-          if (opcode != Opcode.INVOKESPECIAL) {
-            return@forEachInstruction
-          }
-          // If the method reference of the instruction is not using the old superclass then we
-          // should not rewrite it.
-          val methodRef = CodeArray.readU16bit(code, index + 1)
-          val currentClassRef = constantPool.getMethodrefClassName(methodRef)
-          if (currentClassRef != oldSuperclassName) {
-            return@forEachInstruction
-          }
-          val nameAndTypeRef = constantPool.getMethodrefNameAndType(methodRef)
-          val newSuperclassRef = constantPool.addClassInfo(newSuperclassName)
-          val newMethodRef = constantPool.addMethodrefInfo(newSuperclassRef, nameAndTypeRef)
-          logger.info(
-            "[$taskName] Redirecting an invokespecial in " +
-              "${clazz.name}.${method.name}:${method.signature} at code index $index from " +
-              "method ref #$methodRef to #$newMethodRef."
-          )
-          CodeArray.write16bit(newMethodRef, code, index + 1)
-        }
-      }
-  }
-
-  // Iterate over each instruction in a CodeIterator.
-  private fun CodeIterator.forEachInstruction(body: CodeIterator.(Int, Int) -> Unit) {
-    while (hasNext()) {
-      val index = next()
-      this.body(index, byteAt(index))
-    }
-  }
-
-  /**
-   * For a BroadcastReceiver insert a super call in the onReceive method implementation since
-   * after the class is transformed onReceive will no longer be abstract (it is implemented by
-   * Hilt generated receiver).
-   */
-  private fun transformOnReceive(clazz: CtClass, entryPointSuperclassName: String) {
-    val method = clazz.declaredMethods.first {
-      it.name + it.signature == ON_RECEIVE_METHOD_NAME + ON_RECEIVE_METHOD_SIGNATURE
-    }
-    val constantPool = clazz.classFile.constPool
-    val newCode = Bytecode(constantPool).apply {
-      addAload(0) // Loads 'this'
-      addAload(1) // Loads method param 1 (Context)
-      addAload(2) // Loads method param 2 (Intent)
-      addInvokespecial(
-        entryPointSuperclassName, ON_RECEIVE_METHOD_NAME, ON_RECEIVE_METHOD_SIGNATURE
-      )
-    }
-    val newCodeAttribute = newCode.toCodeAttribute()
-    val currentCodeAttribute = method.methodInfo.codeAttribute
-    currentCodeAttribute.maxStack =
-      maxOf(newCodeAttribute.maxStack, currentCodeAttribute.maxStack)
-    currentCodeAttribute.maxLocals =
-      maxOf(newCodeAttribute.maxLocals, currentCodeAttribute.maxLocals)
-    val codeIterator = currentCodeAttribute.iterator()
-    val pos = codeIterator.insertEx(newCode.get()) // insert new code
-    codeIterator.insert(newCodeAttribute.exceptionTable, pos) // offset exception table
-    method.methodInfo.rebuildStackMap(clazz.classPool) // update stack table
-  }
-
-  companion object {
-    val ANDROID_ENTRY_POINT_ANNOTATIONS = setOf(
-      "dagger.hilt.android.AndroidEntryPoint",
-      "dagger.hilt.android.HiltAndroidApp"
-    )
-    val ON_RECEIVE_METHOD_NAME = "onReceive"
-    val ON_RECEIVE_METHOD_SIGNATURE =
-      "(Landroid/content/Context;Landroid/content/Intent;)V"
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassVisitor.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassVisitor.kt
deleted file mode 100644
index 015bb76..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassVisitor.kt
+++ /dev/null
@@ -1,197 +0,0 @@
-package dagger.hilt.android.plugin
-
-import com.android.build.api.instrumentation.AsmClassVisitorFactory
-import com.android.build.api.instrumentation.ClassContext
-import com.android.build.api.instrumentation.ClassData
-import com.android.build.api.instrumentation.InstrumentationParameters
-import java.io.File
-import org.gradle.api.provider.Property
-import org.gradle.api.tasks.Input
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.ClassVisitor
-import org.objectweb.asm.FieldVisitor
-import org.objectweb.asm.MethodVisitor
-import org.objectweb.asm.Opcodes
-
-/**
- * ASM Adapter that transforms @AndroidEntryPoint-annotated classes to extend the Hilt
- * generated android class, including the @HiltAndroidApp application class.
- */
-@Suppress("UnstableApiUsage")
-class AndroidEntryPointClassVisitor(
-  private val apiVersion: Int,
-  nextClassVisitor: ClassVisitor,
-  private val additionalClasses: File
-) : ClassVisitor(apiVersion, nextClassVisitor) {
-
-  interface AndroidEntryPointParams : InstrumentationParameters {
-    @get:Input
-    val additionalClassesDir: Property<File>
-  }
-
-  abstract class Factory : AsmClassVisitorFactory<AndroidEntryPointParams> {
-    override fun createClassVisitor(
-      classContext: ClassContext,
-      nextClassVisitor: ClassVisitor
-    ): ClassVisitor {
-      return AndroidEntryPointClassVisitor(
-        apiVersion = instrumentationContext.apiVersion.get(),
-        nextClassVisitor = nextClassVisitor,
-        additionalClasses = parameters.get().additionalClassesDir.get()
-      )
-    }
-
-    /**
-     * Check if a class should be transformed.
-     *
-     * Only classes that are an Android entry point should be transformed.
-     */
-    override fun isInstrumentable(classData: ClassData) =
-      classData.classAnnotations.any { ANDROID_ENTRY_POINT_ANNOTATIONS.contains(it) }
-  }
-
-  // The name of the Hilt generated superclass in it internal form.
-  // e.g. "my/package/Hilt_MyActivity"
-  lateinit var newSuperclassName: String
-
-  lateinit var oldSuperclassName: String
-
-  override fun visit(
-    version: Int,
-    access: Int,
-    name: String,
-    signature: String?,
-    superName: String?,
-    interfaces: Array<out String>?
-  ) {
-    val packageName = name.substringBeforeLast('/')
-    val className = name.substringAfterLast('/')
-    newSuperclassName =
-      packageName + "/Hilt_" + className.replace("$", "_")
-    oldSuperclassName = superName ?: error { "Superclass of $name is null!" }
-    super.visit(version, access, name, signature, newSuperclassName, interfaces)
-  }
-
-  override fun visitMethod(
-    access: Int,
-    name: String,
-    descriptor: String,
-    signature: String?,
-    exceptions: Array<out String>?
-  ): MethodVisitor {
-    val nextMethodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions)
-    val invokeSpecialVisitor = InvokeSpecialAdapter(apiVersion, nextMethodVisitor)
-    if (name == ON_RECEIVE_METHOD_NAME &&
-      descriptor == ON_RECEIVE_METHOD_DESCRIPTOR &&
-      hasOnReceiveBytecodeInjectionMarker()
-    ) {
-      return OnReceiveAdapter(apiVersion, invokeSpecialVisitor)
-    }
-    return invokeSpecialVisitor
-  }
-
-  /**
-   * Adapter for super calls (e.g. super.onCreate()) that rewrites the owner reference of the
-   * invokespecial instruction to use the new superclass.
-   *
-   * The invokespecial instruction is emitted for code that between other things also invokes a
-   * method of a superclass of the current class. The opcode invokespecial takes two operands, each
-   * of 8 bit, that together represent an address in the constant pool to a method reference. The
-   * method reference is computed at compile-time by looking the direct superclass declaration, but
-   * at runtime the code behaves like invokevirtual, where as the actual method invoked is looked up
-   * based on the class hierarchy.
-   *
-   * However, it has been observed that on APIs 19 to 22 the Android Runtime (ART) jumps over the
-   * direct superclass and into the method reference class, causing unexpected behaviours.
-   * Therefore, this method performs the additional transformation to rewrite direct super call
-   * invocations to use a method reference whose class in the pool is the new superclass. Note that
-   * this is not necessary for constructor calls since the Javassist library takes care of those.
-   *
-   * @see: https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html#jvms-6.5.invokespecial
-   * @see: https://source.android.com/devices/tech/dalvik/dalvik-bytecode
-   */
-  inner class InvokeSpecialAdapter(
-    apiVersion: Int,
-    nextClassVisitor: MethodVisitor
-  ) : MethodVisitor(apiVersion, nextClassVisitor) {
-    override fun visitMethodInsn(
-      opcode: Int,
-      owner: String,
-      name: String,
-      descriptor: String,
-      isInterface: Boolean
-    ) {
-      if (opcode == Opcodes.INVOKESPECIAL && owner == oldSuperclassName) {
-        // Update the owner of all INVOKESPECIAL instructions, including those found in
-        // constructors.
-        super.visitMethodInsn(opcode, newSuperclassName, name, descriptor, isInterface)
-      } else {
-        super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
-      }
-    }
-  }
-
-  /**
-   * Method adapter for a BroadcastReceiver's onReceive method to insert a super call since with
-   * its new superclass, onReceive will no longer be abstract (it is implemented by Hilt generated
-   * receiver).
-   */
-  inner class OnReceiveAdapter(
-    apiVersion: Int,
-    nextClassVisitor: MethodVisitor
-  ) : MethodVisitor(apiVersion, nextClassVisitor) {
-    override fun visitCode() {
-      super.visitCode()
-      super.visitIntInsn(Opcodes.ALOAD, 0) // Load 'this'
-      super.visitIntInsn(Opcodes.ALOAD, 1) // Load method param 1 (Context)
-      super.visitIntInsn(Opcodes.ALOAD, 2) // Load method param 2 (Intent)
-      super.visitMethodInsn(
-        Opcodes.INVOKESPECIAL,
-        newSuperclassName,
-        ON_RECEIVE_METHOD_NAME,
-        ON_RECEIVE_METHOD_DESCRIPTOR,
-        false
-      )
-    }
-  }
-
-  /**
-   * Check if Hilt generated class is a BroadcastReceiver with the marker field which means
-   * a super.onReceive invocation has to be inserted in the implementation.
-   */
-  private fun hasOnReceiveBytecodeInjectionMarker() =
-    findAdditionalClassFile(newSuperclassName).inputStream().use {
-      var hasMarker = false
-      ClassReader(it).accept(
-        object : ClassVisitor(apiVersion) {
-          override fun visitField(
-            access: Int,
-            name: String,
-            descriptor: String,
-            signature: String?,
-            value: Any?
-          ): FieldVisitor? {
-            if (name == "onReceiveBytecodeInjectionMarker") {
-              hasMarker = true
-            }
-            return null
-          }
-        },
-        ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
-      )
-      return@use hasMarker
-    }
-
-  private fun findAdditionalClassFile(className: String) =
-    File(additionalClasses, "$className.class")
-
-  companion object {
-    val ANDROID_ENTRY_POINT_ANNOTATIONS = setOf(
-      "dagger.hilt.android.AndroidEntryPoint",
-      "dagger.hilt.android.HiltAndroidApp"
-    )
-    const val ON_RECEIVE_METHOD_NAME = "onReceive"
-    const val ON_RECEIVE_METHOD_DESCRIPTOR =
-      "(Landroid/content/Context;Landroid/content/Intent;)V"
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointTransform.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointTransform.kt
deleted file mode 100644
index 9bb5160..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointTransform.kt
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.plugin
-
-import com.android.build.api.transform.DirectoryInput
-import com.android.build.api.transform.Format
-import com.android.build.api.transform.JarInput
-import com.android.build.api.transform.QualifiedContent
-import com.android.build.api.transform.Status
-import com.android.build.api.transform.Transform
-import com.android.build.api.transform.TransformInput
-import com.android.build.api.transform.TransformInvocation
-import dagger.hilt.android.plugin.util.isClassFile
-import java.io.File
-
-/**
- * Bytecode transformation to make @AndroidEntryPoint annotated classes extend the Hilt
- * generated android classes, including the @HiltAndroidApp application class.
- *
- * A transform receives input as a collection [TransformInput], which is composed of [JarInput]s and
- * [DirectoryInput]s. The resulting files must be placed in the
- * [TransformInvocation.getOutputProvider]. The bytecode transformation can be done with any library
- * (in our case Javaassit). The [QualifiedContent.Scope] defined in a transform defines the input
- * the transform will receive and if it can be applied to only the Android application projects or
- * Android libraries too.
- *
- * See: [TransformPublic Docs](https://google.github.io/android-gradle-dsl/javadoc/current/com/android/build/api/transform/Transform.html)
- */
-class AndroidEntryPointTransform : Transform() {
-  // The name of the transform. This name appears as a gradle task.
-  override fun getName() = "AndroidEntryPointTransform"
-
-  // The type of input this transform will handle.
-  override fun getInputTypes() = setOf(QualifiedContent.DefaultContentType.CLASSES)
-
-  override fun isIncremental() = true
-
-  // The project scope this transform is applied to.
-  override fun getScopes() = mutableSetOf(QualifiedContent.Scope.PROJECT)
-
-  /**
-   * Performs the transformation of the bytecode.
-   *
-   * The inputs will be available in the [TransformInvocation] along with referenced inputs that
-   * should not be transformed. The inputs received along with the referenced inputs depend on the
-   * scope of the transform.
-   *
-   * The invocation will also indicate if an incremental transform has to be applied or not. Even
-   * though a transform might return true in its [isIncremental] function, the invocation might
-   * return false in [TransformInvocation.isIncremental], therefore both cases must be handled.
-   */
-  override fun transform(invocation: TransformInvocation) {
-    if (!invocation.isIncremental) {
-      // Remove any lingering files on a non-incremental invocation since everything has to be
-      // transformed.
-      invocation.outputProvider.deleteAll()
-    }
-
-    invocation.inputs.forEach { transformInput ->
-      transformInput.jarInputs.forEach { jarInput ->
-        val outputJar =
-          invocation.outputProvider.getContentLocation(
-            jarInput.name,
-            jarInput.contentTypes,
-            jarInput.scopes,
-            Format.JAR
-          )
-        if (invocation.isIncremental) {
-          when (jarInput.status) {
-            Status.ADDED, Status.CHANGED -> copyJar(jarInput.file, outputJar)
-            Status.REMOVED -> outputJar.delete()
-            Status.NOTCHANGED -> {
-              // No need to transform.
-            }
-            else -> {
-              error("Unknown status: ${jarInput.status}")
-            }
-          }
-        } else {
-          copyJar(jarInput.file, outputJar)
-        }
-      }
-      transformInput.directoryInputs.forEach { directoryInput ->
-        val outputDir = invocation.outputProvider.getContentLocation(
-          directoryInput.name,
-          directoryInput.contentTypes,
-          directoryInput.scopes,
-          Format.DIRECTORY
-        )
-        val classTransformer =
-          createHiltClassTransformer(invocation.inputs, invocation.referencedInputs, outputDir)
-        if (invocation.isIncremental) {
-          directoryInput.changedFiles.forEach { (file, status) ->
-            val outputFile = toOutputFile(outputDir, directoryInput.file, file)
-            when (status) {
-              Status.ADDED, Status.CHANGED ->
-                transformFile(file, outputFile.parentFile, classTransformer)
-              Status.REMOVED -> outputFile.delete()
-              Status.NOTCHANGED -> {
-                // No need to transform.
-              }
-              else -> {
-                error("Unknown status: $status")
-              }
-            }
-          }
-        } else {
-          directoryInput.file.walkTopDown().forEach { file ->
-            val outputFile = toOutputFile(outputDir, directoryInput.file, file)
-            transformFile(file, outputFile.parentFile, classTransformer)
-          }
-        }
-      }
-    }
-  }
-
-  // Create a transformer given an invocation inputs. Note that since this is a PROJECT scoped
-  // transform the actual transformation is only done on project files and not its dependencies.
-  private fun createHiltClassTransformer(
-    inputs: Collection<TransformInput>,
-    referencedInputs: Collection<TransformInput>,
-    outputDir: File
-  ): AndroidEntryPointClassTransformer {
-    val classFiles = (inputs + referencedInputs).flatMap { input ->
-      (input.directoryInputs + input.jarInputs).map { it.file }
-    }
-    return AndroidEntryPointClassTransformer(
-      taskName = name,
-      allInputs = classFiles,
-      sourceRootOutputDir = outputDir,
-      copyNonTransformed = true
-    )
-  }
-
-  // Transform a single file. If the file is not a class file it is just copied to the output dir.
-  private fun transformFile(
-    inputFile: File,
-    outputDir: File,
-    transformer: AndroidEntryPointClassTransformer
-  ) {
-    if (inputFile.isClassFile()) {
-      transformer.transformFile(inputFile)
-    } else if (inputFile.isFile) {
-      // Copy all non .class files to the output.
-      outputDir.mkdirs()
-      val outputFile = File(outputDir, inputFile.name)
-      inputFile.copyTo(target = outputFile, overwrite = true)
-    }
-  }
-
-  // We are only interested in project compiled classes but we have to copy received jars to the
-  // output.
-  private fun copyJar(inputJar: File, outputJar: File) {
-    outputJar.parentFile?.mkdirs()
-    inputJar.copyTo(target = outputJar, overwrite = true)
-  }
-
-  private fun toOutputFile(outputDir: File, inputDir: File, inputFile: File) =
-    File(outputDir, inputFile.relativeTo(inputDir).path)
-}
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltExtension.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltExtension.kt
deleted file mode 100644
index 7a33836..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltExtension.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.plugin
-
-/**
- * Configuration options for the Hilt Gradle Plugin
- */
-interface HiltExtension {
-
-  /**
-   * If set to `true`, Hilt will adjust the compile classpath such that it includes transitive
-   * dependencies, ignoring `api` or `implementation` boundaries during compilation. You should
-   * enable this option if your project has multiple level of transitive dependencies that contain
-   * injected classes or entry points.
-   *
-   * Enabling this option also requires android.lintOptions.checkReleaseBuilds to be set to 'false'
-   * if the Android Gradle Plugin version being used is less than 7.0.
-   *
-   * See https://github.com/google/dagger/issues/1991 for more context.
-   */
-  var enableExperimentalClasspathAggregation: Boolean
-
-  /**
-   * If set to `true`, Hilt will register a transform task that will rewrite `@AndroidEntryPoint`
-   * annotated classes before the host-side JVM tests run. You should enable this option if you are
-   * running Robolectric UI tests as part of your JUnit tests.
-   *
-   * This flag is not necessary if when com.android.tools.build:gradle:4.2.0+ is used and will be
-   * deprecated in a future version.
-   */
-  var enableTransformForLocalTests: Boolean
-}
-
-internal open class HiltExtensionImpl : HiltExtension {
-  override var enableExperimentalClasspathAggregation: Boolean = false
-  override var enableTransformForLocalTests: Boolean = false
-}
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt
deleted file mode 100644
index e26edb5..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.plugin
-
-import com.android.build.api.component.Component
-import com.android.build.api.extension.AndroidComponentsExtension
-import com.android.build.api.instrumentation.FramesComputationMode
-import com.android.build.api.instrumentation.InstrumentationScope
-import com.android.build.gradle.AppExtension
-import com.android.build.gradle.BaseExtension
-import com.android.build.gradle.LibraryExtension
-import com.android.build.gradle.TestExtension
-import com.android.build.gradle.TestedExtension
-import com.android.build.gradle.api.AndroidBasePlugin
-import com.android.build.gradle.api.BaseVariant
-import com.android.build.gradle.api.TestVariant
-import com.android.build.gradle.api.UnitTestVariant
-import dagger.hilt.android.plugin.util.CopyTransform
-import dagger.hilt.android.plugin.util.SimpleAGPVersion
-import java.io.File
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.artifacts.component.ProjectComponentIdentifier
-import org.gradle.api.attributes.Attribute
-
-/**
- * A Gradle plugin that checks if the project is an Android project and if so, registers a
- * bytecode transformation.
- *
- * The plugin also passes an annotation processor option to disable superclass validation for
- * classes annotated with `@AndroidEntryPoint` since the registered transform by this plugin will
- * update the superclass.
- */
-class HiltGradlePlugin : Plugin<Project> {
-  override fun apply(project: Project) {
-    var configured = false
-    project.plugins.withType(AndroidBasePlugin::class.java) {
-      configured = true
-      configureHilt(project)
-    }
-    project.afterEvaluate {
-      check(configured) {
-        // Check if configuration was applied, if not inform the developer they have applied the
-        // plugin to a non-android project.
-        "The Hilt Android Gradle plugin can only be applied to an Android project."
-      }
-      verifyDependencies(it)
-    }
-  }
-
-  private fun configureHilt(project: Project) {
-    val hiltExtension = project.extensions.create(
-      HiltExtension::class.java, "hilt", HiltExtensionImpl::class.java
-    )
-    configureCompileClasspath(project, hiltExtension)
-    if (SimpleAGPVersion.ANDROID_GRADLE_PLUGIN_VERSION < SimpleAGPVersion(4, 2)) {
-      // Configures bytecode transform using older APIs pre AGP 4.2
-      configureTransform(project, hiltExtension)
-    } else {
-      // Configures bytecode transform using AGP 4.2 ASM pipeline.
-      configureTransformASM(project, hiltExtension)
-    }
-    configureProcessorFlags(project)
-  }
-
-  private fun configureCompileClasspath(project: Project, hiltExtension: HiltExtension) {
-    val androidExtension = project.extensions.findByType(BaseExtension::class.java)
-      ?: throw error("Android BaseExtension not found.")
-    when (androidExtension) {
-      is AppExtension -> {
-        // For an app project we configure the app variant and both androidTest and test variants,
-        // Hilt components are generated in all of them.
-        androidExtension.applicationVariants.all {
-          configureVariantCompileClasspath(project, hiltExtension, androidExtension, it)
-        }
-        androidExtension.testVariants.all {
-          configureVariantCompileClasspath(project, hiltExtension, androidExtension, it)
-        }
-        androidExtension.unitTestVariants.all {
-          configureVariantCompileClasspath(project, hiltExtension, androidExtension, it)
-        }
-      }
-      is LibraryExtension -> {
-        // For a library project, only the androidTest and test variant are configured since
-        // Hilt components are not generated in a library.
-        androidExtension.testVariants.all {
-          configureVariantCompileClasspath(project, hiltExtension, androidExtension, it)
-        }
-        androidExtension.unitTestVariants.all {
-          configureVariantCompileClasspath(project, hiltExtension, androidExtension, it)
-        }
-      }
-      is TestExtension -> {
-        androidExtension.applicationVariants.all {
-          configureVariantCompileClasspath(project, hiltExtension, androidExtension, it)
-        }
-      }
-      else -> error(
-        "Hilt plugin is unable to configure the compile classpath for project with extension " +
-          "'$androidExtension'"
-      )
-    }
-
-    project.dependencies.apply {
-      registerTransform(CopyTransform::class.java) { spec ->
-        // Java/Kotlin library projects offer an artifact of type 'jar'.
-        spec.from.attribute(ARTIFACT_TYPE_ATTRIBUTE, "jar")
-        // Android library projects (with or without Kotlin) offer an artifact of type
-        // 'processed-jar', which AGP can offer as a jar.
-        spec.from.attribute(ARTIFACT_TYPE_ATTRIBUTE, "processed-jar")
-        spec.to.attribute(ARTIFACT_TYPE_ATTRIBUTE, DAGGER_ARTIFACT_TYPE_VALUE)
-      }
-    }
-  }
-
-  private fun configureVariantCompileClasspath(
-    project: Project,
-    hiltExtension: HiltExtension,
-    androidExtension: BaseExtension,
-    variant: BaseVariant
-  ) {
-    if (!hiltExtension.enableExperimentalClasspathAggregation) {
-      // Option is not enabled, don't configure compile classpath. Note that the option can't be
-      // checked earlier (before iterating over the variants) since it would have been too early for
-      // the value to be populated from the build file.
-      return
-    }
-
-    if (androidExtension.lintOptions.isCheckReleaseBuilds &&
-      SimpleAGPVersion.ANDROID_GRADLE_PLUGIN_VERSION < SimpleAGPVersion(7, 0)
-    ) {
-      // Sadly we have to ask users to disable lint when enableExperimentalClasspathAggregation is
-      // set to true and they are not in AGP 7.0+ since Lint will cause issues during the
-      // configuration phase. See b/158753935 and b/160392650
-      error(
-        "Invalid Hilt plugin configuration: When 'enableExperimentalClasspathAggregation' is " +
-          "enabled 'android.lintOptions.checkReleaseBuilds' has to be set to false unless " +
-          "com.android.tools.build:gradle:7.0.0+ is used."
-      )
-    }
-
-    if (
-      listOf(
-          "android.injected.build.model.only", // Sent by AS 1.0 only
-          "android.injected.build.model.only.advanced", // Sent by AS 1.1+
-          "android.injected.build.model.only.versioned", // Sent by AS 2.4+
-          "android.injected.build.model.feature.full.dependencies", // Sent by AS 2.4+
-          "android.injected.build.model.v2", // Sent by AS 4.2+
-        ).any { project.properties.containsKey(it) }
-    ) {
-      // Do not configure compile classpath when AndroidStudio is building the model (syncing)
-      // otherwise it will cause a freeze.
-      return
-    }
-
-    val runtimeConfiguration = if (variant is TestVariant) {
-      // For Android test variants, the tested runtime classpath is used since the test app has
-      // tested dependencies removed.
-      variant.testedVariant.runtimeConfiguration
-    } else {
-      variant.runtimeConfiguration
-    }
-    val artifactView = runtimeConfiguration.incoming.artifactView { view ->
-      view.attributes.attribute(ARTIFACT_TYPE_ATTRIBUTE, DAGGER_ARTIFACT_TYPE_VALUE)
-      view.componentFilter { identifier ->
-        // Filter out the project's classes from the aggregated view since this can cause
-        // issues with Kotlin internal members visibility. b/178230629
-        if (identifier is ProjectComponentIdentifier) {
-          identifier.projectName != project.name
-        } else {
-          true
-        }
-      }
-    }
-
-    // CompileOnly config names don't follow the usual convention:
-    // <Variant Name>   -> <Config Name>
-    // debug            -> debugCompileOnly
-    // debugAndroidTest -> androidTestDebugCompileOnly
-    // debugUnitTest    -> testDebugCompileOnly
-    // release          -> releaseCompileOnly
-    // releaseUnitTest  -> testReleaseCompileOnly
-    val compileOnlyConfigName = when (variant) {
-      is TestVariant ->
-        "androidTest${variant.name.substringBeforeLast("AndroidTest").capitalize()}CompileOnly"
-      is UnitTestVariant ->
-        "test${variant.name.substringBeforeLast("UnitTest").capitalize()}CompileOnly"
-      else ->
-        "${variant.name}CompileOnly"
-    }
-    project.dependencies.add(compileOnlyConfigName, artifactView.files)
-  }
-
-  @Suppress("UnstableApiUsage")
-  private fun configureTransformASM(project: Project, hiltExtension: HiltExtension) {
-    var warnAboutLocalTestsFlag = false
-    fun registerTransform(androidComponent: Component) {
-      if (hiltExtension.enableTransformForLocalTests && !warnAboutLocalTestsFlag) {
-        project.logger.warn(
-          "The Hilt configuration option 'enableTransformForLocalTests' is no longer necessary " +
-            "when com.android.tools.build:gradle:4.2.0+ is used."
-        )
-        warnAboutLocalTestsFlag = true
-      }
-      androidComponent.transformClassesWith(
-        classVisitorFactoryImplClass = AndroidEntryPointClassVisitor.Factory::class.java,
-        scope = InstrumentationScope.PROJECT
-      ) { params ->
-        val classesDir =
-          File(project.buildDir, "intermediates/javac/${androidComponent.name}/classes")
-        params.additionalClassesDir.set(classesDir)
-      }
-      androidComponent.setAsmFramesComputationMode(
-        FramesComputationMode.COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS
-      )
-    }
-
-    val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
-    androidComponents.onVariants { registerTransform(it) }
-    androidComponents.androidTests { registerTransform(it) }
-    androidComponents.unitTests { registerTransform(it) }
-  }
-
-  private fun configureTransform(project: Project, hiltExtension: HiltExtension) {
-    val androidExtension = project.extensions.findByType(BaseExtension::class.java)
-      ?: throw error("Android BaseExtension not found.")
-    androidExtension.registerTransform(AndroidEntryPointTransform())
-
-    // Create and configure a task for applying the transform for host-side unit tests. b/37076369
-    val testedExtensions = project.extensions.findByType(TestedExtension::class.java)
-    testedExtensions?.unitTestVariants?.all { unitTestVariant ->
-      HiltTransformTestClassesTask.create(
-        project = project,
-        unitTestVariant = unitTestVariant,
-        extension = hiltExtension
-      )
-    }
-  }
-
-  private fun configureProcessorFlags(project: Project) {
-    val androidExtension = project.extensions.findByType(BaseExtension::class.java)
-      ?: throw error("Android BaseExtension not found.")
-    // Pass annotation processor flag to disable @AndroidEntryPoint superclass validation.
-    androidExtension.defaultConfig.apply {
-      javaCompileOptions.apply {
-        annotationProcessorOptions.apply {
-          PROCESSOR_OPTIONS.forEach { (key, value) -> argument(key, value) }
-        }
-      }
-    }
-  }
-
-  private fun verifyDependencies(project: Project) {
-    // If project is already failing, skip verification since dependencies might not be resolved.
-    if (project.state.failure != null) {
-      return
-    }
-    val dependencies = project.configurations.flatMap { configuration ->
-      configuration.dependencies.map { dependency -> dependency.group to dependency.name }
-    }
-    if (!dependencies.contains(LIBRARY_GROUP to "hilt-android")) {
-      error(missingDepError("$LIBRARY_GROUP:hilt-android"))
-    }
-    if (!dependencies.contains(LIBRARY_GROUP to "hilt-android-compiler") &&
-      !dependencies.contains(LIBRARY_GROUP to "hilt-compiler")
-    ) {
-      error(missingDepError("$LIBRARY_GROUP:hilt-compiler"))
-    }
-  }
-
-  companion object {
-    val ARTIFACT_TYPE_ATTRIBUTE = Attribute.of("artifactType", String::class.java)
-    const val DAGGER_ARTIFACT_TYPE_VALUE = "jar-for-dagger"
-
-    const val LIBRARY_GROUP = "com.google.dagger"
-    val PROCESSOR_OPTIONS = listOf(
-      "dagger.fastInit" to "enabled",
-      "dagger.hilt.android.internal.disableAndroidSuperclassValidation" to "true"
-    )
-    val missingDepError: (String) -> String = { depCoordinate ->
-      "The Hilt Android Gradle plugin is applied but no $depCoordinate dependency was found."
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltTransformTestClassesTask.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltTransformTestClassesTask.kt
deleted file mode 100644
index 84b35b1..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/HiltTransformTestClassesTask.kt
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.plugin
-
-import com.android.build.gradle.api.UnitTestVariant
-import dagger.hilt.android.plugin.util.isClassFile
-import dagger.hilt.android.plugin.util.isJarFile
-import java.io.File
-import javax.inject.Inject
-import org.gradle.api.Action
-import org.gradle.api.DefaultTask
-import org.gradle.api.Project
-import org.gradle.api.file.ConfigurableFileCollection
-import org.gradle.api.file.DirectoryProperty
-import org.gradle.api.file.FileCollection
-import org.gradle.api.provider.Property
-import org.gradle.api.tasks.Classpath
-import org.gradle.api.tasks.OutputDirectory
-import org.gradle.api.tasks.TaskAction
-import org.gradle.api.tasks.TaskProvider
-import org.gradle.api.tasks.compile.JavaCompile
-import org.gradle.api.tasks.testing.Test
-import org.gradle.workers.WorkAction
-import org.gradle.workers.WorkParameters
-import org.gradle.workers.WorkerExecutor
-import org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-/**
- * Task that transform classes used by host-side unit tests. See b/37076369
- */
-@Suppress("UnstableApiUsage")
-abstract class HiltTransformTestClassesTask @Inject constructor(
-  private val workerExecutor: WorkerExecutor
-) : DefaultTask() {
-
-  @get:Classpath
-  abstract val compiledClasses: ConfigurableFileCollection
-
-  @get:OutputDirectory
-  abstract val outputDir: DirectoryProperty
-
-  internal interface Parameters : WorkParameters {
-    val name: Property<String>
-    val compiledClasses: ConfigurableFileCollection
-    val outputDir: DirectoryProperty
-  }
-
-  abstract class WorkerAction : WorkAction<Parameters> {
-    override fun execute() {
-      val outputDir = parameters.outputDir.asFile.get()
-      outputDir.deleteRecursively()
-      outputDir.mkdirs()
-
-      val allInputs = parameters.compiledClasses.files.toList()
-      val classTransformer = AndroidEntryPointClassTransformer(
-        taskName = parameters.name.get(),
-        allInputs = allInputs,
-        sourceRootOutputDir = outputDir,
-        copyNonTransformed = false
-      )
-      // Parse the classpath in reverse so that we respect overwrites, if it ever happens.
-      allInputs.reversed().forEach {
-        if (it.isDirectory) {
-          it.walkTopDown().forEach { file ->
-            if (file.isClassFile()) {
-              classTransformer.transformFile(file)
-            }
-          }
-        } else if (it.isJarFile()) {
-          classTransformer.transformJarContents(it)
-        }
-      }
-    }
-  }
-
-  @TaskAction
-  fun transformClasses() {
-    workerExecutor.noIsolation().submit(WorkerAction::class.java) {
-      it.compiledClasses.from(compiledClasses)
-      it.outputDir.set(outputDir)
-      it.name.set(name)
-    }
-  }
-
-  internal class ConfigAction(
-    private val outputDir: File,
-    private val inputClasspath: FileCollection
-  ) : Action<HiltTransformTestClassesTask> {
-    override fun execute(transformTask: HiltTransformTestClassesTask) {
-      transformTask.description = "Transforms AndroidEntryPoint annotated classes for JUnit tests."
-      transformTask.outputDir.set(outputDir)
-      transformTask.compiledClasses.from(inputClasspath)
-    }
-  }
-
-  companion object {
-
-    private const val TASK_PREFIX = "hiltTransformFor"
-
-    fun create(
-      project: Project,
-      unitTestVariant: UnitTestVariant,
-      extension: HiltExtension
-    ) {
-      if (!extension.enableTransformForLocalTests) {
-        // Not enabled, nothing to do here.
-        return
-      }
-
-      // TODO(danysantiago): Only use project compiled sources as input, and not all dependency jars
-      // Using 'null' key to obtain the full compile classpath since we are not using the
-      // registerPreJavacGeneratedBytecode() API that would have otherwise given us a key to get
-      // a classpath up to the generated bytecode associated with the key.
-      val inputClasspath =
-        project.objects.fileCollection().from(unitTestVariant.getCompileClasspath(null))
-
-      // Find the test sources Java compile task and add its output directory into our input
-      // classpath file collection. This also makes the transform task depend on the test compile
-      // task.
-      @Suppress("UNCHECKED_CAST")
-      val testCompileTaskProvider = project.tasks.named(
-        "compile${unitTestVariant.name.capitalize()}JavaWithJavac"
-      ) as TaskProvider<JavaCompile>
-      inputClasspath.from(testCompileTaskProvider.map { it.destinationDirectory })
-
-      // Similarly, if the Kotlin plugin is configured, find the test sources Kotlin compile task
-      // and add its output directory to our input classpath file collection.
-      project.plugins.withType(KotlinBasePluginWrapper::class.java) {
-        @Suppress("UNCHECKED_CAST")
-        val kotlinCompileTaskProvider = project.tasks.named(
-          "compile${unitTestVariant.name.capitalize()}Kotlin"
-        ) as TaskProvider<KotlinCompile>
-        inputClasspath.from(kotlinCompileTaskProvider.map { it.destinationDirectory })
-      }
-
-      // Create and configure the transform task.
-      val outputDir =
-        project.buildDir.resolve("intermediates/hilt/${unitTestVariant.dirName}Output")
-      val hiltTransformProvider = project.tasks.register(
-        "$TASK_PREFIX${unitTestVariant.name.capitalize()}",
-        HiltTransformTestClassesTask::class.java,
-        ConfigAction(outputDir, inputClasspath)
-      )
-      // Map the transform task's output to a file collection.
-      val outputFileCollection =
-        project.objects.fileCollection().from(hiltTransformProvider.map { it.outputDir })
-
-      // Configure test classpath by appending the transform output file collection to the start of
-      // the test classpath so they override the original ones. This also makes test task (the one
-      // that runs the tests) depend on the transform task.
-      @Suppress("UNCHECKED_CAST")
-      val testTaskProvider = project.tasks.named(
-        "test${unitTestVariant.name.capitalize()}"
-      ) as TaskProvider<Test>
-      testTaskProvider.configure {
-        it.classpath = outputFileCollection + it.classpath
-      }
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/CopyTransform.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/CopyTransform.kt
deleted file mode 100644
index 39a2d3a..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/CopyTransform.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package dagger.hilt.android.plugin.util
-
-import org.gradle.api.artifacts.transform.CacheableTransform
-import org.gradle.api.artifacts.transform.InputArtifact
-import org.gradle.api.artifacts.transform.TransformAction
-import org.gradle.api.artifacts.transform.TransformOutputs
-import org.gradle.api.artifacts.transform.TransformParameters
-import org.gradle.api.file.FileSystemLocation
-import org.gradle.api.provider.Provider
-import org.gradle.api.tasks.Classpath
-
-// A transform that registers the input jar file as an output and thus changing from one artifact
-// type to another.
-// TODO: Improve to only copy classes that need to be visible by Hilt & Dagger.
-@CacheableTransform
-abstract class CopyTransform : TransformAction<TransformParameters.None> {
-  @get:Classpath
-  @get:InputArtifact
-  abstract val inputArtifactProvider: Provider<FileSystemLocation>
-
-  override fun transform(outputs: TransformOutputs) {
-    val input = inputArtifactProvider.get().asFile
-    when {
-      input.isDirectory -> outputs.dir(input)
-      input.isFile -> outputs.file(input)
-      else -> error("File/directory does not exist: ${input.absolutePath}")
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/Files.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/Files.kt
deleted file mode 100644
index e5a101e..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/Files.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package dagger.hilt.android.plugin.util
-
-import com.android.SdkConstants
-import java.io.File
-import java.util.zip.ZipEntry
-
-/* Checks if a file is a .class file. */
-fun File.isClassFile() = this.isFile && this.extension == SdkConstants.EXT_CLASS
-
-/* Checks if a Zip entry is a .class file. */
-fun ZipEntry.isClassFile() = !this.isDirectory && this.name.endsWith(SdkConstants.DOT_CLASS)
-
-/* CHecks if a file is a .jar file. */
-fun File.isJarFile() = this.isFile && this.extension == SdkConstants.EXT_JAR
diff --git a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/SimpleAGPVersion.kt b/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/SimpleAGPVersion.kt
deleted file mode 100644
index 1580431..0000000
--- a/java/dagger/hilt/android/plugin/src/main/kotlin/dagger/hilt/android/plugin/util/SimpleAGPVersion.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package dagger.hilt.android.plugin.util
-
-import com.android.Version
-
-/**
- * Simple Android Gradle Plugin version class since there is no public API one. b/175816217
- */
-internal data class SimpleAGPVersion(
-  val major: Int,
-  val minor: Int,
-) : Comparable<SimpleAGPVersion> {
-
-  override fun compareTo(other: SimpleAGPVersion): Int {
-    return compareValuesBy(
-      this,
-      other,
-      compareBy(SimpleAGPVersion::major).thenBy(SimpleAGPVersion::minor)
-    ) { it }
-  }
-
-  companion object {
-
-    val ANDROID_GRADLE_PLUGIN_VERSION by lazy { parse(Version.ANDROID_GRADLE_PLUGIN_VERSION) }
-
-    fun parse(version: String?) =
-      tryParse(version) ?: error("Unable to parse AGP version: $version")
-
-    private fun tryParse(version: String?): SimpleAGPVersion? {
-      if (version == null) {
-        return null
-      }
-
-      val parts = version.split('.')
-      if (parts.size == 1) {
-        return SimpleAGPVersion(parts[0].toInt(), 0)
-      }
-
-      return SimpleAGPVersion(parts[0].toInt(), parts[1].toInt())
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/main/resources/META-INF/gradle-plugins/dagger.hilt.android.plugin.properties b/java/dagger/hilt/android/plugin/src/main/resources/META-INF/gradle-plugins/dagger.hilt.android.plugin.properties
deleted file mode 100644
index 5d2b9df..0000000
--- a/java/dagger/hilt/android/plugin/src/main/resources/META-INF/gradle-plugins/dagger.hilt.android.plugin.properties
+++ /dev/null
@@ -1 +0,0 @@
-implementation-class=dagger.hilt.android.plugin.HiltGradlePlugin
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/build.gradle b/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/build.gradle
deleted file mode 100644
index e2d2a7b..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/build.gradle
+++ /dev/null
@@ -1,28 +0,0 @@
-plugins {
-    id 'com.android.library'
-    id 'dagger.hilt.android.plugin'
-}
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        minSdkVersion 21
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-}
-
-dependencies {
-    implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-    annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-
-    implementation project(':libraryB')
-    implementation project(':libraryC')
-}
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/src/main/AndroidManifest.xml b/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/src/main/AndroidManifest.xml
deleted file mode 100644
index e704d4a..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="liba">
-</manifest>
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/src/main/java/liba/LibraryA.java b/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/src/main/java/liba/LibraryA.java
deleted file mode 100644
index 95e9356..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/android-libraryA/src/main/java/liba/LibraryA.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2020 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 liba;
-
-import javax.inject.Inject;
-import libb.LibraryB;
-import libc.LibraryC;
-
-/** Test LibA */
-public class LibraryA {
-  @Inject
-  public LibraryA(LibraryB b, LibraryC c) {}
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/build.gradle b/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/build.gradle
deleted file mode 100644
index 3031528..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/build.gradle
+++ /dev/null
@@ -1,25 +0,0 @@
-plugins {
-    id 'com.android.library'
-    id 'dagger.hilt.android.plugin'
-}
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        minSdkVersion 21
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-}
-
-dependencies {
-    implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-    annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-}
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/src/main/AndroidManifest.xml b/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/src/main/AndroidManifest.xml
deleted file mode 100644
index a4967e3..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="libc">
-</manifest>
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/src/main/java/libc/LibraryC.java b/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/src/main/java/libc/LibraryC.java
deleted file mode 100644
index f7397fc..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/android-libraryC/src/main/java/libc/LibraryC.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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 libc;
-
-import javax.inject.Inject;
-
-/** Test LibC */
-public class LibraryC {
-  @Inject
-  public LibraryC() {}
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/java-libraryA/build.gradle b/java/dagger/hilt/android/plugin/src/test/data/java-libraryA/build.gradle
deleted file mode 100644
index dde8858..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/java-libraryA/build.gradle
+++ /dev/null
@@ -1,15 +0,0 @@
-plugins {
-    id 'java-library'
-}
-
-java {
-    sourceCompatibility = JavaVersion.VERSION_1_8
-    targetCompatibility = JavaVersion.VERSION_1_8
-}
-
-dependencies {
-    implementation 'com.google.dagger:hilt-core:LOCAL-SNAPSHOT'
-    annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-
-    implementation project(':libraryB')
-}
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/src/test/data/java-libraryA/src/main/java/liba/LibraryA.java b/java/dagger/hilt/android/plugin/src/test/data/java-libraryA/src/main/java/liba/LibraryA.java
deleted file mode 100644
index afc0da2..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/java-libraryA/src/main/java/liba/LibraryA.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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 liba;
-
-import javax.inject.Inject;
-import libb.LibraryBProvided;
-
-/** Test LibA */
-public class LibraryA {
-  @Inject
-  public LibraryA(LibraryBProvided b) {}
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/build.gradle b/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/build.gradle
deleted file mode 100644
index 55780cc..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/build.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-plugins {
-    id 'java-library'
-}
-
-java {
-    sourceCompatibility = JavaVersion.VERSION_1_8
-    targetCompatibility = JavaVersion.VERSION_1_8
-}
-
-dependencies {
-    implementation 'com.google.dagger:hilt-core:LOCAL-SNAPSHOT'
-    annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-}
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryB.java b/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryB.java
deleted file mode 100644
index 285d5ba..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryB.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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 libb;
-
-import javax.inject.Inject;
-
-/** Test LibB */
-public class LibraryB {
-  @Inject
-  public LibraryB() {}
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryBModule.java b/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryBModule.java
deleted file mode 100644
index d1c08f0..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryBModule.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 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 libb;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.components.SingletonComponent;
-
-/** Test LibB Module */
-@Module
-@InstallIn(SingletonComponent.class)
-public final class LibraryBModule {
-  @Provides
-  public static LibraryBProvided provideB() {
-    return new LibraryBProvided();
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryBProvided.java b/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryBProvided.java
deleted file mode 100644
index b472bfb..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/java-libraryB/src/main/java/libb/LibraryBProvided.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2020 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 libb;
-
-/** Test LibB Provided */
-public class LibraryBProvided {}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/simple-project/gradle.properties b/java/dagger/hilt/android/plugin/src/test/data/simple-project/gradle.properties
deleted file mode 100644
index 5bac8ac..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/simple-project/gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-android.useAndroidX=true
diff --git a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/AndroidManifest.xml b/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/AndroidManifest.xml
deleted file mode 100644
index 29060e0..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="simple">
-</manifest>
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Activity1.java b/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Activity1.java
deleted file mode 100644
index a6e5d93..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Activity1.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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 simple;
-
-import androidx.appcompat.app.AppCompatActivity;
-import dagger.hilt.android.AndroidEntryPoint;
-import javax.inject.Inject;
-
-/** Just an activity. */
-@AndroidEntryPoint(AppCompatActivity.class)
-public class Activity1 extends Hilt_Activity1 {
-  @Inject String data;
-
-  // Insert-change
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Activity2.java b/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Activity2.java
deleted file mode 100644
index f7793be..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Activity2.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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 simple;
-
-import androidx.appcompat.app.AppCompatActivity;
-import dagger.hilt.android.AndroidEntryPoint;
-import javax.inject.Inject;
-
-/** Just an activity. */
-@AndroidEntryPoint(AppCompatActivity.class)
-public class Activity2 extends Hilt_Activity2 {
-  @Inject String data;
-
-  // Insert-change
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Module1.java b/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Module1.java
deleted file mode 100644
index d3297c3..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Module1.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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 simple;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-
-/** Just a module. */
-@Module
-@InstallIn(ActivityComponent.class)
-public class Module1 {
-
-  @Provides
-  static String provideData() {
-    return "010101";
-  }
-
-  // Insert-change
-
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Module2.java b/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Module2.java
deleted file mode 100644
index dd23236..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/Module2.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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 simple;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-
-/** Just a module. */
-@Module
-@InstallIn(ActivityComponent.class)
-public class Module2 {
-
-  @Provides
-  static int provideData() {
-    return 0x010101;
-  }
-
-  // Insert-change
-
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/SimpleApp.java b/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/SimpleApp.java
deleted file mode 100644
index 5a92241..0000000
--- a/java/dagger/hilt/android/plugin/src/test/data/simple-project/src/main/java/simple/SimpleApp.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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 simple;
-
-import android.app.Application;
-import dagger.hilt.android.HiltAndroidApp;
-
-/** Just an application. */
-@HiltAndroidApp(Application.class)
-public class SimpleApp extends Hilt_SimpleApp {
-  // Insert-change
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/kotlin/CompileClasspathTest.kt b/java/dagger/hilt/android/plugin/src/test/kotlin/CompileClasspathTest.kt
deleted file mode 100644
index 6141250..0000000
--- a/java/dagger/hilt/android/plugin/src/test/kotlin/CompileClasspathTest.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-import java.io.File
-import org.gradle.testkit.runner.TaskOutcome
-import org.junit.Assert.assertEquals
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TemporaryFolder
-
-class CompileClasspathTest {
-  @get:Rule
-  val testProjectDir = TemporaryFolder()
-
-  lateinit var gradleRunner: GradleTestRunner
-
-  @Before
-  fun setup() {
-    gradleRunner = GradleTestRunner(testProjectDir)
-    gradleRunner.addAndroidOption(
-      "lintOptions.checkReleaseBuilds = false"
-    )
-    gradleRunner.addHiltOption(
-      "enableExperimentalClasspathAggregation = true"
-    )
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'",
-      "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'",
-      "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'",
-      "implementation project(':libraryA')",
-    )
-    gradleRunner.addSrc(
-      srcPath = "minimal/MyApp.java",
-      srcContent =
-        """
-        package minimal;
-
-        import android.app.Application;
-        import liba.LibraryA;
-
-        @dagger.hilt.android.HiltAndroidApp
-        public class MyApp extends Application {
-          @javax.inject.Inject
-          LibraryA libraryA;
-        }
-        """.trimIndent()
-    )
-    gradleRunner.setAppClassName(".MyApp")
-  }
-
-  // Verifies that library B and library C injected classes are available in the root classpath.
-  @Test
-  fun test_injectClasses() {
-    File("src/test/data/android-libraryA")
-      .copyRecursively(File(testProjectDir.root, "libraryA"))
-    File("src/test/data/java-libraryB")
-      .copyRecursively(File(testProjectDir.root, "libraryB"))
-    File("src/test/data/android-libraryC")
-      .copyRecursively(File(testProjectDir.root, "libraryC"))
-
-    testProjectDir.newFile("settings.gradle").apply {
-      writeText(
-        """
-        include ':libraryA'
-        include ':libraryB'
-        include ':libraryC'
-        """.trimIndent()
-      )
-    }
-
-    val result = gradleRunner.build()
-    val assembleTask = result.getTask(":assembleDebug")
-    assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-  }
-
-  // Verifies that library B Hilt module is available in the root classpath.
-  @Test
-  fun test_injectClassesFromModules() {
-    File("src/test/data/java-libraryA")
-      .copyRecursively(File(testProjectDir.root, "libraryA"))
-    File("src/test/data/java-libraryB")
-      .copyRecursively(File(testProjectDir.root, "libraryB"))
-
-    testProjectDir.newFile("settings.gradle").apply {
-      writeText(
-        """
-        include ':libraryA'
-        include ':libraryB'
-        """.trimIndent()
-      )
-    }
-
-    val result = gradleRunner.build()
-    val assembleTask = result.getTask(":assembleDebug")
-    assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/kotlin/GradleTestRunner.kt b/java/dagger/hilt/android/plugin/src/test/kotlin/GradleTestRunner.kt
deleted file mode 100644
index 2d58766..0000000
--- a/java/dagger/hilt/android/plugin/src/test/kotlin/GradleTestRunner.kt
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-import java.io.File
-import org.gradle.testkit.runner.BuildResult
-import org.gradle.testkit.runner.GradleRunner
-import org.junit.rules.TemporaryFolder
-
-/**
- * Testing utility class that sets up a simple Android project that applies the Hilt plugin.
- */
-class GradleTestRunner(val tempFolder: TemporaryFolder) {
-  private val dependencies = mutableListOf<String>()
-  private val activities = mutableListOf<String>()
-  private val additionalAndroidOptions = mutableListOf<String>()
-  private val hiltOptions = mutableListOf<String>()
-  private var appClassName: String? = null
-  private var buildFile: File? = null
-  private var gradlePropertiesFile: File? = null
-  private var manifestFile: File? = null
-
-  init {
-    tempFolder.newFolder("src", "main", "java", "minimal")
-    tempFolder.newFolder("src", "main", "res")
-  }
-
-  // Adds project dependencies, e.g. "implementation <group>:<id>:<version>"
-  fun addDependencies(vararg deps: String) {
-    dependencies.addAll(deps)
-  }
-
-  // Adds an <activity> tag in the project's Android Manifest, e.g. "<activity name=".Foo"/>
-  fun addActivities(vararg activityElements: String) {
-    activities.addAll(activityElements)
-  }
-
-  // Adds 'android' options to the project's build.gradle, e.g. "lintOptions.checkReleaseBuilds = false"
-  fun addAndroidOption(vararg options: String) {
-    additionalAndroidOptions.addAll(options)
-  }
-
-  // Adds 'hilt' options to the project's build.gradle, e.g. "enableExperimentalClasspathAggregation = true"
-  fun addHiltOption(vararg options: String) {
-    hiltOptions.addAll(options)
-  }
-
-  // Adds a source package to the project. The package path is relative to 'src/main/java'.
-  fun addSrcPackage(packagePath: String) {
-    File(tempFolder.root, "src/main/java/$packagePath").mkdirs()
-  }
-
-  // Adds a source file to the project. The source path is relative to 'src/main/java'.
-  fun addSrc(srcPath: String, srcContent: String): File {
-    File(tempFolder.root, "src/main/java/${srcPath.substringBeforeLast(File.separator)}").mkdirs()
-    return tempFolder.newFile("/src/main/java/$srcPath").apply { writeText(srcContent) }
-  }
-
-  // Adds a resource file to the project. The source path is relative to 'src/main/res'.
-  fun addRes(resPath: String, resContent: String): File {
-    File(tempFolder.root, "src/main/res/${resPath.substringBeforeLast(File.separator)}").mkdirs()
-    return tempFolder.newFile("/src/main/res/$resPath").apply { writeText(resContent) }
-  }
-
-  fun setAppClassName(name: String) {
-    appClassName = name
-  }
-
-  // Executes a Gradle builds and expects it to succeed.
-  fun build(): Result {
-    setupFiles()
-    return Result(tempFolder.root, createRunner().build())
-  }
-
-  // Executes a Gradle build and expects it to fail.
-  fun buildAndFail(): Result {
-    setupFiles()
-    return Result(tempFolder.root, createRunner().buildAndFail())
-  }
-
-  private fun setupFiles() {
-    writeBuildFile()
-    writeGradleProperties()
-    writeAndroidManifest()
-  }
-
-  private fun writeBuildFile() {
-    buildFile?.delete()
-    buildFile = tempFolder.newFile("build.gradle").apply {
-      writeText(
-        """
-        buildscript {
-          repositories {
-            google()
-            jcenter()
-          }
-          dependencies {
-            classpath 'com.android.tools.build:gradle:4.2.0-beta04'
-          }
-        }
-
-        plugins {
-          id 'com.android.application'
-          id 'dagger.hilt.android.plugin'
-        }
-
-        android {
-          compileSdkVersion 30
-          buildToolsVersion "30.0.2"
-
-          defaultConfig {
-            applicationId "plugin.test"
-            minSdkVersion 21
-            targetSdkVersion 30
-          }
-
-          compileOptions {
-              sourceCompatibility 1.8
-              targetCompatibility 1.8
-          }
-          ${additionalAndroidOptions.joinToString(separator = "\n")}
-        }
-
-        allprojects {
-          repositories {
-            mavenLocal()
-            google()
-            jcenter()
-          }
-        }
-
-        dependencies {
-          ${dependencies.joinToString(separator = "\n")}
-        }
-
-        hilt {
-          ${hiltOptions.joinToString(separator = "\n")}
-        }
-        """.trimIndent()
-      )
-    }
-  }
-
-  private fun writeGradleProperties() {
-    gradlePropertiesFile?.delete()
-    gradlePropertiesFile = tempFolder.newFile("gradle.properties").apply {
-      writeText(
-        """
-        android.useAndroidX=true
-        """.trimIndent()
-      )
-    }
-  }
-
-  private fun writeAndroidManifest() {
-    manifestFile?.delete()
-    manifestFile = tempFolder.newFile("/src/main/AndroidManifest.xml").apply {
-      writeText(
-        """
-        <?xml version="1.0" encoding="utf-8"?>
-        <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="minimal">
-            <application
-                android:name="${appClassName ?: "android.app.Application"}"
-                android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
-                ${activities.joinToString(separator = "\n")}
-            </application>
-        </manifest>
-        """.trimIndent()
-      )
-    }
-  }
-
-  private fun createRunner() = GradleRunner.create()
-    .withProjectDir(tempFolder.root)
-    .withArguments("assembleDebug", "--stacktrace")
-    .withPluginClasspath()
-//    .withDebug(true) // Add this line to enable attaching a debugger to the gradle test invocation
-    .forwardOutput()
-
-  // Data class representing a Gradle Test run result.
-  data class Result(
-    private val projectRoot: File,
-    private val buildResult: BuildResult
-  ) {
-    // Finds a task by name.
-    fun getTask(name: String) = buildResult.task(name) ?: error("Task '$name' not found.")
-
-    // Gets the full build output.
-    fun getOutput() = buildResult.output
-
-    // Finds a transformed file. The srcFilePath is relative to the app's package.
-    fun getTransformedFile(srcFilePath: String): File {
-      val parentDir =
-        File(projectRoot, "build/intermediates/asm_instrumented_project_classes/debug")
-      return File(parentDir, srcFilePath).also {
-        if (!it.exists()) {
-          error("Unable to find transformed class ${it.path}")
-        }
-      }
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/kotlin/HiltGradlePluginTest.kt b/java/dagger/hilt/android/plugin/src/test/kotlin/HiltGradlePluginTest.kt
deleted file mode 100644
index f256985..0000000
--- a/java/dagger/hilt/android/plugin/src/test/kotlin/HiltGradlePluginTest.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TemporaryFolder
-
-/**
- * Functional test of the plugin
- *
- * To run these tests first deploy artifacts to local maven via util/install-local-snapshot.sh.
- */
-class HiltGradlePluginTest {
-
-  @get:Rule
-  val testProjectDir = TemporaryFolder()
-
-  lateinit var gradleRunner: GradleTestRunner
-
-  @Before
-  fun setup() {
-    gradleRunner = GradleTestRunner(testProjectDir)
-  }
-
-  // Verify plugin configuration fails when runtime dependency is missing but plugin is applied.
-  @Test
-  fun test_missingLibraryDep() {
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'"
-    )
-
-    val result = gradleRunner.buildAndFail()
-    assertThat(result.getOutput()).contains(
-      "The Hilt Android Gradle plugin is applied but no " +
-        "com.google.dagger:hilt-android dependency was found."
-    )
-  }
-
-  // Verify plugin configuration fails when compiler dependency is missing but plugin is applied.
-  @Test
-  fun test_missingCompilerDep() {
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'",
-      "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'"
-    )
-
-    val result = gradleRunner.buildAndFail()
-    assertThat(result.getOutput()).contains(
-      "The Hilt Android Gradle plugin is applied but no " +
-        "com.google.dagger:hilt-compiler dependency was found."
-    )
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/kotlin/IncrementalProcessorTest.kt b/java/dagger/hilt/android/plugin/src/test/kotlin/IncrementalProcessorTest.kt
deleted file mode 100644
index a003ab5..0000000
--- a/java/dagger/hilt/android/plugin/src/test/kotlin/IncrementalProcessorTest.kt
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-import com.google.common.truth.Expect
-import java.io.File
-import org.gradle.testkit.runner.BuildResult
-import org.gradle.testkit.runner.GradleRunner
-import org.gradle.testkit.runner.TaskOutcome
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TemporaryFolder
-
-/**
- * Tests to verify Gradle annotation processor incremental compilation.
- *
- * To run these tests first deploy artifacts to local maven via util/install-local-snapshot.sh.
- */
-class IncrementalProcessorTest {
-
-  @get:Rule
-  val testProjectDir = TemporaryFolder()
-
-  @get:Rule
-  val expect: Expect = Expect.create()
-
-  // Original source files
-  private lateinit var srcApp: File
-  private lateinit var srcActivity1: File
-  private lateinit var srcActivity2: File
-  private lateinit var srcModule1: File
-  private lateinit var srcModule2: File
-
-  // Generated source files
-  private lateinit var genHiltApp: File
-  private lateinit var genHiltActivity1: File
-  private lateinit var genHiltActivity2: File
-  private lateinit var genAppInjector: File
-  private lateinit var genActivityInjector1: File
-  private lateinit var genActivityInjector2: File
-  private lateinit var genAppInjectorDeps: File
-  private lateinit var genActivityInjectorDeps1: File
-  private lateinit var genActivityInjectorDeps2: File
-  private lateinit var genModuleDeps1: File
-  private lateinit var genModuleDeps2: File
-  private lateinit var genHiltComponents: File
-  private lateinit var genDaggerHiltApplicationComponent: File
-
-  // Compiled classes
-  private lateinit var classSrcApp: File
-  private lateinit var classSrcActivity1: File
-  private lateinit var classSrcActivity2: File
-  private lateinit var classSrcModule1: File
-  private lateinit var classSrcModule2: File
-  private lateinit var classGenHiltApp: File
-  private lateinit var classGenHiltActivity1: File
-  private lateinit var classGenHiltActivity2: File
-  private lateinit var classGenAppInjector: File
-  private lateinit var classGenActivityInjector1: File
-  private lateinit var classGenActivityInjector2: File
-  private lateinit var classGenAppInjectorDeps: File
-  private lateinit var classGenActivityInjectorDeps1: File
-  private lateinit var classGenActivityInjectorDeps2: File
-  private lateinit var classGenModuleDeps1: File
-  private lateinit var classGenModuleDeps2: File
-  private lateinit var classGenHiltComponents: File
-  private lateinit var classGenDaggerHiltApplicationComponent: File
-
-  // Timestamps of files
-  private lateinit var fileToTimestampMap: Map<File, Long>
-
-  // Sets of files that have changed/not changed/deleted
-  private lateinit var changedFiles: Set<File>
-  private lateinit var unchangedFiles: Set<File>
-  private lateinit var deletedFiles: Set<File>
-
-  @Before
-  fun setup() {
-    val projectRoot = testProjectDir.root
-    // copy test project
-    File("src/test/data/simple-project").copyRecursively(projectRoot)
-
-    // set up build file
-    File(projectRoot, "build.gradle").writeText(
-      """
-      buildscript {
-        repositories {
-          google()
-          jcenter()
-        }
-        dependencies {
-          classpath 'com.android.tools.build:gradle:3.5.3'
-        }
-      }
-
-      plugins {
-        id 'com.android.application'
-      }
-
-      android {
-        compileSdkVersion 30
-        buildToolsVersion "30.0.2"
-
-        defaultConfig {
-          applicationId "hilt.simple"
-          minSdkVersion 21
-          targetSdkVersion 30
-        }
-
-        compileOptions {
-            sourceCompatibility 1.8
-            targetCompatibility 1.8
-        }
-      }
-
-      repositories {
-        mavenLocal()
-        google()
-        jcenter()
-      }
-
-      dependencies {
-        implementation 'androidx.appcompat:appcompat:1.1.0'
-        implementation 'com.google.dagger:dagger:LOCAL-SNAPSHOT'
-        annotationProcessor 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
-        implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-        annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-      }
-      """.trimIndent()
-    )
-
-    // Compute file paths
-    srcApp = File(projectRoot, "$SRC_DIR/simple/SimpleApp.java")
-    srcActivity1 = File(projectRoot, "$SRC_DIR/simple/Activity1.java")
-    srcActivity2 = File(projectRoot, "$SRC_DIR/simple/Activity2.java")
-    srcModule1 = File(projectRoot, "$SRC_DIR/simple/Module1.java")
-    srcModule2 = File(projectRoot, "$SRC_DIR/simple/Module2.java")
-
-    genHiltApp = File(projectRoot, "$GEN_SRC_DIR/simple/Hilt_SimpleApp.java")
-    genHiltActivity1 = File(projectRoot, "$GEN_SRC_DIR/simple/Hilt_Activity1.java")
-    genHiltActivity2 = File(projectRoot, "$GEN_SRC_DIR/simple/Hilt_Activity2.java")
-    genAppInjector = File(projectRoot, "$GEN_SRC_DIR/simple/SimpleApp_GeneratedInjector.java")
-    genActivityInjector1 = File(projectRoot, "$GEN_SRC_DIR/simple/Activity1_GeneratedInjector.java")
-    genActivityInjector2 = File(projectRoot, "$GEN_SRC_DIR/simple/Activity2_GeneratedInjector.java")
-    genAppInjectorDeps = File(
-      projectRoot,
-      "$GEN_SRC_DIR/hilt_aggregated_deps/simple_SimpleApp_GeneratedInjectorModuleDeps.java"
-    )
-    genActivityInjectorDeps1 = File(
-      projectRoot,
-      "$GEN_SRC_DIR/hilt_aggregated_deps/simple_Activity1_GeneratedInjectorModuleDeps.java"
-    )
-    genActivityInjectorDeps2 = File(
-      projectRoot,
-      "$GEN_SRC_DIR/hilt_aggregated_deps/simple_Activity2_GeneratedInjectorModuleDeps.java"
-    )
-    genModuleDeps1 = File(
-      projectRoot,
-      "$GEN_SRC_DIR/hilt_aggregated_deps/simple_Module1ModuleDeps.java"
-    )
-    genModuleDeps2 = File(
-      projectRoot,
-      "$GEN_SRC_DIR/hilt_aggregated_deps/simple_Module2ModuleDeps.java"
-    )
-    genHiltComponents = File(
-      projectRoot,
-      "$GEN_SRC_DIR/simple/SimpleApp_HiltComponents.java"
-    )
-    genDaggerHiltApplicationComponent = File(
-      projectRoot,
-      "$GEN_SRC_DIR/simple/DaggerSimpleApp_HiltComponents_SingletonC.java"
-    )
-
-    classSrcApp = File(projectRoot, "$CLASS_DIR/simple/SimpleApp.class")
-    classSrcActivity1 = File(projectRoot, "$CLASS_DIR/simple/Activity1.class")
-    classSrcActivity2 = File(projectRoot, "$CLASS_DIR/simple/Activity2.class")
-    classSrcModule1 = File(projectRoot, "$CLASS_DIR/simple/Module1.class")
-    classSrcModule2 = File(projectRoot, "$CLASS_DIR/simple/Module2.class")
-    classGenHiltApp = File(projectRoot, "$CLASS_DIR/simple/Hilt_SimpleApp.class")
-    classGenHiltActivity1 = File(projectRoot, "$CLASS_DIR/simple/Hilt_Activity1.class")
-    classGenHiltActivity2 = File(projectRoot, "$CLASS_DIR/simple/Hilt_Activity2.class")
-    classGenAppInjector = File(projectRoot, "$CLASS_DIR/simple/SimpleApp_GeneratedInjector.class")
-    classGenActivityInjector1 = File(
-      projectRoot,
-      "$CLASS_DIR/simple/Activity1_GeneratedInjector.class"
-    )
-    classGenActivityInjector2 = File(
-      projectRoot,
-      "$CLASS_DIR/simple/Activity2_GeneratedInjector.class"
-    )
-    classGenAppInjectorDeps = File(
-      projectRoot,
-      "$CLASS_DIR/hilt_aggregated_deps/simple_SimpleApp_GeneratedInjectorModuleDeps.class"
-    )
-    classGenActivityInjectorDeps1 = File(
-      projectRoot,
-      "$CLASS_DIR/hilt_aggregated_deps/simple_Activity1_GeneratedInjectorModuleDeps.class"
-    )
-    classGenActivityInjectorDeps2 = File(
-      projectRoot,
-      "$CLASS_DIR/hilt_aggregated_deps/simple_Activity2_GeneratedInjectorModuleDeps.class"
-    )
-    classGenModuleDeps1 = File(
-      projectRoot,
-      "$CLASS_DIR/hilt_aggregated_deps/simple_Module1ModuleDeps.class"
-    )
-    classGenModuleDeps2 = File(
-      projectRoot,
-      "$CLASS_DIR/hilt_aggregated_deps/simple_Module2ModuleDeps.class"
-    )
-    classGenHiltComponents = File(
-      projectRoot,
-      "$CLASS_DIR/simple/SimpleApp_HiltComponents.class"
-    )
-    classGenDaggerHiltApplicationComponent = File(
-      projectRoot,
-      "$CLASS_DIR/simple/DaggerSimpleApp_HiltComponents_SingletonC.class"
-    )
-  }
-
-  @Test
-  fun firstFullBuild() {
-    // This test verifies the results of the first full (non-incremental) build. The other tests
-    // verify the results of the second incremental build based on different change scenarios.
-    val result = runFullBuild()
-    expect.that(result.task(COMPILE_TASK)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
-
-    // Check annotation processing outputs
-    assertFilesExist(
-      genHiltApp,
-      genHiltActivity1,
-      genHiltActivity2,
-      genAppInjector,
-      genActivityInjector1,
-      genActivityInjector2,
-      genAppInjectorDeps,
-      genActivityInjectorDeps1,
-      genActivityInjectorDeps2,
-      genModuleDeps1,
-      genModuleDeps2,
-      genHiltComponents,
-      genDaggerHiltApplicationComponent
-    )
-
-    // Check compilation outputs
-    assertFilesExist(
-      classSrcApp,
-      classSrcActivity1,
-      classSrcActivity2,
-      classSrcModule1,
-      classSrcModule2,
-      classGenHiltApp,
-      classGenHiltActivity1,
-      classGenHiltActivity2,
-      classGenAppInjector,
-      classGenActivityInjector1,
-      classGenActivityInjector2,
-      classGenAppInjectorDeps,
-      classGenActivityInjectorDeps1,
-      classGenActivityInjectorDeps2,
-      classGenModuleDeps1,
-      classGenModuleDeps2,
-      classGenHiltComponents,
-      classGenDaggerHiltApplicationComponent
-    )
-  }
-
-  @Test
-  fun changeActivitySource() {
-    runFullBuild()
-
-    // Change Activity 1 source
-    searchAndReplace(
-      srcActivity1, "// Insert-change",
-      """
-      @Override
-      public void onResume() {
-        super.onResume();
-      }
-      """.trimIndent()
-    )
-
-    val result = runIncrementalBuild()
-    expect.that(result.task(COMPILE_TASK)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
-
-    // Check annotation processing outputs
-    // * Only activity 1 sources are re-generated, isolation in modules and from other activities
-    // * Root classes along with components are always re-generated (aggregated processor)
-    assertChangedFiles(
-      FileType.JAVA,
-      genHiltApp,
-      genHiltActivity1,
-      genAppInjector,
-      genActivityInjector1,
-      genAppInjectorDeps,
-      genActivityInjectorDeps1,
-      genHiltComponents,
-      genDaggerHiltApplicationComponent
-    )
-
-    // Check compilation outputs
-    // * Gen sources from activity 1 are re-compiled
-    // * All aggregating processor gen sources are re-compiled
-    assertChangedFiles(
-      FileType.CLASS,
-      classSrcActivity1,
-      classGenHiltApp,
-      classGenHiltActivity1,
-      classGenAppInjector,
-      classGenActivityInjector1,
-      classGenAppInjectorDeps,
-      classGenActivityInjectorDeps1,
-      classGenHiltComponents,
-      classGenDaggerHiltApplicationComponent
-    )
-  }
-
-  @Test
-  fun changeModuleSource() {
-    runFullBuild()
-
-    // Change Module 1 source
-    searchAndReplace(
-      srcModule1, "// Insert-change",
-      """
-      @Provides
-      static double provideDouble() {
-        return 10.10;
-      }
-      """.trimIndent()
-    )
-
-    val result = runIncrementalBuild()
-    expect.that(result.task(COMPILE_TASK)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
-
-    // Check annotation processing outputs
-    // * Only module 1 sources are re-generated, isolation from other modules
-    // * Root classes along with components are always re-generated (aggregated processor)
-    assertChangedFiles(
-      FileType.JAVA,
-      genHiltApp,
-      genAppInjector,
-      genAppInjectorDeps,
-      genModuleDeps1,
-      genHiltComponents,
-      genDaggerHiltApplicationComponent
-    )
-
-    // Check compilation outputs
-    // * Gen sources from module 1 are re-compiled
-    // * All aggregating processor gen sources are re-compiled
-    assertChangedFiles(
-      FileType.CLASS,
-      classSrcModule1,
-      classGenHiltApp,
-      classGenAppInjector,
-      classGenAppInjectorDeps,
-      classGenModuleDeps1,
-      classGenHiltComponents,
-      classGenDaggerHiltApplicationComponent
-    )
-  }
-
-  @Test
-  fun changeAppSource() {
-    runFullBuild()
-
-    // Change Application source
-    searchAndReplace(
-      srcApp, "// Insert-change",
-      """
-      @Override
-      public void onCreate() {
-        super.onCreate();
-      }
-      """.trimIndent()
-    )
-
-    val result = runIncrementalBuild()
-    expect.that(result.task(COMPILE_TASK)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
-
-    // Check annotation processing outputs
-    // * No modules or activities (or any other non-root) classes should be generated
-    // * Root classes along with components are always re-generated (aggregated processor)
-    assertChangedFiles(
-      FileType.JAVA,
-      genHiltApp,
-      genAppInjector,
-      genAppInjectorDeps,
-      genHiltComponents,
-      genDaggerHiltApplicationComponent
-    )
-
-    // Check compilation outputs
-    // * All aggregating processor gen sources are re-compiled
-    assertChangedFiles(
-      FileType.CLASS,
-      classSrcApp, // re-compiles because superclass re-compiled
-      classGenHiltApp,
-      classGenAppInjector,
-      classGenAppInjectorDeps,
-      classGenHiltComponents,
-      classGenDaggerHiltApplicationComponent
-    )
-  }
-
-  @Test
-  fun deleteActivitySource() {
-    runFullBuild()
-
-    srcActivity2.delete()
-
-    val result = runIncrementalBuild()
-    expect.that(result.task(COMPILE_TASK)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
-
-    // Check annotation processing outputs
-    // * All related gen classes from activity 2 should be deleted
-    // * Unrelated activities and modules are in isolation and should be unchanged
-    // * Root classes along with components are always re-generated (aggregated processor)
-    assertDeletedFiles(
-      genHiltActivity2,
-      genActivityInjector2,
-      genActivityInjectorDeps2
-    )
-    assertChangedFiles(
-      FileType.JAVA,
-      genHiltApp,
-      genAppInjector,
-      genAppInjectorDeps,
-      genHiltComponents,
-      genDaggerHiltApplicationComponent
-    )
-
-    // Check compilation outputs
-    // * All compiled classes from activity 2 should be deleted
-    // * Unrelated activities and modules are in isolation and should be unchanged
-    assertDeletedFiles(
-      classSrcActivity2,
-      classGenHiltActivity2,
-      classGenActivityInjector2,
-      classGenActivityInjectorDeps2
-    )
-    assertChangedFiles(
-      FileType.CLASS,
-      classGenHiltApp,
-      classGenAppInjector,
-      classGenAppInjectorDeps,
-      classGenHiltComponents,
-      classGenDaggerHiltApplicationComponent
-    )
-  }
-
-  @Test
-  fun deleteModuleSource() {
-    runFullBuild()
-
-    srcModule2.delete()
-
-    val result = runIncrementalBuild()
-    expect.that(result.task(COMPILE_TASK)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
-
-    // Check annotation processing outputs
-    // * All related gen classes from module 2 should be deleted
-    // * Unrelated activities and modules are in isolation and should be unchanged
-    // * Root classes along with components are always re-generated (aggregated processor)
-    assertDeletedFiles(
-      genModuleDeps2
-    )
-    assertChangedFiles(
-      FileType.JAVA,
-      genHiltApp,
-      genAppInjector,
-      genAppInjectorDeps,
-      genHiltComponents,
-      genDaggerHiltApplicationComponent
-    )
-
-    // Check compilation outputs
-    // * All compiled classes from module 2 should be deleted
-    // * Unrelated activities and modules are in isolation and should be unchanged
-    assertDeletedFiles(
-      classSrcModule2,
-      classGenModuleDeps2
-    )
-    assertChangedFiles(
-      FileType.CLASS,
-      classGenHiltApp,
-      classGenAppInjector,
-      classGenAppInjectorDeps,
-      classGenHiltComponents,
-      classGenDaggerHiltApplicationComponent
-    )
-  }
-
-  private fun runGradleTasks(vararg args: String): BuildResult {
-    return GradleRunner.create()
-      .withProjectDir(testProjectDir.root)
-      .withArguments(*args)
-      .withPluginClasspath()
-      .forwardOutput()
-      .build()
-  }
-
-  private fun runFullBuild(): BuildResult {
-    val result = runGradleTasks(CLEAN_TASK, COMPILE_TASK)
-    recordTimestamps()
-    return result
-  }
-
-  private fun runIncrementalBuild(): BuildResult {
-    val result = runGradleTasks(COMPILE_TASK)
-    recordFileChanges()
-    return result
-  }
-  private fun recordTimestamps() {
-    val files = listOf(
-      genHiltApp,
-      genHiltActivity1,
-      genHiltActivity2,
-      genAppInjector,
-      genActivityInjector1,
-      genActivityInjector2,
-      genAppInjectorDeps,
-      genActivityInjectorDeps1,
-      genActivityInjectorDeps2,
-      genModuleDeps1,
-      genModuleDeps2,
-      genHiltComponents,
-      genDaggerHiltApplicationComponent,
-      classSrcApp,
-      classSrcActivity1,
-      classSrcActivity2,
-      classSrcModule1,
-      classSrcModule2,
-      classGenHiltApp,
-      classGenHiltActivity1,
-      classGenHiltActivity2,
-      classGenAppInjector,
-      classGenActivityInjector1,
-      classGenActivityInjector2,
-      classGenAppInjectorDeps,
-      classGenActivityInjectorDeps1,
-      classGenActivityInjectorDeps2,
-      classGenModuleDeps1,
-      classGenModuleDeps2,
-      classGenHiltComponents,
-      classGenDaggerHiltApplicationComponent
-    )
-
-    fileToTimestampMap = mutableMapOf<File, Long>().apply {
-      for (file in files) {
-        this[file] = file.lastModified()
-      }
-    }
-  }
-
-  private fun recordFileChanges() {
-    changedFiles = fileToTimestampMap.filter { (file, previousTimestamp) ->
-      file.exists() && file.lastModified() != previousTimestamp
-    }.keys
-
-    unchangedFiles = fileToTimestampMap.filter { (file, previousTimestamp) ->
-      file.exists() && file.lastModified() == previousTimestamp
-    }.keys
-
-    deletedFiles = fileToTimestampMap.filter { (file, _) -> !file.exists() }.keys
-  }
-
-  private fun assertFilesExist(vararg files: File) {
-    expect.withMessage("Existing files")
-      .that(files.filter { it.exists() })
-      .containsExactlyElementsIn(files)
-  }
-
-  private fun assertChangedFiles(type: FileType, vararg files: File) {
-    expect.withMessage("Changed files")
-      .that(changedFiles.filter { it.name.endsWith(type.extension) })
-      .containsExactlyElementsIn(files)
-  }
-
-  private fun assertDeletedFiles(vararg files: File) {
-    expect.withMessage("Deleted files").that(deletedFiles).containsAtLeastElementsIn(files)
-  }
-
-  private fun searchAndReplace(file: File, search: String, replace: String) {
-    file.writeText(file.readText().replace(search, replace))
-  }
-
-  enum class FileType(val extension: String) {
-    JAVA(".java"),
-    CLASS(".class"),
-  }
-
-  companion object {
-    private const val SRC_DIR = "src/main/java"
-    private const val GEN_SRC_DIR = "build/generated/ap_generated_sources/debug/out/"
-    private const val CLASS_DIR = "build/intermediates/javac/debug/classes"
-
-    private const val CLEAN_TASK = ":clean"
-    private const val COMPILE_TASK = ":compileDebugJavaWithJavac"
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/kotlin/TransformTest.kt b/java/dagger/hilt/android/plugin/src/test/kotlin/TransformTest.kt
deleted file mode 100644
index 0b84002..0000000
--- a/java/dagger/hilt/android/plugin/src/test/kotlin/TransformTest.kt
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-import java.io.DataInputStream
-import java.io.FileInputStream
-import javassist.bytecode.ByteArray
-import javassist.bytecode.ClassFile
-import junit.framework.Assert.assertEquals
-import org.gradle.testkit.runner.TaskOutcome
-import org.junit.Assert
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TemporaryFolder
-
-class TransformTest {
-
-  @get:Rule
-  val testProjectDir = TemporaryFolder()
-
-  lateinit var gradleRunner: GradleTestRunner
-
-  @Before
-  fun setup() {
-    gradleRunner = GradleTestRunner(testProjectDir)
-    gradleRunner.addSrc(
-      srcPath = "minimal/MainActivity.java",
-      srcContent =
-        """
-        package minimal;
-
-        import android.os.Bundle;
-        import androidx.appcompat.app.AppCompatActivity;
-
-        @dagger.hilt.android.AndroidEntryPoint
-        public class MainActivity extends AppCompatActivity {
-          @Override
-          public void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-          }
-        }
-        """.trimIndent()
-    )
-  }
-
-  // Simple functional test to verify transformation.
-  @Test
-  fun testAssemble() {
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'",
-      "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'",
-      "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'"
-    )
-    gradleRunner.addActivities(
-      "<activity android:name=\".MainActivity\"/>"
-    )
-
-    val result = gradleRunner.build()
-    val assembleTask = result.getTask(":assembleDebug")
-    Assert.assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-
-    val transformedClass = result.getTransformedFile("minimal/MainActivity.class")
-    FileInputStream(transformedClass).use { fileInput ->
-      ClassFile(DataInputStream(fileInput)).let { classFile ->
-        // Verify superclass is updated
-        Assert.assertEquals("minimal.Hilt_MainActivity", classFile.superclass)
-        // Verify super call is also updated
-        val constPool = classFile.constPool
-        classFile.methods.first { it.name == "onCreate" }.let { methodInfo ->
-          // bytecode of MainActivity.onCreate() is:
-          // 0 - aload_0
-          // 1 - aload_1
-          // 2 - invokespecial
-          // 5 - return
-          val invokeIndex = 2
-          val methodRef = ByteArray.readU16bit(methodInfo.codeAttribute.code, invokeIndex + 1)
-          val classRef = constPool.getMethodrefClassName(methodRef)
-          Assert.assertEquals("minimal.Hilt_MainActivity", classRef)
-        }
-      }
-    }
-  }
-
-  // Verify correct transformation is done on nested classes.
-  @Test
-  fun testAssemble_nestedClass() {
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'",
-      "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'",
-      "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'"
-    )
-
-    gradleRunner.addSrc(
-      srcPath = "minimal/TopClass.java",
-      srcContent =
-        """
-        package minimal;
-
-        import androidx.appcompat.app.AppCompatActivity;
-
-        public class TopClass {
-            @dagger.hilt.android.AndroidEntryPoint
-            public static class NestedActivity extends AppCompatActivity { }
-        }
-        """.trimIndent()
-    )
-
-    val result = gradleRunner.build()
-    val assembleTask = result.getTask(":assembleDebug")
-    Assert.assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-
-    val transformedClass = result.getTransformedFile("minimal/TopClass\$NestedActivity.class")
-    FileInputStream(transformedClass).use { fileInput ->
-      ClassFile(DataInputStream(fileInput)).let { classFile ->
-        Assert.assertEquals("minimal.Hilt_TopClass_NestedActivity", classFile.superclass)
-      }
-    }
-  }
-
-  // Verify transformation ignores abstract methods.
-  @Test
-  fun testAssemble_abstractMethod() {
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'",
-      "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'",
-      "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'"
-    )
-
-    gradleRunner.addSrc(
-      srcPath = "minimal/AbstractActivity.java",
-      srcContent =
-        """
-        package minimal;
-
-        import androidx.appcompat.app.AppCompatActivity;
-
-        @dagger.hilt.android.AndroidEntryPoint
-        public abstract class AbstractActivity extends AppCompatActivity {
-            public abstract void method();
-        }
-        """.trimIndent()
-    )
-
-    val result = gradleRunner.build()
-    val assembleTask = result.getTask(":assembleDebug")
-    Assert.assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-
-    val transformedClass = result.getTransformedFile("minimal/AbstractActivity.class")
-    FileInputStream(transformedClass).use { fileInput ->
-      ClassFile(DataInputStream(fileInput)).let { classFile ->
-        Assert.assertEquals("minimal.Hilt_AbstractActivity", classFile.superclass)
-      }
-    }
-  }
-
-  // Verify transformation ignores native methods.
-  @Test
-  fun testAssemble_nativeMethod() {
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'",
-      "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'",
-      "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'"
-    )
-
-    gradleRunner.addSrc(
-      srcPath = "minimal/SimpleActivity.java",
-      srcContent =
-        """
-        package minimal;
-
-        import androidx.appcompat.app.AppCompatActivity;
-
-        @dagger.hilt.android.AndroidEntryPoint
-        public class SimpleActivity extends AppCompatActivity {
-            public native void method();
-        }
-        """.trimIndent()
-    )
-
-    val result = gradleRunner.build()
-    val assembleTask = result.getTask(":assembleDebug")
-    Assert.assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-
-    val transformedClass = result.getTransformedFile("minimal/SimpleActivity.class")
-    FileInputStream(transformedClass).use { fileInput ->
-      ClassFile(DataInputStream(fileInput)).let { classFile ->
-        Assert.assertEquals("minimal.Hilt_SimpleActivity", classFile.superclass)
-      }
-    }
-  }
-
-  // Verifies the transformation is applied incrementally when a class to be transformed is updated.
-  @Test
-  fun testTransform_incrementalClass() {
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'",
-      "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'",
-      "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'"
-    )
-
-    val srcFile = gradleRunner.addSrc(
-      srcPath = "minimal/OtherActivity.java",
-      srcContent =
-        """
-        package minimal;
-
-        import androidx.appcompat.app.AppCompatActivity;
-
-        @dagger.hilt.android.AndroidEntryPoint
-        public class OtherActivity extends AppCompatActivity {
-
-        }
-        """.trimIndent()
-    )
-
-    gradleRunner.build().let {
-      val assembleTask = it.getTask(TRANSFORM_TASK_NAME)
-      Assert.assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-    }
-
-    gradleRunner.build().let {
-      val assembleTask = it.getTask(TRANSFORM_TASK_NAME)
-      Assert.assertEquals(TaskOutcome.UP_TO_DATE, assembleTask.outcome)
-    }
-
-    srcFile.delete()
-    gradleRunner.addSrc(
-      srcPath = "minimal/OtherActivity.java",
-      srcContent =
-        """
-        package minimal;
-
-        import androidx.fragment.app.FragmentActivity;
-
-        @dagger.hilt.android.AndroidEntryPoint
-        public class OtherActivity extends FragmentActivity {
-
-        }
-        """.trimIndent()
-    )
-
-    val result = gradleRunner.build()
-    val assembleTask = result.getTask(TRANSFORM_TASK_NAME)
-    Assert.assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-
-    val transformedClass = result.getTransformedFile("minimal/OtherActivity.class")
-    FileInputStream(transformedClass).use { fileInput ->
-      ClassFile(DataInputStream(fileInput)).let { classFile ->
-        Assert.assertEquals("minimal.Hilt_OtherActivity", classFile.superclass)
-      }
-    }
-  }
-
-  // Verifies the transformation is applied incrementally when a new class is added to an existing
-  // directory.
-  @Test
-  fun testTransform_incrementalDir() {
-    gradleRunner.addDependencies(
-      "implementation 'androidx.appcompat:appcompat:1.1.0'",
-      "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'",
-      "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'"
-    )
-
-    gradleRunner.addSrcPackage("ui/")
-
-    gradleRunner.build().let {
-      val assembleTask = it.getTask(TRANSFORM_TASK_NAME)
-      assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-    }
-
-    gradleRunner.build().let {
-      val assembleTask = it.getTask(TRANSFORM_TASK_NAME)
-      assertEquals(TaskOutcome.UP_TO_DATE, assembleTask.outcome)
-    }
-
-    gradleRunner.addSrc(
-      srcPath = "ui/OtherActivity.java",
-      srcContent =
-        """
-        package ui;
-
-        import androidx.appcompat.app.AppCompatActivity;
-
-        @dagger.hilt.android.AndroidEntryPoint
-        public class OtherActivity extends AppCompatActivity {
-
-        }
-        """.trimIndent()
-    )
-
-    val result = gradleRunner.build()
-    val assembleTask = result.getTask(TRANSFORM_TASK_NAME)
-    assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome)
-  }
-
-  companion object {
-    const val TRANSFORM_TASK_NAME =
-      ":transformDebugClassesWithAsm"
-  }
-}
diff --git a/java/dagger/hilt/android/plugin/src/test/kotlin/util/SimpleAGPVersionTest.kt b/java/dagger/hilt/android/plugin/src/test/kotlin/util/SimpleAGPVersionTest.kt
deleted file mode 100644
index 75292b8..0000000
--- a/java/dagger/hilt/android/plugin/src/test/kotlin/util/SimpleAGPVersionTest.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package util
-
-import com.google.common.truth.Truth.assertThat
-import dagger.hilt.android.plugin.util.SimpleAGPVersion
-import org.junit.Test
-
-class SimpleAGPVersionTest {
-
-  @Test
-  fun parsing() {
-    assertThat(SimpleAGPVersion.parse("4.2"))
-      .isEqualTo(SimpleAGPVersion(4, 2))
-    assertThat(SimpleAGPVersion.parse("4.2.1"))
-      .isEqualTo(SimpleAGPVersion(4, 2))
-    assertThat(SimpleAGPVersion.parse("7.0.0-alpha01"))
-      .isEqualTo(SimpleAGPVersion(7, 0))
-  }
-
-  @Test
-  fun comparing() {
-    assertThat(SimpleAGPVersion(4, 2))
-      .isEqualTo(SimpleAGPVersion(4, 2))
-    assertThat(SimpleAGPVersion(4, 2))
-      .isGreaterThan(SimpleAGPVersion(3, 4))
-    assertThat(SimpleAGPVersion(4, 2))
-      .isLessThan(SimpleAGPVersion(7, 0))
-
-    assertThat(SimpleAGPVersion.parse("4.2.1"))
-      .isEqualTo(SimpleAGPVersion.parse("4.2.2"))
-    assertThat(SimpleAGPVersion.parse("4.2.1"))
-      .isGreaterThan(SimpleAGPVersion.parse("3.4.1"))
-    assertThat(SimpleAGPVersion.parse("4.2.1"))
-      .isLessThan(SimpleAGPVersion.parse("7.0.1"))
-
-    assertThat(SimpleAGPVersion.parse("4.2.1"))
-      .isLessThan(SimpleAGPVersion.parse("7.0.0-alpha01"))
-    assertThat(SimpleAGPVersion.parse("7.0.0-alpha01"))
-      .isEqualTo(SimpleAGPVersion.parse("7.0.0-alpha02"))
-  }
-}
diff --git a/java/dagger/hilt/android/processor/BUILD b/java/dagger/hilt/android/processor/BUILD
deleted file mode 100644
index e116c44..0000000
--- a/java/dagger/hilt/android/processor/BUILD
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Hilt android processors.
-
-load("//:build_defs.bzl", "POM_VERSION_ALPHA")
-load("//tools:maven.bzl", "gen_maven_artifact")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "artifact-lib",
-    tags = ["maven_coordinates=com.google.dagger:hilt-android-compiler:" + POM_VERSION_ALPHA],
-    visibility = ["//visibility:private"],
-    exports = [
-        "//java/dagger/hilt/processor:artifact-lib-shared",
-    ],
-)
-
-gen_maven_artifact(
-    name = "artifact",
-    artifact_coordinates = "com.google.dagger:hilt-android-compiler:" + POM_VERSION_ALPHA,
-    artifact_name = "Hilt Android Processor",
-    artifact_target = ":artifact-lib",
-    artifact_target_libs = [
-        "//java/dagger/hilt/android/processor/internal:android_classnames",
-        "//java/dagger/hilt/android/processor/internal:utils",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:android_generators",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:compiler_options",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:metadata",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/bindvalue:bind_value_processor_lib",
-        "//java/dagger/hilt/android/processor/internal/customtestapplication:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:validation_plugin_lib",
-        "//java/dagger/hilt/android/processor/internal/uninstallmodules:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:component_descriptor",
-        "//java/dagger/hilt/processor/internal:component_names",
-        "//java/dagger/hilt/processor/internal:components",
-        "//java/dagger/hilt/processor/internal:kotlin",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:component_dependencies",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:processor_lib",
-        "//java/dagger/hilt/processor/internal/aliasof:alias_ofs",
-        "//java/dagger/hilt/processor/internal/aliasof:processor_lib",
-        "//java/dagger/hilt/processor/internal/definecomponent:define_components",
-        "//java/dagger/hilt/processor/internal/definecomponent:processor_lib",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:generates_root_inputs",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:processor_lib",
-        "//java/dagger/hilt/processor/internal/originatingelement:processor_lib",
-        "//java/dagger/hilt/processor/internal/root:processor_lib",
-        "//java/dagger/hilt/processor/internal/root:root_metadata",
-        "//java/dagger/hilt/processor/internal/root:root_type",
-    ],
-    artifact_target_maven_deps = [
-        "com.google.auto:auto-common",
-        "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger-compiler",
-        "com.google.dagger:dagger",
-        "com.google.dagger:dagger-spi",
-        "com.google.guava:failureaccess",
-        "com.google.guava:guava",
-        "com.squareup:javapoet",
-        "javax.annotation:jsr250-api",
-        "javax.inject:javax.inject",
-        "net.ltgt.gradle.incap:incap",
-        "org.jetbrains.kotlin:kotlin-stdlib",
-        "org.jetbrains.kotlinx:kotlinx-metadata-jvm",
-    ],
-    javadoc_android_api_level = 30,
-    javadoc_root_packages = [
-        "dagger.hilt.processor",
-        "dagger.hilt.android.processor",
-    ],
-    javadoc_srcs = [
-        "//java/dagger/hilt:hilt_processing_filegroup",
-    ],
-    shaded_deps = ["@maven//:com_google_auto_auto_common"],
-    shaded_rules = ["rule com.google.auto.common.** dagger.hilt.android.shaded.auto.common.@1"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/processor/internal/AndroidClassNames.java b/java/dagger/hilt/android/processor/internal/AndroidClassNames.java
deleted file mode 100644
index 915ae51..0000000
--- a/java/dagger/hilt/android/processor/internal/AndroidClassNames.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal;
-
-import static com.squareup.javapoet.ClassName.get;
-
-import com.squareup.javapoet.ClassName;
-
-/** Holder for commonly used class names. */
-public final class AndroidClassNames {
-
-  public static final ClassName APPLICATION_PROVIDER =
-      get("androidx.test.core.app", "ApplicationProvider");
-  public static final ClassName ACTIVITY = get("android.app", "Activity");
-  public static final ClassName COMPONENT_ACTIVITY = get("androidx.activity", "ComponentActivity");
-  public static final ClassName APPLICATION = get("android.app", "Application");
-  public static final ClassName BROADCAST_RECEIVER = get("android.content", "BroadcastReceiver");
-  public static final ClassName SERVICE = get("android.app", "Service");
-  public static final ClassName FRAGMENT =
-      get("androidx.fragment.app", "Fragment");
-  public static final ClassName VIEW = get("android.view", "View");
-
-  public static final ClassName NULLABLE_INTERNAL = get("android.annotation", "Nullable");
-  public static final ClassName TARGET_API = get("android.annotation", "TargetApi");
-
-  public static final ClassName CONTEXT = get("android.content", "Context");
-  public static final ClassName CONTEXT_WRAPPER = get("android.content", "ContextWrapper");
-  public static final ClassName INTENT = get("android.content", "Intent");
-
-  public static final ClassName BUNDLE = get("android.os", "Bundle");
-
-  public static final ClassName CALL_SUPER = get("androidx.annotation", "CallSuper");
-  public static final ClassName MAIN_THREAD = get("androidx.annotation", "MainThread");
-  public static final ClassName NULLABLE = get("androidx.annotation", "Nullable");
-  public static final ClassName MULTI_DEX_APPLICATION =
-      get("androidx.multidex", "MultiDexApplication");
-
-  public static final ClassName ATTRIBUTE_SET = get("android.util", "AttributeSet");
-  public static final ClassName LAYOUT_INFLATER = get("android.view", "LayoutInflater");
-
-  public static final ClassName ANDROID_ENTRY_POINT =
-      get("dagger.hilt.android", "AndroidEntryPoint");
-  public static final ClassName WITH_FRAGMENT_BINDINGS =
-      get("dagger.hilt.android", "WithFragmentBindings");
-  public static final ClassName HILT_ANDROID_APP =
-      get("dagger.hilt.android", "HiltAndroidApp");
-  public static final ClassName OPTIONAL_INJECT =
-      get("dagger.hilt.android.migration", "OptionalInject");
-
-  public static final ClassName SINGLETON_COMPONENT =
-      get("dagger.hilt.components", "SingletonComponent");
-  public static final ClassName ACTIVITY_COMPONENT =
-      get("dagger.hilt.android.components", "ActivityComponent");
-  public static final ClassName ACTIVITY_RETAINED_COMPONENT =
-      get("dagger.hilt.android.components", "ActivityRetainedComponent");
-  public static final ClassName FRAGMENT_COMPONENT =
-      get("dagger.hilt.android.components", "FragmentComponent");
-  public static final ClassName VIEW_WITH_FRAGMENT_COMPONENT =
-      get("dagger.hilt.android.components", "ViewWithFragmentComponent");
-  public static final ClassName VIEW_COMPONENT =
-      get("dagger.hilt.android.components", "ViewComponent");
-  public static final ClassName SERVICE_COMPONENT =
-      get("dagger.hilt.android.components", "ServiceComponent");
-  public static final ClassName VIEW_MODEL_COMPONENT =
-      get("dagger.hilt.android.components", "ViewModelComponent");
-
-  public static final ClassName ACTIVITY_COMPONENT_MANAGER =
-      get("dagger.hilt.android.internal.managers", "ActivityComponentManager");
-  public static final ClassName APPLICATION_COMPONENT_MANAGER =
-      get("dagger.hilt.android.internal.managers", "ApplicationComponentManager");
-  public static final ClassName BROADCAST_RECEIVER_COMPONENT_MANAGER =
-      get("dagger.hilt.android.internal.managers", "BroadcastReceiverComponentManager");
-  public static final ClassName COMPONENT_SUPPLIER =
-      get("dagger.hilt.android.internal.managers", "ComponentSupplier");
-  public static final ClassName FRAGMENT_COMPONENT_MANAGER =
-      get("dagger.hilt.android.internal.managers", "FragmentComponentManager");
-  public static final ClassName SERVICE_COMPONENT_MANAGER =
-      get("dagger.hilt.android.internal.managers", "ServiceComponentManager");
-  public static final ClassName VIEW_COMPONENT_MANAGER =
-      get("dagger.hilt.android.internal.managers", "ViewComponentManager");
-
-  public static final ClassName INJECTED_BY_HILT =
-      get("dagger.hilt.android.internal.migration", "InjectedByHilt");
-
-  public static final ClassName APPLICATION_CONTEXT_MODULE =
-      get("dagger.hilt.android.internal.modules", "ApplicationContextModule");
-
-  public static final ClassName DEFAULT_VIEW_MODEL_FACTORIES =
-      get("dagger.hilt.android.internal.lifecycle", "DefaultViewModelFactories");
-  public static final ClassName HILT_VIEW_MODEL =
-      get("dagger.hilt.android.lifecycle", "HiltViewModel");
-  public static final ClassName HILT_VIEW_MODEL_MAP_QUALIFIER =
-      get("dagger.hilt.android.internal.lifecycle", "HiltViewModelMap");
-  public static final ClassName HILT_VIEW_MODEL_KEYS_QUALIFIER =
-      get("dagger.hilt.android.internal.lifecycle", "HiltViewModelMap", "KeySet");
-  public static final ClassName VIEW_MODEL = get("androidx.lifecycle", "ViewModel");
-  public static final ClassName VIEW_MODEL_PROVIDER_FACTORY =
-      get("androidx.lifecycle", "ViewModelProvider", "Factory");
-  public static final ClassName SAVED_STATE_HANDLE =
-      get("androidx.lifecycle", "SavedStateHandle");
-
-  private AndroidClassNames() {}
-}
diff --git a/java/dagger/hilt/android/processor/internal/BUILD b/java/dagger/hilt/android/processor/internal/BUILD
deleted file mode 100644
index aaf8b89..0000000
--- a/java/dagger/hilt/android/processor/internal/BUILD
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Internal code for implementing Hilt android processors.
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "android_classnames",
-    srcs = [
-        "AndroidClassNames.java",
-    ],
-    deps = [
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-# TODO(erichang): Merge this into other utils
-java_library(
-    name = "utils",
-    srcs = [
-        "MoreTypes.java",
-    ],
-    deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["**/*"]),
-)
diff --git a/java/dagger/hilt/android/processor/internal/MoreTypes.java b/java/dagger/hilt/android/processor/internal/MoreTypes.java
deleted file mode 100644
index e5a2cdd..0000000
--- a/java/dagger/hilt/android/processor/internal/MoreTypes.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ErrorType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.SimpleTypeVisitor7;
-import javax.lang.model.util.Types;
-
-/** More utility methods for types. */
-public final class MoreTypes {
-  private MoreTypes() {}
-
-  /**
-   * If the received mirror represents a declared type or an array of declared types, this returns
-   * the represented declared type. Otherwise throws an IllegalStateException.
-   */
-  public static DeclaredType getDeclaredType(TypeMirror type) {
-    return type.accept(
-        new SimpleTypeVisitor7<DeclaredType, Void>() {
-          @Override public DeclaredType visitArray(ArrayType type, Void unused) {
-            return getDeclaredType(type.getComponentType());
-          }
-
-          @Override public DeclaredType visitDeclared(DeclaredType type, Void unused) {
-            return type;
-          }
-
-          @Override public DeclaredType visitError(ErrorType type, Void unused) {
-            return type;
-          }
-
-          @Override public DeclaredType defaultAction(TypeMirror type, Void unused) {
-            throw new IllegalStateException("Unhandled type: " + type);
-          }
-        }, null /* the Void accumulator */);
-  }
-
-  /** Returns the TypeElement corresponding to a TypeMirror. */
-  public static TypeElement asTypeElement(TypeMirror type) {
-    return asTypeElement(getDeclaredType(type));
-  }
-
-  /** Returns the TypeElement corresponding to a DeclaredType. */
-  public static TypeElement asTypeElement(DeclaredType type) {
-    return (TypeElement) type.asElement();
-  }
-
-  /**
-   * Returns a {@link ExecutableType} if the {@link TypeMirror} represents an executable type such
-   * as a method, constructor, or initializer or throws an {@link IllegalArgumentException}.
-   */
-  public static ExecutableType asExecutable(TypeMirror maybeExecutableType) {
-    return maybeExecutableType.accept(ExecutableTypeVisitor.INSTANCE, null);
-  }
-
-  private static final class ExecutableTypeVisitor extends CastingTypeVisitor<ExecutableType> {
-    private static final ExecutableTypeVisitor INSTANCE = new ExecutableTypeVisitor();
-
-    ExecutableTypeVisitor() {
-      super("executable type");
-    }
-
-    @Override
-    public ExecutableType visitExecutable(ExecutableType type, Void ignore) {
-      return type;
-    }
-  }
-
-  private abstract static class CastingTypeVisitor<T> extends SimpleTypeVisitor7<T, Void> {
-    private final String label;
-
-    CastingTypeVisitor(String label) {
-      this.label = label;
-    }
-
-    @Override
-    protected T defaultAction(TypeMirror e, Void v) {
-      throw new IllegalArgumentException(e + " does not represent a " + label);
-    }
-  }
-
-  /**
-   * Returns the first matching method, if one exists (starting with classElement, then searching
-   * each sub classes).
-   */
-  public static Optional<ExecutableElement> findInheritedMethod(
-      Types types, TypeElement classElement, ExecutableElement method) {
-    Optional<ExecutableElement> match = Optional.empty();
-    while (!match.isPresent() && !classElement.asType().getKind().equals(TypeKind.NONE)) {
-      match = findMethod(types, classElement, method);
-      classElement = MoreTypes.asTypeElement(classElement.getSuperclass());
-    }
-    return match;
-  }
-
-  /** Returns a method with a matching signature in classElement if one exists. */
-  public static Optional<ExecutableElement> findMethod(
-      Types types, TypeElement classElement, ExecutableElement method) {
-    ExecutableType methodType = asExecutable(method.asType());
-    Set<ExecutableElement> matchingMethods =
-        findMethods(classElement, method.getSimpleName().toString())
-            .stream()
-            .filter(clsMethod -> types.isSubsignature(asExecutable(clsMethod.asType()), methodType))
-            .collect(Collectors.toSet());
-
-    Preconditions.checkState(
-        matchingMethods.size() <= 1,
-        "Found multiple methods with matching signature in class %s: %s",
-        classElement,
-        matchingMethods);
-
-    return matchingMethods.size() == 1
-        ? Optional.of(Iterables.getOnlyElement(matchingMethods))
-        : Optional.empty();
-  }
-
-  /** Returns methods with a matching name in classElement. */
-  public static Set<ExecutableElement> findMethods(TypeElement classElement, String name) {
-    return ElementFilter.methodsIn(classElement.getEnclosedElements())
-        .stream()
-        .filter(clsMethod -> clsMethod.getSimpleName().contentEquals(name))
-        .collect(Collectors.toSet());
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java
deleted file mode 100644
index ce9ad14..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/** Generates an Hilt Activity class for the @AndroidEntryPoint annotated class. */
-public final class ActivityGenerator {
-
-  private final ProcessingEnvironment env;
-  private final AndroidEntryPointMetadata metadata;
-  private final ClassName generatedClassName;
-
-  public ActivityGenerator(ProcessingEnvironment env, AndroidEntryPointMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-
-    generatedClassName = metadata.generatedClassName();
-  }
-
-  // @Generated("ActivityGenerator")
-  // abstract class Hilt_$CLASS extends $BASE implements ComponentManager<?> {
-  //   ...
-  // }
-  public void generate() throws IOException {
-    TypeSpec.Builder builder =
-        TypeSpec.classBuilder(generatedClassName.simpleName())
-            .addOriginatingElement(metadata.element())
-            .superclass(metadata.baseClassName())
-            .addModifiers(metadata.generatedClassModifiers());
-
-    Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT);
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-
-      Generators.copyConstructors(metadata.baseElement(), builder);
-      builder.addMethod(onCreate());
-
-
-    metadata.baseElement().getTypeParameters().stream()
-        .map(TypeVariableName::get)
-        .forEachOrdered(builder::addTypeVariable);
-
-    Generators.addComponentOverride(metadata, builder);
-    Generators.copyLintAnnotations(metadata.element(), builder);
-
-    Generators.addInjectionMethods(metadata, builder);
-
-    if (Processors.isAssignableFrom(metadata.baseElement(), AndroidClassNames.COMPONENT_ACTIVITY)
-        && !metadata.overridesAndroidEntryPointClass()) {
-      builder.addMethod(getDefaultViewModelProviderFactory());
-    }
-
-    JavaFile.builder(generatedClassName.packageName(), builder.build())
-        .build()
-        .writeTo(env.getFiler());
-  }
-
-  // @CallSuper
-  // @Override
-  // protected void onCreate(@Nullable Bundle savedInstanceState) {
-  //   inject();
-  //   super.onCreate(savedInstanceState);
-  // }
-  private MethodSpec onCreate() {
-    return MethodSpec.methodBuilder("onCreate")
-        .addAnnotation(AndroidClassNames.CALL_SUPER)
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PROTECTED)
-        .addParameter(
-            ParameterSpec.builder(AndroidClassNames.BUNDLE, "savedInstanceState")
-                .addAnnotation(AndroidClassNames.NULLABLE)
-                .build())
-        .addStatement("inject()")
-        .addStatement("super.onCreate(savedInstanceState)")
-        .build();
-  }
-
-  // @Override
-  // public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
-  //   return DefaultViewModelFactories.getActivityFactory(this);
-  // }
-  private MethodSpec getDefaultViewModelProviderFactory() {
-    return MethodSpec.methodBuilder("getDefaultViewModelProviderFactory")
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC)
-        .returns(AndroidClassNames.VIEW_MODEL_PROVIDER_FACTORY)
-        .addStatement(
-            "return $T.getActivityFactory(this)",
-            AndroidClassNames.DEFAULT_VIEW_MODEL_FACTORIES)
-        .build();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java
deleted file mode 100644
index e5868f8..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-import static dagger.hilt.android.processor.internal.androidentrypoint.HiltCompilerOptions.BooleanOption.DISABLE_ANDROID_SUPERCLASS_VALIDATION;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.processor.internal.BadInputException;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Components;
-import dagger.hilt.processor.internal.KotlinMetadataUtils;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import java.util.LinkedHashSet;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-
-/** Metadata class for @AndroidEntryPoint annotated classes. */
-@AutoValue
-public abstract class AndroidEntryPointMetadata {
-
-  /** The class {@link Element} annotated with @AndroidEntryPoint. */
-  public abstract TypeElement element();
-
-  /** The base class {@link Element} given to @AndroidEntryPoint. */
-  public abstract TypeElement baseElement();
-
-  /** The name of the generated base class, beginning with 'Hilt_'. */
-  public abstract ClassName generatedClassName();
-
-  /** Returns {@code true} if the class requires bytecode injection to replace the base class. */
-  public abstract boolean requiresBytecodeInjection();
-
-  /** Returns the {@link AndroidType} for the annotated element. */
-  public abstract AndroidType androidType();
-
-  /** Returns {@link Optional} of {@link AndroidEntryPointMetadata}. */
-  public abstract Optional<AndroidEntryPointMetadata> baseMetadata();
-
-  /** Returns set of scopes that the component interface should be installed in. */
-  public abstract ImmutableSet<ClassName> installInComponents();
-
-  /** Returns the component manager this generated Hilt class should use. */
-  public abstract TypeName componentManager();
-
-  /** Returns the initialization arguments for the component manager. */
-  public abstract Optional<CodeBlock> componentManagerInitArgs();
-
-  /**
-   * Returns the metadata for the root most class in the hierarchy.
-   *
-   * <p>If this is the only metadata in the class hierarchy, it returns this.
-   */
-  @Memoized
-  public AndroidEntryPointMetadata rootMetadata() {
-    return baseMetadata().map(AndroidEntryPointMetadata::rootMetadata).orElse(this);
-  }
-
-  boolean isRootMetadata() {
-    return this.equals(rootMetadata());
-  }
-
-  /** Returns true if this class allows optional injection. */
-  public boolean allowsOptionalInjection() {
-    return Processors.hasAnnotation(element(), AndroidClassNames.OPTIONAL_INJECT);
-  }
-
-  /** Returns true if any base class (transitively) allows optional injection. */
-  public boolean baseAllowsOptionalInjection() {
-    return baseMetadata().isPresent() && baseMetadata().get().allowsOptionalInjection();
-  }
-
-  /** Returns true if any base class (transitively) uses @AndroidEntryPoint. */
-  public boolean overridesAndroidEntryPointClass() {
-    return baseMetadata().isPresent();
-  }
-
-  /** The name of the class annotated with @AndroidEntryPoint */
-  public ClassName elementClassName() {
-    return ClassName.get(element());
-  }
-
-  /** The name of the base class given to @AndroidEntryPoint */
-  public TypeName baseClassName() {
-    return TypeName.get(baseElement().asType());
-  }
-
-  /** The name of the generated injector for the Hilt class. */
-  public ClassName injectorClassName() {
-    return Processors.append(
-        Processors.getEnclosedClassName(elementClassName()), "_GeneratedInjector");
-  }
-
-  /**
-   * The name of inject method for this class. The format is: inject$CLASS. If the class is nested,
-   * will return the full name deliminated with '_'. e.g. Foo.Bar.Baz -> injectFoo_Bar_Baz
-   */
-  public String injectMethodName() {
-    return "inject" + Processors.getEnclosedName(elementClassName());
-  }
-
-  /** Returns the @InstallIn annotation for the module providing this class. */
-  public final AnnotationSpec injectorInstallInAnnotation() {
-    return Components.getInstallInAnnotationSpec(installInComponents());
-  }
-
-  public ParameterSpec componentManagerParam() {
-    return ParameterSpec.builder(componentManager(), "componentManager").build();
-  }
-
-  /**
-   * Modifiers that should be applied to the generated class.
-   *
-   * <p>Note that the generated class must have public visibility if used by a
-   * public @AndroidEntryPoint-annotated kotlin class. See:
-   * https://discuss.kotlinlang.org/t/why-does-kotlin-prohibit-exposing-restricted-visibility-types/7047
-   */
-  public Modifier[] generatedClassModifiers() {
-    return isKotlinClass(element()) && element().getModifiers().contains(Modifier.PUBLIC)
-        ? new Modifier[] {Modifier.ABSTRACT, Modifier.PUBLIC}
-        : new Modifier[] {Modifier.ABSTRACT};
-  }
-
-  private static ClassName generatedClassName(TypeElement element) {
-    String prefix = "Hilt_";
-    return Processors.prepend(Processors.getEnclosedClassName(ClassName.get(element)), prefix);
-  }
-
-  private static final ImmutableSet<ClassName> HILT_ANNOTATION_NAMES =
-      ImmutableSet.of(
-          AndroidClassNames.HILT_ANDROID_APP,
-          AndroidClassNames.ANDROID_ENTRY_POINT);
-
-  private static ImmutableSet<? extends AnnotationMirror> hiltAnnotations(Element element) {
-    return element.getAnnotationMirrors().stream()
-        .filter(mirror -> HILT_ANNOTATION_NAMES.contains(ClassName.get(mirror.getAnnotationType())))
-        .collect(toImmutableSet());
-  }
-
-  /** Returns true if the given element has Android Entry Point metadata. */
-  public static boolean hasAndroidEntryPointMetadata(Element element) {
-    return !hiltAnnotations(element).isEmpty();
-  }
-
-  /** Returns the {@link AndroidEntryPointMetadata} for a @AndroidEntryPoint annotated element. */
-  public static AndroidEntryPointMetadata of(ProcessingEnvironment env, Element element) {
-    LinkedHashSet<Element> inheritanceTrace = new LinkedHashSet<>();
-    inheritanceTrace.add(element);
-    return of(env, element, inheritanceTrace);
-  }
-
-  public static AndroidEntryPointMetadata manuallyConstruct(
-      TypeElement element,
-      TypeElement baseElement,
-      ClassName generatedClassName,
-      boolean requiresBytecodeInjection,
-      AndroidType androidType,
-      Optional<AndroidEntryPointMetadata> baseMetadata,
-      ImmutableSet<ClassName> installInComponents,
-      TypeName componentManager,
-      Optional<CodeBlock> componentManagerInitArgs) {
-    return new AutoValue_AndroidEntryPointMetadata(
-        element,
-        baseElement,
-        generatedClassName,
-        requiresBytecodeInjection,
-        androidType,
-        baseMetadata,
-        installInComponents,
-        componentManager,
-        componentManagerInitArgs);
-  }
-
-  /**
-   * Internal implementation for "of" method, checking inheritance cycle utilizing inheritanceTrace
-   * along the way.
-   */
-  private static AndroidEntryPointMetadata of(
-      ProcessingEnvironment env, Element element, LinkedHashSet<Element> inheritanceTrace) {
-    ImmutableSet<? extends AnnotationMirror> hiltAnnotations = hiltAnnotations(element);
-    ProcessorErrors.checkState(
-        hiltAnnotations.size() == 1,
-        element,
-        "Expected exactly 1 of %s. Found: %s",
-        HILT_ANNOTATION_NAMES,
-        hiltAnnotations);
-    ClassName annotationClassName =
-        ClassName.get(
-            MoreTypes.asTypeElement(Iterables.getOnlyElement(hiltAnnotations).getAnnotationType()));
-
-    ProcessorErrors.checkState(
-        element.getKind() == ElementKind.CLASS,
-        element,
-        "Only classes can be annotated with @%s",
-        annotationClassName.simpleName());
-    TypeElement androidEntryPointElement = MoreElements.asType(element);
-
-    ProcessorErrors.checkState(
-        androidEntryPointElement.getTypeParameters().isEmpty(),
-        element,
-        "@%s-annotated classes cannot have type parameters.",
-        annotationClassName.simpleName());
-
-    final TypeElement androidEntryPointClassValue =
-        Processors.getAnnotationClassValue(
-            env.getElementUtils(),
-            Processors.getAnnotationMirror(androidEntryPointElement, annotationClassName),
-            "value");
-    final TypeElement baseElement;
-    final ClassName generatedClassName;
-    boolean requiresBytecodeInjection =
-        DISABLE_ANDROID_SUPERCLASS_VALIDATION.get(env)
-            && MoreTypes.isTypeOf(Void.class, androidEntryPointClassValue.asType());
-    if (requiresBytecodeInjection) {
-      baseElement = MoreElements.asType(env.getTypeUtils().asElement(androidEntryPointElement.getSuperclass()));
-      // If this AndroidEntryPoint is a Kotlin class and its base type is also Kotlin and has
-      // default values declared in its constructor then error out because for the short-form
-      // usage of @AndroidEntryPoint the bytecode transformation will be done incorrectly.
-      KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
-      ProcessorErrors.checkState(
-          !metadataUtil.hasMetadata(androidEntryPointElement)
-              || !metadataUtil.containsConstructorWithDefaultParam(baseElement),
-          baseElement,
-          "The base class, '%s', of the @AndroidEntryPoint, '%s', contains a constructor with "
-              + "default parameters. This is currently not supported by the Gradle plugin. Either "
-              + "specify the base class as described at "
-              + "https://dagger.dev/hilt/gradle-setup#why-use-the-plugin or remove the default value "
-              + "declaration.",
-          baseElement.getQualifiedName(),
-          androidEntryPointElement.getQualifiedName());
-      generatedClassName = generatedClassName(androidEntryPointElement);
-    } else {
-      baseElement = androidEntryPointClassValue;
-      ProcessorErrors.checkState(
-          !MoreTypes.isTypeOf(Void.class, baseElement.asType()),
-          androidEntryPointElement,
-          "Expected @%s to have a value."
-          + " Did you forget to apply the Gradle Plugin? (dagger.hilt.android.plugin)\n"
-          + "See https://dagger.dev/hilt/gradle-setup.html" ,
-          annotationClassName.simpleName());
-
-      // Check that the root $CLASS extends Hilt_$CLASS
-      String extendsName =
-          env.getTypeUtils()
-              .asElement(androidEntryPointElement.getSuperclass())
-              .getSimpleName()
-              .toString();
-      generatedClassName = generatedClassName(androidEntryPointElement);
-      ProcessorErrors.checkState(
-          extendsName.contentEquals(generatedClassName.simpleName()),
-          androidEntryPointElement,
-          "@%s class expected to extend %s. Found: %s",
-          annotationClassName.simpleName(),
-          generatedClassName.simpleName(),
-          extendsName);
-    }
-
-    Optional<AndroidEntryPointMetadata> baseMetadata =
-        baseMetadata(env, androidEntryPointElement, baseElement, inheritanceTrace);
-
-    if (baseMetadata.isPresent()) {
-      return manuallyConstruct(
-          androidEntryPointElement,
-          baseElement,
-          generatedClassName,
-          requiresBytecodeInjection,
-          baseMetadata.get().androidType(),
-          baseMetadata,
-          baseMetadata.get().installInComponents(),
-          baseMetadata.get().componentManager(),
-          baseMetadata.get().componentManagerInitArgs());
-    } else {
-      Type type = Type.of(androidEntryPointElement, baseElement);
-      return manuallyConstruct(
-          androidEntryPointElement,
-          baseElement,
-          generatedClassName,
-          requiresBytecodeInjection,
-          type.androidType,
-          Optional.empty(),
-          ImmutableSet.of(type.component),
-          type.manager,
-          Optional.ofNullable(type.componentManagerInitArgs));
-    }
-  }
-
-  private static Optional<AndroidEntryPointMetadata> baseMetadata(
-      ProcessingEnvironment env,
-      TypeElement element,
-      TypeElement baseElement,
-      LinkedHashSet<Element> inheritanceTrace) {
-    ProcessorErrors.checkState(
-        inheritanceTrace.add(baseElement),
-        element,
-        cyclicInheritanceErrorMessage(inheritanceTrace, baseElement));
-    if (hasAndroidEntryPointMetadata(baseElement)) {
-      AndroidEntryPointMetadata baseMetadata =
-          AndroidEntryPointMetadata.of(env, baseElement, inheritanceTrace);
-      checkConsistentAnnotations(element, baseMetadata);
-      return Optional.of(baseMetadata);
-    }
-
-    TypeMirror superClass = baseElement.getSuperclass();
-    // None type is returned if this is an interface or Object
-    if (superClass.getKind() != TypeKind.NONE && superClass.getKind() != TypeKind.ERROR) {
-      Preconditions.checkState(superClass.getKind() == TypeKind.DECLARED);
-      return baseMetadata(env, element, MoreTypes.asTypeElement(superClass), inheritanceTrace);
-    }
-
-    return Optional.empty();
-  }
-
-  private static String cyclicInheritanceErrorMessage(
-      LinkedHashSet<Element> inheritanceTrace, TypeElement cycleEntryPoint) {
-    return String.format(
-        "Cyclic inheritance detected. Make sure the base class of @AndroidEntryPoint "
-            + "is not the annotated class itself or subclass of the annotated class.\n"
-            + "The cyclic inheritance structure: %s --> %s\n",
-        inheritanceTrace.stream()
-            .map(Element::asType)
-            .map(TypeMirror::toString)
-            .collect(Collectors.joining(" --> ")),
-        cycleEntryPoint.asType());
-  }
-
-  private static boolean isKotlinClass(TypeElement typeElement) {
-    return typeElement.getAnnotationMirrors().stream()
-        .map(mirror -> mirror.getAnnotationType())
-        .anyMatch(type -> ClassName.get(type).equals(ClassNames.KOTLIN_METADATA));
-  }
-
-  /**
-   * The Android type of the Android Entry Point element. Component splits (like with fragment
-   * bindings) are coalesced.
-   */
-  public enum AndroidType {
-    APPLICATION,
-    ACTIVITY,
-    BROADCAST_RECEIVER,
-    FRAGMENT,
-    SERVICE,
-    VIEW
-  }
-
-  /** The type of Android Entry Point element. This includes splits for different components. */
-  private static final class Type {
-    private static final Type APPLICATION =
-        new Type(
-            AndroidClassNames.SINGLETON_COMPONENT,
-            AndroidType.APPLICATION,
-            AndroidClassNames.APPLICATION_COMPONENT_MANAGER,
-            null);
-    private static final Type SERVICE =
-        new Type(
-            AndroidClassNames.SERVICE_COMPONENT,
-            AndroidType.SERVICE,
-            AndroidClassNames.SERVICE_COMPONENT_MANAGER,
-            CodeBlock.of("this"));
-    private static final Type BROADCAST_RECEIVER =
-        new Type(
-            AndroidClassNames.SINGLETON_COMPONENT,
-            AndroidType.BROADCAST_RECEIVER,
-            AndroidClassNames.BROADCAST_RECEIVER_COMPONENT_MANAGER,
-            null);
-    private static final Type ACTIVITY =
-        new Type(
-            AndroidClassNames.ACTIVITY_COMPONENT,
-            AndroidType.ACTIVITY,
-            AndroidClassNames.ACTIVITY_COMPONENT_MANAGER,
-            CodeBlock.of("this"));
-    private static final Type FRAGMENT =
-        new Type(
-            AndroidClassNames.FRAGMENT_COMPONENT,
-            AndroidType.FRAGMENT,
-            AndroidClassNames.FRAGMENT_COMPONENT_MANAGER,
-            CodeBlock.of("this"));
-    private static final Type VIEW =
-        new Type(
-            AndroidClassNames.VIEW_WITH_FRAGMENT_COMPONENT,
-            AndroidType.VIEW,
-            AndroidClassNames.VIEW_COMPONENT_MANAGER,
-            CodeBlock.of("this, true /* hasFragmentBindings */"));
-    private static final Type VIEW_NO_FRAGMENT =
-        new Type(
-            AndroidClassNames.VIEW_COMPONENT,
-            AndroidType.VIEW,
-            AndroidClassNames.VIEW_COMPONENT_MANAGER,
-            CodeBlock.of("this, false /* hasFragmentBindings */"));
-
-    final ClassName component;
-    final AndroidType androidType;
-    final ClassName manager;
-    final CodeBlock componentManagerInitArgs;
-
-    Type(
-        ClassName component,
-        AndroidType androidType,
-        ClassName manager,
-        CodeBlock componentManagerInitArgs) {
-      this.component = component;
-      this.androidType = androidType;
-      this.manager = manager;
-      this.componentManagerInitArgs = componentManagerInitArgs;
-    }
-
-    AndroidType androidType() {
-      return androidType;
-    }
-
-    private static Type of(TypeElement element, TypeElement baseElement) {
-      if (Processors.hasAnnotation(element, AndroidClassNames.HILT_ANDROID_APP)) {
-        return forHiltAndroidApp(element, baseElement);
-      }
-      return forAndroidEntryPoint(element, baseElement);
-    }
-
-    private static Type forHiltAndroidApp(TypeElement element, TypeElement baseElement) {
-      ProcessorErrors.checkState(
-          Processors.isAssignableFrom(baseElement, AndroidClassNames.APPLICATION),
-          element,
-          "@HiltAndroidApp base class must extend Application. Found: %s",
-          baseElement);
-      return Type.APPLICATION;
-    }
-
-    private static Type forAndroidEntryPoint(TypeElement element, TypeElement baseElement) {
-      if (Processors.isAssignableFrom(baseElement, AndroidClassNames.ACTIVITY)) {
-        ProcessorErrors.checkState(
-            Processors.isAssignableFrom(baseElement, AndroidClassNames.COMPONENT_ACTIVITY),
-            element,
-            "Activities annotated with @AndroidEntryPoint must be a subclass of "
-                + "androidx.activity.ComponentActivity. (e.g. FragmentActivity, "
-                + "AppCompatActivity, etc.)"
-            );
-        return Type.ACTIVITY;
-      } else if (Processors.isAssignableFrom(baseElement, AndroidClassNames.SERVICE)) {
-        return Type.SERVICE;
-      } else if (Processors.isAssignableFrom(baseElement, AndroidClassNames.BROADCAST_RECEIVER)) {
-        return Type.BROADCAST_RECEIVER;
-      } else if (Processors.isAssignableFrom(baseElement, AndroidClassNames.FRAGMENT)) {
-        return Type.FRAGMENT;
-      } else if (Processors.isAssignableFrom(baseElement, AndroidClassNames.VIEW)) {
-        boolean withFragmentBindings =
-            Processors.hasAnnotation(element, AndroidClassNames.WITH_FRAGMENT_BINDINGS);
-        return withFragmentBindings ? Type.VIEW : Type.VIEW_NO_FRAGMENT;
-      } else if (Processors.isAssignableFrom(baseElement, AndroidClassNames.APPLICATION)) {
-        throw new BadInputException(
-            "@AndroidEntryPoint cannot be used on an Application. Use @HiltAndroidApp instead.",
-            element);
-      }
-      throw new BadInputException(
-          "@AndroidEntryPoint base class must extend ComponentActivity, (support) Fragment, "
-              + "View, Service, or BroadcastReceiver.",
-          element);
-    }
-  }
-
-  private static void checkConsistentAnnotations(
-      TypeElement element, AndroidEntryPointMetadata baseMetadata) {
-    TypeElement baseElement = baseMetadata.element();
-    checkAnnotationsMatch(element, baseElement, AndroidClassNames.WITH_FRAGMENT_BINDINGS);
-
-    ProcessorErrors.checkState(
-        baseMetadata.allowsOptionalInjection()
-            || !Processors.hasAnnotation(element, AndroidClassNames.OPTIONAL_INJECT),
-        element,
-        "@OptionalInject Hilt class cannot extend from a non-optional @AndroidEntryPoint "
-            + "base: %s",
-        element);
-  }
-
-  private static void checkAnnotationsMatch(
-      TypeElement element, TypeElement baseElement, ClassName annotationName) {
-    boolean isAnnotated = Processors.hasAnnotation(element, annotationName);
-    boolean isBaseAnnotated = Processors.hasAnnotation(baseElement, annotationName);
-    ProcessorErrors.checkState(
-        isAnnotated == isBaseAnnotated,
-        element,
-        isBaseAnnotated
-            ? "Classes that extend an @%1$s base class must also be annotated @%1$s"
-                : "Classes that extend a @AndroidEntryPoint base class must not use @%1$s when the "
-                    + "base class "
-                + "does not use @%1$s",
-        annotationName.simpleName());
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessor.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessor.java
deleted file mode 100644
index 7bb9b9a..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessor.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.androidentrypoint;
-
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableSet;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.processor.internal.BaseProcessor;
-import java.util.Set;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/**
- * Processor that creates a module for classes marked with {@link
- * dagger.hilt.android.AndroidEntryPoint}.
- */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class AndroidEntryPointProcessor extends BaseProcessor {
-
-  @Override
-  public Set<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.of(
-        AndroidClassNames.ANDROID_ENTRY_POINT.toString(),
-        AndroidClassNames.HILT_ANDROID_APP.toString());
-  }
-
-  @Override
-  public Set<String> getSupportedOptions() {
-    return HiltCompilerOptions.getProcessorOptions();
-  }
-
-  @Override
-  public boolean delayErrors() {
-    return true;
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    AndroidEntryPointMetadata metadata = AndroidEntryPointMetadata.of(getProcessingEnv(), element);
-    new InjectorEntryPointGenerator(getProcessingEnv(), metadata).generate();
-    switch (metadata.androidType()) {
-      case APPLICATION:
-        new ApplicationGenerator(getProcessingEnv(), metadata).generate();
-        break;
-      case ACTIVITY:
-        new ActivityGenerator(getProcessingEnv(), metadata).generate();
-        break;
-      case BROADCAST_RECEIVER:
-        new BroadcastReceiverGenerator(getProcessingEnv(), metadata).generate();
-        break;
-      case FRAGMENT:
-        new FragmentGenerator(
-            getProcessingEnv(), metadata )
-            .generate();
-        break;
-      case SERVICE:
-        new ServiceGenerator(getProcessingEnv(), metadata).generate();
-        break;
-      case VIEW:
-        new ViewGenerator(getProcessingEnv(), metadata).generate();
-        break;
-      default:
-        throw new IllegalStateException("Unknown Hilt type: " + metadata.androidType());
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/ApplicationGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/ApplicationGenerator.java
deleted file mode 100644
index f16e06d..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/ApplicationGenerator.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.processor.internal.ComponentNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/** Generates an Hilt Application for an @AndroidEntryPoint app class. */
-public final class ApplicationGenerator {
-  private final ProcessingEnvironment env;
-  private final AndroidEntryPointMetadata metadata;
-  private final ClassName wrapperClassName;
-
-  public ApplicationGenerator(ProcessingEnvironment env, AndroidEntryPointMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-    wrapperClassName = metadata.generatedClassName();
-  }
-
-  // @Generated("ApplicationGenerator")
-  // abstract class Hilt_$APP extends $BASE implements ComponentManager<ApplicationComponent> {
-  //   ...
-  // }
-  public void generate() throws IOException {
-    TypeSpec.Builder typeSpecBuilder =
-        TypeSpec.classBuilder(wrapperClassName.simpleName())
-            .addOriginatingElement(metadata.element())
-            .superclass(metadata.baseClassName())
-            .addModifiers(metadata.generatedClassModifiers())
-            .addField(componentManagerField())
-            .addMethod(componentManagerMethod());
-
-    Generators.addGeneratedBaseClassJavadoc(typeSpecBuilder, AndroidClassNames.HILT_ANDROID_APP);
-    Processors.addGeneratedAnnotation(typeSpecBuilder, env, getClass());
-
-    metadata.baseElement().getTypeParameters().stream()
-        .map(TypeVariableName::get)
-        .forEachOrdered(typeSpecBuilder::addTypeVariable);
-
-    Generators.copyLintAnnotations(metadata.element(), typeSpecBuilder);
-    Generators.addComponentOverride(metadata, typeSpecBuilder);
-
-      typeSpecBuilder.addMethod(onCreateMethod());
-
-    JavaFile.builder(metadata.elementClassName().packageName(), typeSpecBuilder.build())
-        .build()
-        .writeTo(env.getFiler());
-  }
-
-  // private final ApplicationComponentManager<ApplicationComponent> componentManager =
-  //     new ApplicationComponentManager(/* creatorType */);
-  private FieldSpec componentManagerField() {
-    ParameterSpec managerParam = metadata.componentManagerParam();
-    return FieldSpec.builder(managerParam.type, managerParam.name)
-        .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
-        .initializer("new $T($L)", AndroidClassNames.APPLICATION_COMPONENT_MANAGER, creatorType())
-        .build();
-  }
-
-  // protected ApplicationComponentManager<ApplicationComponent> componentManager() {
-  //   return componentManager();
-  // }
-  private MethodSpec componentManagerMethod() {
-    return MethodSpec.methodBuilder("componentManager")
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-        .returns(metadata.componentManagerParam().type)
-        .addStatement("return $N", metadata.componentManagerParam())
-        .build();
-  }
-
-  // new Supplier<ApplicationComponent>() {
-  //   @Override
-  //   public ApplicationComponent get() {
-  //     return DaggerApplicationComponent.builder()
-  //         .applicationContextModule(new ApplicationContextModule(Hilt_$APP.this))
-  //         .build();
-  //   }
-  // }
-  private TypeSpec creatorType() {
-    ClassName component =
-        ComponentNames.generatedComponent(
-            metadata.elementClassName(), AndroidClassNames.SINGLETON_COMPONENT);
-    return TypeSpec.anonymousClassBuilder("")
-        .addSuperinterface(AndroidClassNames.COMPONENT_SUPPLIER)
-        .addMethod(
-            MethodSpec.methodBuilder("get")
-                .addAnnotation(Override.class)
-                .addModifiers(Modifier.PUBLIC)
-                .returns(TypeName.OBJECT)
-                .addStatement(
-                    "return $T.builder()\n"
-                        + ".applicationContextModule(new $T($T.this))\n"
-                        + ".build()",
-                    Processors.prepend(Processors.getEnclosedClassName(component), "Dagger"),
-                    AndroidClassNames.APPLICATION_CONTEXT_MODULE,
-                    wrapperClassName)
-                .build())
-        .build();
-  }
-
-  // @CallSuper
-  // @Override
-  // public void onCreate() {
-  //   // This is a known unsafe cast but should be fine if the only use is
-  //   // $APP extends Hilt_$APP
-  //   generatedComponent().inject(($APP) this);
-  //   super.onCreate();
-  // }
-  private MethodSpec onCreateMethod() {
-    return MethodSpec.methodBuilder("onCreate")
-        .addAnnotation(AndroidClassNames.CALL_SUPER)
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC)
-        .addCode(injectCodeBlock())
-        .addStatement("super.onCreate()")
-        .build();
-  }
-
-  //   // This is a known unsafe cast but should be fine if the only use is
-  //   // $APP extends Hilt_$APP
-  //   generatedComponent().inject$APP(($APP) this);
-  private CodeBlock injectCodeBlock() {
-    return CodeBlock.builder()
-        .add("// This is a known unsafe cast, but is safe in the only correct use case:\n")
-        .add("// $T extends $T\n", metadata.elementClassName(), metadata.generatedClassName())
-        .addStatement(
-            "(($T) generatedComponent()).$L($L)",
-            metadata.injectorClassName(),
-            metadata.injectMethodName(),
-            Generators.unsafeCastThisTo(metadata.elementClassName()))
-        .build();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD b/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
deleted file mode 100644
index 55e9ddc..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright (C) 2020 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.
-# Description:
-#   Hilt android processors.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "plugin",
-    generates_api = 1,
-    processor_class = "dagger.hilt.android.processor.internal.androidentrypoint.AndroidEntryPointProcessor",
-    tags = [
-        "annotation=dagger.hilt.android.AndroidEntryPoint;" +
-        "genclass=${package}.Hilt_${outerclasses}${classname};" +
-        "genclass=${package}.${outerclasses}${classname}_EntryPoint",
-    ],
-    deps = [
-        ":processor_lib",
-    ],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = ["AndroidEntryPointProcessor.java"],
-    deps = [
-        ":android_generators",
-        ":compiler_options",
-        ":metadata",
-        "//java/dagger/hilt/android/processor/internal:android_classnames",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-    ],
-)
-
-java_library(
-    name = "android_generators",
-    srcs = [
-        "ActivityGenerator.java",
-        "ApplicationGenerator.java",
-        "BroadcastReceiverGenerator.java",
-        "FragmentGenerator.java",
-        "Generators.java",
-        "InjectorEntryPointGenerator.java",
-        "ServiceGenerator.java",
-        "ViewGenerator.java",
-    ],
-    deps = [
-        ":metadata",
-        "//java/dagger/hilt/android/processor/internal:android_classnames",
-        "//java/dagger/hilt/android/processor/internal:utils",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:component_names",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_library(
-    name = "metadata",
-    srcs = [
-        "AndroidEntryPointMetadata.java",
-    ],
-    deps = [
-        ":compiler_options",
-        "//java/dagger/hilt/android/processor/internal:android_classnames",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:components",
-        "//java/dagger/hilt/processor/internal:kotlin",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_library(
-    name = "compiler_options",
-    srcs = ["HiltCompilerOptions.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/BroadcastReceiverGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/BroadcastReceiverGenerator.java
deleted file mode 100644
index f8e9f60..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/BroadcastReceiverGenerator.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-import static dagger.internal.codegen.langmodel.DaggerElements.getMethodDescriptor;
-
-import com.google.common.collect.Iterables;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.android.processor.internal.MoreTypes;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-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 javax.lang.model.util.ElementFilter;
-
-/** Generates an Hilt BroadcastReceiver class for the @AndroidEntryPoint annotated class. */
-public final class BroadcastReceiverGenerator {
-
-  private static final String ON_RECEIVE_DESCRIPTOR =
-      "onReceive(Landroid/content/Context;Landroid/content/Intent;)V";
-
-  private final ProcessingEnvironment env;
-  private final AndroidEntryPointMetadata metadata;
-  private final ClassName generatedClassName;
-
-  public BroadcastReceiverGenerator(
-      ProcessingEnvironment env, AndroidEntryPointMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-
-    generatedClassName = metadata.generatedClassName();
-  }
-
-  // @Generated("BroadcastReceiverGenerator")
-  // abstract class Hilt_$CLASS extends $BASE {
-  //   ...
-  // }
-  public void generate() throws IOException {
-    TypeSpec.Builder builder =
-        TypeSpec.classBuilder(generatedClassName.simpleName())
-            .addOriginatingElement(metadata.element())
-            .superclass(metadata.baseClassName())
-            .addModifiers(metadata.generatedClassModifiers())
-            .addMethod(onReceiveMethod());
-
-    Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT);
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-    Generators.copyConstructors(metadata.baseElement(), builder);
-
-    metadata.baseElement().getTypeParameters().stream()
-        .map(TypeVariableName::get)
-        .forEachOrdered(builder::addTypeVariable);
-
-    Generators.addInjectionMethods(metadata, builder);
-    Generators.copyLintAnnotations(metadata.element(), builder);
-
-    // Add an unused field used as a marker to let the bytecode injector know this receiver will
-    // need to be injected with a super.onReceive call. This is only necessary if no concrete
-    // onReceive call is implemented in any of the super classes.
-    if (metadata.requiresBytecodeInjection() && !isOnReceiveImplemented(metadata.baseElement())) {
-      builder.addField(
-          FieldSpec.builder(
-                  TypeName.BOOLEAN,
-                  "onReceiveBytecodeInjectionMarker",
-                  Modifier.PRIVATE,
-                  Modifier.FINAL)
-              .initializer("false")
-              .build());
-    }
-
-    JavaFile.builder(generatedClassName.packageName(),
-        builder.build()).build().writeTo(env.getFiler());
-  }
-
-  private static boolean isOnReceiveImplemented(TypeElement typeElement) {
-    boolean isImplemented =
-        ElementFilter.methodsIn(typeElement.getEnclosedElements()).stream()
-            .anyMatch(
-                methodElement ->
-                    getMethodDescriptor(methodElement).equals(ON_RECEIVE_DESCRIPTOR)
-                        && !methodElement.getModifiers().contains(Modifier.ABSTRACT));
-    if (isImplemented) {
-      return true;
-    } else if (typeElement.getSuperclass().getKind() != TypeKind.NONE) {
-      return isOnReceiveImplemented(MoreTypes.asTypeElement(typeElement.getSuperclass()));
-    } else {
-      return false;
-    }
-  }
-
-  // @Override
-  // public void onReceive(Context context, Intent intent) {
-  //   inject(context);
-  //   super.onReceive();
-  // }
-  private MethodSpec onReceiveMethod() throws IOException {
-    MethodSpec.Builder method =
-        MethodSpec.methodBuilder("onReceive")
-            .addAnnotation(Override.class)
-            .addAnnotation(AndroidClassNames.CALL_SUPER)
-            .addModifiers(Modifier.PUBLIC)
-            .addParameter(ParameterSpec.builder(AndroidClassNames.CONTEXT, "context").build())
-            .addParameter(ParameterSpec.builder(AndroidClassNames.INTENT, "intent").build())
-            .addStatement("inject(context)");
-
-    if (metadata.overridesAndroidEntryPointClass()) {
-      // We directly call super.onReceive here because we know Hilt base classes have a
-      // non-abstract onReceive method. However, because the Hilt base class may not be generated
-      // already we cannot fall down to the below logic to find it.
-      method.addStatement("super.onReceive(context, intent)");
-    } else {
-      // Get the onReceive method element from BroadcastReceiver.
-      ExecutableElement onReceiveElement =
-          Iterables.getOnlyElement(
-              MoreTypes.findMethods(
-                  env.getElementUtils()
-                      .getTypeElement(AndroidClassNames.BROADCAST_RECEIVER.toString()),
-                  "onReceive"));
-
-      // If the base class or one of its super classes implements onReceive, call super.onReceive()
-      MoreTypes.findInheritedMethod(env.getTypeUtils(), metadata.baseElement(), onReceiveElement)
-          .filter(onReceive -> !onReceive.getModifiers().contains(Modifier.ABSTRACT))
-          .ifPresent(onReceive -> method.addStatement("super.onReceive(context, intent)"));
-    }
-
-    return method.build();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/FragmentGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/FragmentGenerator.java
deleted file mode 100644
index 4ef479f..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/FragmentGenerator.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/** Generates an Hilt Fragment class for the @AndroidEntryPoint annotated class. */
-public final class FragmentGenerator {
-  private static final FieldSpec COMPONENT_CONTEXT_FIELD =
-      FieldSpec.builder(AndroidClassNames.CONTEXT_WRAPPER, "componentContext")
-          .addModifiers(Modifier.PRIVATE)
-          .build();
-
-  private final ProcessingEnvironment env;
-  private final AndroidEntryPointMetadata metadata;
-  private final ClassName generatedClassName;
-
-  public FragmentGenerator(
-      ProcessingEnvironment env,
-      AndroidEntryPointMetadata metadata ) {
-    this.env = env;
-    this.metadata = metadata;
-    generatedClassName = metadata.generatedClassName();
-  }
-
-  public void generate() throws IOException {
-    JavaFile.builder(generatedClassName.packageName(), createTypeSpec())
-        .build()
-        .writeTo(env.getFiler());
-  }
-
-  // @Generated("FragmentGenerator")
-  // abstract class Hilt_$CLASS extends $BASE implements ComponentManager<?> {
-  //   ...
-  // }
-  TypeSpec createTypeSpec() {
-    TypeSpec.Builder builder =
-        TypeSpec.classBuilder(generatedClassName.simpleName())
-            .addOriginatingElement(metadata.element())
-            .superclass(metadata.baseClassName())
-            .addModifiers(metadata.generatedClassModifiers())
-            .addField(COMPONENT_CONTEXT_FIELD)
-            .addMethod(onAttachContextMethod())
-            .addMethod(onAttachActivityMethod())
-            .addMethod(initializeComponentContextMethod())
-            .addMethod(getContextMethod())
-            .addMethod(inflatorMethod());
-
-    Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT);
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-    Generators.copyLintAnnotations(metadata.element(), builder);
-    Generators.addSuppressAnnotation(builder, "deprecation");
-    Generators.copyConstructors(metadata.baseElement(), builder);
-
-    metadata.baseElement().getTypeParameters().stream()
-        .map(TypeVariableName::get)
-        .forEachOrdered(builder::addTypeVariable);
-
-    Generators.addComponentOverride(metadata, builder);
-
-    Generators.addInjectionMethods(metadata, builder);
-
-    if (!metadata.overridesAndroidEntryPointClass() ) {
-      builder.addMethod(getDefaultViewModelProviderFactory());
-    }
-
-    return builder.build();
-  }
-
-  // @CallSuper
-  // @Override
-  // public void onAttach(Activity activity) {
-  //   super.onAttach(activity);
-  //   initializeComponentContext();
-  // }
-  private static MethodSpec onAttachContextMethod() {
-    return MethodSpec.methodBuilder("onAttach")
-        .addAnnotation(Override.class)
-        .addAnnotation(AndroidClassNames.CALL_SUPER)
-        .addModifiers(Modifier.PUBLIC)
-        .addParameter(AndroidClassNames.CONTEXT, "context")
-        .addStatement("super.onAttach(context)")
-        .addStatement("initializeComponentContext()")
-        .build();
-  }
-
-  // @CallSuper
-  // @Override
-  // public void onAttach(Activity activity) {
-  //   super.onAttach(activity);
-  //   Preconditions.checkState(
-  //       componentContext == null || FragmentComponentManager.findActivity(
-  //           componentContext) == activity, "...");
-  //   initializeComponentContext();
-  // }
-  private static MethodSpec onAttachActivityMethod() {
-    return MethodSpec.methodBuilder("onAttach")
-        .addAnnotation(Override.class)
-        .addAnnotation(AndroidClassNames.CALL_SUPER)
-        .addAnnotation(AndroidClassNames.MAIN_THREAD)
-        .addModifiers(Modifier.PUBLIC)
-        .addParameter(AndroidClassNames.ACTIVITY, "activity")
-        .addStatement("super.onAttach(activity)")
-        .addStatement(
-            "$T.checkState($N == null || $T.findActivity($N) == activity, $S)",
-            ClassNames.PRECONDITIONS,
-            COMPONENT_CONTEXT_FIELD,
-            AndroidClassNames.FRAGMENT_COMPONENT_MANAGER,
-            COMPONENT_CONTEXT_FIELD,
-            "onAttach called multiple times with different Context! "
-        + "Hilt Fragments should not be retained.")
-        .addStatement("initializeComponentContext()")
-        .build();
-  }
-
-  // private void initializeComponentContext() {
-  //   // Only inject on the first call to onAttach.
-  //   if (componentContext == null) {
-  //     // Note: The LayoutInflater provided by this componentContext may be different from super
-  //     // Fragment's because we are getting it from base context instead of cloning from super
-  //     // Fragment's LayoutInflater.
-  //     componentContext = FragmentComponentManager.createContextWrapper(super.getContext(), this);
-  //     inject();
-  //   }
-  // }
-  private MethodSpec initializeComponentContextMethod() {
-    return MethodSpec.methodBuilder("initializeComponentContext")
-        .addModifiers(Modifier.PRIVATE)
-        .addComment("Only inject on the first call to onAttach.")
-        .beginControlFlow("if ($N == null)", COMPONENT_CONTEXT_FIELD)
-        .addComment(
-            "Note: The LayoutInflater provided by this componentContext may be different from"
-                + " super Fragment's because we getting it from base context instead of cloning"
-                + " from the super Fragment's LayoutInflater.")
-        .addStatement(
-            "$N = $T.createContextWrapper(super.getContext(), this)",
-            COMPONENT_CONTEXT_FIELD,
-            metadata.componentManager())
-        .addStatement("inject()")
-        .endControlFlow()
-        .build();
-  }
-
-  // @Override
-  // public Context getContext() {
-  //   return componentContext;
-  // }
-  private static MethodSpec getContextMethod() {
-    return MethodSpec.methodBuilder("getContext")
-        .returns(AndroidClassNames.CONTEXT)
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC)
-        .addStatement("return $N", COMPONENT_CONTEXT_FIELD)
-        .build();
-  }
-
-  // @Override
-  // public LayoutInflater onGetLayoutInflater(Bundle savedInstanceState) {
-  //   LayoutInflater inflater = super.onGetLayoutInflater(savedInstanceState);
-  //   return LayoutInflater.from(FragmentComponentManager.createContextWrapper(inflater, this));
-  // }
-  private MethodSpec inflatorMethod() {
-    return MethodSpec.methodBuilder("onGetLayoutInflater")
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC)
-        .addParameter(AndroidClassNames.BUNDLE, "savedInstanceState")
-        .returns(AndroidClassNames.LAYOUT_INFLATER)
-        .addStatement(
-            "$T inflater = super.onGetLayoutInflater(savedInstanceState)",
-            AndroidClassNames.LAYOUT_INFLATER)
-        .addStatement(
-            "return $T.from($T.createContextWrapper(inflater, this))",
-            AndroidClassNames.LAYOUT_INFLATER,
-            metadata.componentManager())
-        .build();
-  }
-
-  // @Override
-  // public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
-  //   return DefaultViewModelFactories.getFragmentFactory(this);
-  // }
-  private MethodSpec getDefaultViewModelProviderFactory() {
-    return MethodSpec.methodBuilder("getDefaultViewModelProviderFactory")
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC)
-        .returns(AndroidClassNames.VIEW_MODEL_PROVIDER_FACTORY)
-        .addStatement(
-            "return $T.getFragmentFactory(this)",
-            AndroidClassNames.DEFAULT_VIEW_MODEL_FACTORIES)
-        .build();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/Generators.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/Generators.java
deleted file mode 100644
index daadd03..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/Generators.java
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.google.common.base.Preconditions;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import javax.lang.model.element.AnnotationMirror;
-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.element.VariableElement;
-import javax.lang.model.util.ElementFilter;
-
-/** Helper class for writing Hilt generators. */
-final class Generators {
-
-  static void addGeneratedBaseClassJavadoc(TypeSpec.Builder builder, ClassName annotation) {
-    builder.addJavadoc("A generated base class to be extended by the @$T annotated class. If using"
-        + " the Gradle plugin, this is swapped as the base class via bytecode transformation.",
-        annotation);
-  }
-
-  /**
-   * Copies all constructors with arguments to the builder.
-   */
-  static void copyConstructors(TypeElement baseClass, TypeSpec.Builder builder) {
-    copyConstructors(baseClass, CodeBlock.builder().build(), builder);
-  }
-
-  /**
-   * Copies all constructors with arguments along with an appended body to the builder.
-   */
-  static void copyConstructors(TypeElement baseClass, CodeBlock body, TypeSpec.Builder builder) {
-    List<ExecutableElement> constructors =
-        ElementFilter.constructorsIn(baseClass.getEnclosedElements())
-            .stream()
-            .filter(constructor -> !constructor.getModifiers().contains(PRIVATE))
-            .collect(Collectors.toList());
-
-    if (constructors.size() == 1
-        && getOnlyElement(constructors).getParameters().isEmpty()
-        && body.isEmpty()) {
-      // No need to copy the constructor if the default constructor will handle it.
-      return;
-    }
-
-    constructors.forEach(constructor -> builder.addMethod(copyConstructor(constructor, body)));
-  }
-
-  /** Returns Optional with AnnotationSpec for Nullable if found on element, empty otherwise. */
-  private static Optional<AnnotationSpec> getNullableAnnotationSpec(Element element) {
-    for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
-      if (annotationMirror
-          .getAnnotationType()
-          .asElement()
-          .getSimpleName()
-          .contentEquals("Nullable")) {
-        AnnotationSpec annotationSpec = AnnotationSpec.get(annotationMirror);
-        // If using the android internal Nullable, convert it to the externally-visible version.
-        return AndroidClassNames.NULLABLE_INTERNAL.equals(annotationSpec.type)
-            ? Optional.of(AnnotationSpec.builder(AndroidClassNames.NULLABLE).build())
-            : Optional.of(annotationSpec);
-      }
-    }
-    return Optional.empty();
-  }
-
-  /**
-   * Returns a ParameterSpec of the input parameter, @Nullable annotated if existing in original
-   * (this does not handle Nullable type annotations).
-   */
-  private static ParameterSpec getParameterSpecWithNullable(VariableElement parameter) {
-    ParameterSpec.Builder builder = ParameterSpec.get(parameter).toBuilder();
-    getNullableAnnotationSpec(parameter).ifPresent(builder::addAnnotation);
-    return builder.build();
-  }
-
-  /**
-   * Returns a {@link MethodSpec} for a constructor matching the given {@link ExecutableElement}
-   * constructor signature, and just calls super. If the constructor is
-   * {@link android.annotation.TargetApi} guarded, adds the TargetApi as well.
-   */
-  // Example:
-  //   Foo(Param1 param1, Param2 param2) {
-  //     super(param1, param2);
-  //   }
-  static MethodSpec copyConstructor(ExecutableElement constructor) {
-    return copyConstructor(constructor, CodeBlock.builder().build());
-  }
-
-  private static MethodSpec copyConstructor(ExecutableElement constructor, CodeBlock body) {
-    List<ParameterSpec> params =
-        constructor.getParameters().stream()
-            .map(parameter -> getParameterSpecWithNullable(parameter))
-            .collect(Collectors.toList());
-
-    final MethodSpec.Builder builder =
-        MethodSpec.constructorBuilder()
-            .addParameters(params)
-            .addStatement(
-                "super($L)",
-                params.stream().map(param -> param.name).collect(Collectors.joining(", ")))
-            .addCode(body);
-
-    constructor.getAnnotationMirrors().stream()
-        .filter(a -> Processors.hasAnnotation(a, AndroidClassNames.TARGET_API))
-        .collect(toOptional())
-        .map(AnnotationSpec::get)
-        .ifPresent(builder::addAnnotation);
-
-    return builder.build();
-  }
-
-  /**
-   * Copies the Android lint annotations from the annotated element to the generated element.
-   *
-   * <p>Note: For now we only copy over {@link android.annotation.TargetApi}.
-   */
-  static void copyLintAnnotations(Element element, TypeSpec.Builder builder) {
-    if (Processors.hasAnnotation(element, AndroidClassNames.TARGET_API)) {
-      builder.addAnnotation(
-          AnnotationSpec.get(
-              Processors.getAnnotationMirror(element, AndroidClassNames.TARGET_API)));
-    }
-  }
-
-  // @Override
-  // public CompT generatedComponent() {
-  //   return componentManager().generatedComponent();
-  // }
-  static void addComponentOverride(AndroidEntryPointMetadata metadata, TypeSpec.Builder builder) {
-    if (metadata.overridesAndroidEntryPointClass()) {
-      // We don't need to override this method if we are extending a Hilt type.
-      return;
-    }
-    builder
-        .addSuperinterface(ClassNames.GENERATED_COMPONENT_MANAGER_HOLDER)
-        .addMethod(
-            MethodSpec.methodBuilder("generatedComponent")
-                .addAnnotation(Override.class)
-                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-                .returns(TypeName.OBJECT)
-                .addStatement("return $L.generatedComponent()", componentManagerCallBlock(metadata))
-                .build());
-  }
-
-  /** Adds the inject() and optionally the componentManager() methods to allow for injection. */
-  static void addInjectionMethods(AndroidEntryPointMetadata metadata, TypeSpec.Builder builder) {
-    switch (metadata.androidType()) {
-      case ACTIVITY:
-      case FRAGMENT:
-      case VIEW:
-      case SERVICE:
-        addComponentManagerMethods(metadata, builder);
-        // fall through
-      case BROADCAST_RECEIVER:
-        addInjectMethod(metadata, builder);
-        break;
-      default:
-        throw new AssertionError();
-    }
-  }
-
-  // @Override
-  // public FragmentComponentManager componentManager() {
-  //   if (componentManager == null) {
-  //     synchronize (componentManagerLock) {
-  //       if (componentManager == null) {
-  //         componentManager = createComponentManager();
-  //       }
-  //     }
-  //   }
-  //   return componentManager;
-  // }
-  private static void addComponentManagerMethods(
-      AndroidEntryPointMetadata metadata, TypeSpec.Builder typeSpecBuilder) {
-    if (metadata.overridesAndroidEntryPointClass()) {
-      // We don't need to override this method if we are extending a Hilt type.
-      return;
-    }
-
-    ParameterSpec managerParam = metadata.componentManagerParam();
-    typeSpecBuilder.addField(componentManagerField(metadata));
-
-    typeSpecBuilder.addMethod(createComponentManagerMethod(metadata));
-
-    MethodSpec.Builder methodSpecBuilder =
-        MethodSpec.methodBuilder("componentManager")
-            .addAnnotation(Override.class)
-            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-            .returns(managerParam.type)
-            .beginControlFlow("if ($N == null)", managerParam);
-
-    // Views do not do double-checked locking because this is called from the constructor
-    if (metadata.androidType() != AndroidEntryPointMetadata.AndroidType.VIEW) {
-      typeSpecBuilder.addField(componentManagerLockField());
-
-      methodSpecBuilder
-        .beginControlFlow("synchronized (componentManagerLock)")
-        .beginControlFlow("if ($N == null)", managerParam);
-    }
-
-    methodSpecBuilder
-        .addStatement("$N = createComponentManager()", managerParam)
-        .endControlFlow();
-
-    if (metadata.androidType() != AndroidEntryPointMetadata.AndroidType.VIEW) {
-      methodSpecBuilder
-          .endControlFlow()
-          .endControlFlow();
-    }
-
-    methodSpecBuilder.addStatement("return $N", managerParam);
-
-    typeSpecBuilder.addMethod(methodSpecBuilder.build());
-  }
-
-  // protected FragmentComponentManager createComponentManager() {
-  //   return new FragmentComponentManager(initArgs);
-  // }
-  private static MethodSpec createComponentManagerMethod(AndroidEntryPointMetadata metadata) {
-    Preconditions.checkState(
-        metadata.componentManagerInitArgs().isPresent(),
-        "This method should not have been called for metadata where the init args are not"
-            + " present.");
-    return MethodSpec.methodBuilder("createComponentManager")
-        .addModifiers(Modifier.PROTECTED)
-        .returns(metadata.componentManager())
-        .addStatement(
-            "return new $T($L)",
-            metadata.componentManager(),
-            metadata.componentManagerInitArgs().get())
-        .build();
-  }
-
-  // private volatile ComponentManager componentManager;
-  private static FieldSpec componentManagerField(AndroidEntryPointMetadata metadata) {
-    ParameterSpec managerParam = metadata.componentManagerParam();
-    FieldSpec.Builder builder = FieldSpec.builder(managerParam.type, managerParam.name)
-        .addModifiers(Modifier.PRIVATE);
-
-    // Views do not need volatile since these are set in the constructor if ever set.
-    if (metadata.androidType() != AndroidEntryPointMetadata.AndroidType.VIEW) {
-      builder.addModifiers(Modifier.VOLATILE);
-    }
-
-    return builder.build();
-  }
-
-  // private final Object componentManagerLock = new Object();
-  private static FieldSpec componentManagerLockField() {
-    return FieldSpec.builder(TypeName.get(Object.class), "componentManagerLock")
-        .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
-        .initializer("new Object()")
-        .build();
-  }
-
-  // protected void inject() {
-  //   if (!injected) {
-  //     generatedComponent().inject$CLASS(($CLASS) this);
-  //     injected = true;
-  //   }
-  // }
-  private static void addInjectMethod(
-      AndroidEntryPointMetadata metadata, TypeSpec.Builder typeSpecBuilder) {
-    MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder("inject")
-        .addModifiers(Modifier.PROTECTED);
-
-    // Check if the parent is a Hilt type. If it isn't or if it is but it
-    // wasn't injected by hilt, then return.
-    // Object parent = ...depends on type...
-    // if (!(parent instanceof GeneratedComponentManager)
-    //     || ((parent instanceof InjectedByHilt) &&
-    //         !((InjectedByHilt) parent).wasInjectedByHilt())) {
-    //   return;
-    //
-    if (metadata.allowsOptionalInjection()) {
-      methodSpecBuilder
-          .addStatement("$T parent = $L", ClassNames.OBJECT, getParentCodeBlock(metadata))
-          .beginControlFlow(
-              "if (!(parent instanceof $T) "
-              + "|| ((parent instanceof $T) && !(($T) parent).wasInjectedByHilt()))",
-              ClassNames.GENERATED_COMPONENT_MANAGER,
-              AndroidClassNames.INJECTED_BY_HILT,
-              AndroidClassNames.INJECTED_BY_HILT)
-          .addStatement("return")
-          .endControlFlow();
-    }
-
-    typeSpecBuilder.addField(injectedField(metadata));
-
-    switch (metadata.androidType()) {
-      case ACTIVITY:
-      case FRAGMENT:
-      case VIEW:
-      case SERVICE:
-        // Only add @Override if an ancestor extends a generated Hilt class.
-        // When using bytecode injection, this isn't always guaranteed.
-        if (metadata.overridesAndroidEntryPointClass()
-            && ancestorExtendsGeneratedHiltClass(metadata)) {
-          methodSpecBuilder.addAnnotation(Override.class);
-        }
-        methodSpecBuilder
-            .beginControlFlow("if (!injected)")
-            .addStatement("injected = true")
-            .addStatement(
-                "(($T) $L).$L($L)",
-                metadata.injectorClassName(),
-                generatedComponentCallBlock(metadata),
-                metadata.injectMethodName(),
-                unsafeCastThisTo(metadata.elementClassName()))
-            .endControlFlow();
-        break;
-      case BROADCAST_RECEIVER:
-        typeSpecBuilder.addField(injectedLockField());
-
-        methodSpecBuilder
-            .addParameter(ParameterSpec.builder(AndroidClassNames.CONTEXT, "context").build())
-            .beginControlFlow("if (!injected)")
-            .beginControlFlow("synchronized (injectedLock)")
-            .beginControlFlow("if (!injected)")
-            .addStatement(
-                "(($T) $T.generatedComponent(context)).$L($L)",
-                metadata.injectorClassName(),
-                metadata.componentManager(),
-                metadata.injectMethodName(),
-                unsafeCastThisTo(metadata.elementClassName()))
-            .addStatement("injected = true")
-            .endControlFlow()
-            .endControlFlow()
-            .endControlFlow();
-        break;
-      default:
-        throw new AssertionError();
-    }
-
-    // Also add a wasInjectedByHilt method if needed.
-    // Even if we aren't optionally injected, if we override an optionally injected Hilt class
-    // we also need to override the wasInjectedByHilt method.
-    if (metadata.allowsOptionalInjection() || metadata.baseAllowsOptionalInjection()) {
-      typeSpecBuilder.addMethod(
-          MethodSpec.methodBuilder("wasInjectedByHilt")
-              .addAnnotation(Override.class)
-              .addModifiers(Modifier.PUBLIC)
-              .returns(boolean.class)
-              .addStatement("return injected")
-              .build());
-      // Only add the interface though if this class allows optional injection (not that it
-      // really matters since if the base allows optional injection the class implements the
-      // interface anyway). But it is probably better to be consistent about only optionally
-      // injected classes extend the interface.
-      if (metadata.allowsOptionalInjection()) {
-        typeSpecBuilder.addSuperinterface(AndroidClassNames.INJECTED_BY_HILT);
-      }
-    }
-
-    typeSpecBuilder.addMethod(methodSpecBuilder.build());
-  }
-
-  private static CodeBlock getParentCodeBlock(AndroidEntryPointMetadata metadata) {
-    switch (metadata.androidType()) {
-      case ACTIVITY:
-      case SERVICE:
-        return CodeBlock.of("getApplicationContext()");
-      case FRAGMENT:
-        return CodeBlock.of("getHost()");
-      case VIEW:
-        return CodeBlock.of(
-            "$L.maybeGetParentComponentManager()", componentManagerCallBlock(metadata));
-      case BROADCAST_RECEIVER:
-        // Broadcast receivers receive a "context" parameter
-        return CodeBlock.of("context.getApplicationContext()");
-      default:
-        throw new AssertionError();
-    }
-  }
-
-  /**
-   * Returns the call to {@code generatedComponent()} with casts if needed.
-   *
-   * <p>A cast is required when the root generated Hilt class uses bytecode injection because
-   * subclasses won't have access to the {@code generatedComponent()} method in that case.
-   */
-  private static CodeBlock generatedComponentCallBlock(AndroidEntryPointMetadata metadata) {
-    return CodeBlock.of(
-        "$L.generatedComponent()",
-        !metadata.isRootMetadata() && metadata.rootMetadata().requiresBytecodeInjection()
-            ? unsafeCastThisTo(ClassNames.GENERATED_COMPONENT_MANAGER_HOLDER)
-            : "this");
-  }
-
-  /**
-   * Returns the call to {@code componentManager()} with casts if needed.
-   *
-   * <p>A cast is required when the root generated Hilt class uses bytecode injection because
-   * subclasses won't have access to the {@code componentManager()} method in that case.
-   */
-  private static CodeBlock componentManagerCallBlock(AndroidEntryPointMetadata metadata) {
-    return CodeBlock.of(
-        "$L.componentManager()",
-        !metadata.isRootMetadata() && metadata.rootMetadata().requiresBytecodeInjection()
-            ? unsafeCastThisTo(ClassNames.GENERATED_COMPONENT_MANAGER_HOLDER)
-            : "this");
-  }
-
-  static CodeBlock unsafeCastThisTo(ClassName castType) {
-    return CodeBlock.of("$T.<$T>unsafeCast(this)", ClassNames.UNSAFE_CASTS, castType);
-  }
-
-  /** Returns {@code true} if the an ancestor annotated class extends the generated class */
-  private static boolean ancestorExtendsGeneratedHiltClass(AndroidEntryPointMetadata metadata) {
-    while (metadata.baseMetadata().isPresent()) {
-      metadata = metadata.baseMetadata().get();
-      if (!metadata.requiresBytecodeInjection()) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  // private boolean injected = false;
-  private static FieldSpec injectedField(AndroidEntryPointMetadata metadata) {
-    FieldSpec.Builder builder = FieldSpec.builder(TypeName.BOOLEAN, "injected")
-        .addModifiers(Modifier.PRIVATE);
-
-    // Broadcast receivers do double-checked locking so this needs to be volatile
-    if (metadata.androidType() == AndroidEntryPointMetadata.AndroidType.BROADCAST_RECEIVER) {
-      builder.addModifiers(Modifier.VOLATILE);
-    }
-
-    // Views should not add an initializer here as this runs after the super constructor
-    // and may reset state set during the super constructor call.
-    if (metadata.androidType() != AndroidEntryPointMetadata.AndroidType.VIEW) {
-      builder.initializer("false");
-    }
-    return builder.build();
-  }
-
-  // private final Object injectedLock = new Object();
-  private static FieldSpec injectedLockField() {
-    return FieldSpec.builder(TypeName.OBJECT, "injectedLock")
-        .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
-        .initializer("new $T()", TypeName.OBJECT)
-        .build();
-  }
-
-  /**
-   * Adds the SupressWarnings to supress a warning in the generated code.
-   *
-   * @param keys the string keys of the warnings to suppress, e.g. 'deprecation', 'unchecked', etc.
-   */
-  public static void addSuppressAnnotation(TypeSpec.Builder builder, String... keys) {
-    AnnotationSpec.Builder annotationBuilder = AnnotationSpec.builder(SuppressWarnings.class);
-    for (String key : keys) {
-      annotationBuilder.addMember("value", "$S", key);
-    }
-    builder.addAnnotation(annotationBuilder.build());
-  }
-
-  private Generators() {}
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/HiltCompilerOptions.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/HiltCompilerOptions.java
deleted file mode 100644
index 577410d..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/HiltCompilerOptions.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.androidentrypoint;
-
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.annotation.processing.ProcessingEnvironment;
-
-/** Hilt annotation processor options. */
-// TODO(danysantiago): Consider consolidating with Dagger compiler options logic.
-// TODO(user): Move this class to dagger/hilt/processor/internal
-public final class HiltCompilerOptions {
-
-  /** Processor options which can have true or false values. */
-  public enum BooleanOption {
-    /**
-     * Flag that disables validating the superclass of @AndroidEntryPoint are Hilt_ generated,
-     * classes. This flag is to be used internally by the Gradle plugin, enabling the bytecode
-     * transformation to change the superclass.
-     */
-    DISABLE_ANDROID_SUPERCLASS_VALIDATION(
-        "android.internal.disableAndroidSuperclassValidation", false),
-
-    /** Flag that disables check on modules to be annotated with @InstallIn. */
-    DISABLE_MODULES_HAVE_INSTALL_IN_CHECK("disableModulesHaveInstallInCheck", false);
-
-    private final String name;
-    private final boolean defaultValue;
-
-    BooleanOption(String name, boolean defaultValue) {
-      this.name = name;
-      this.defaultValue = defaultValue;
-    }
-
-    public boolean get(ProcessingEnvironment env) {
-      String value = env.getOptions().get(getQualifiedName());
-      if (value == null) {
-        return defaultValue;
-      }
-      // TODO(danysantiago): Strictly verify input, either 'true' or 'false' and nothing else.
-      return Boolean.parseBoolean(value);
-    }
-
-    public String getQualifiedName() {
-      return "dagger.hilt." + name;
-    }
-  }
-
-  public static Set<String> getProcessorOptions() {
-    return Arrays.stream(BooleanOption.values())
-        .map(BooleanOption::getQualifiedName)
-        .collect(Collectors.toSet());
-  }
-
-  private HiltCompilerOptions() {}
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/InjectorEntryPointGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/InjectorEntryPointGenerator.java
deleted file mode 100644
index e9e217d..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/InjectorEntryPointGenerator.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/** Generates an entry point that allows for injection of the given activity */
-public final class InjectorEntryPointGenerator {
-  private final ProcessingEnvironment env;
-  private final AndroidEntryPointMetadata metadata;
-
-  public InjectorEntryPointGenerator(
-      ProcessingEnvironment env, AndroidEntryPointMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-  }
-
-  // @Generated("InjectorEntryPointGenerator")
-  // @InstallIn({$SCOPES})
-  // public interface FooActivity_GeneratedInjector {
-  //   void injectFoo(FooActivity foo);
-  // }
-  public void generate() throws IOException {
-    ClassName name = metadata.injectorClassName();
-    TypeSpec.Builder builder =
-        TypeSpec.interfaceBuilder(name.simpleName())
-            .addOriginatingElement(metadata.element())
-            .addAnnotation(Processors.getOriginatingElementAnnotation(metadata.element()))
-            .addAnnotation(ClassNames.GENERATED_ENTRY_POINT)
-            .addAnnotation(metadata.injectorInstallInAnnotation())
-            .addModifiers(Modifier.PUBLIC)
-            .addMethod(
-                MethodSpec.methodBuilder(metadata.injectMethodName())
-                    .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
-                    .addParameter(
-                        metadata.elementClassName(),
-                        Processors.upperToLowerCamel(metadata.elementClassName().simpleName()))
-                    .build());
-
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-    Generators.copyLintAnnotations(metadata.element(), builder);
-
-    JavaFile.builder(name.packageName(), builder.build()).build().writeTo(env.getFiler());
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/ServiceGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/ServiceGenerator.java
deleted file mode 100644
index a80a215..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/ServiceGenerator.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import java.util.List;
-import java.util.stream.Collectors;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.util.ElementFilter;
-
-/** Generates an Hilt Service class for the @AndroidEntryPoint annotated class. */
-public final class ServiceGenerator {
-  private final ProcessingEnvironment env;
-  private final AndroidEntryPointMetadata metadata;
-  private final ClassName generatedClassName;
-
-  public ServiceGenerator(ProcessingEnvironment env, AndroidEntryPointMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-
-    generatedClassName = metadata.generatedClassName();
-  }
-
-  // @Generated("ServiceGenerator")
-  // abstract class Hilt_$CLASS extends $BASE {
-  //   ...
-  // }
-  public void generate() throws IOException {
-    TypeSpec.Builder builder =
-        TypeSpec.classBuilder(generatedClassName.simpleName())
-            .addOriginatingElement(metadata.element())
-            .superclass(metadata.baseClassName())
-            .addModifiers(metadata.generatedClassModifiers())
-            .addMethods(baseClassConstructors())
-            .addMethod(onCreateMethod());
-
-    Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT);
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-    Generators.copyLintAnnotations(metadata.element(), builder);
-
-    metadata.baseElement().getTypeParameters().stream()
-        .map(TypeVariableName::get)
-        .forEachOrdered(builder::addTypeVariable);
-
-    Generators.addInjectionMethods(metadata, builder);
-
-    Generators.addComponentOverride(metadata, builder);
-
-    JavaFile.builder(generatedClassName.packageName(), builder.build())
-        .build().writeTo(env.getFiler());
-  }
-
-  private List<MethodSpec> baseClassConstructors() {
-    return ElementFilter.constructorsIn(metadata.baseElement().getEnclosedElements())
-        .stream()
-        .map((constructor) -> {
-          List<ParameterSpec> params =
-              constructor.getParameters()
-                  .stream()
-                  .map(p -> ParameterSpec.builder(TypeName.get(p.asType()), p.toString()).build())
-                  .collect(Collectors.toList());
-
-          return MethodSpec.constructorBuilder()
-              .addParameters(params)
-              .addStatement(
-                  "super($L)",
-                  params.stream().map(p -> p.name).collect(Collectors.joining(",")))
-              .build();
-        })
-        .collect(Collectors.toList());
-  }
-
-  // @CallSuper
-  // @Override
-  // protected void onCreate() {
-  //   inject();
-  //   super.onCreate();
-  // }
-  private MethodSpec onCreateMethod() throws IOException {
-    return MethodSpec.methodBuilder("onCreate")
-        .addAnnotation(AndroidClassNames.CALL_SUPER)
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC)
-        .addStatement("inject()")
-        .addStatement("super.onCreate()")
-        .build();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/ViewGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/ViewGenerator.java
deleted file mode 100644
index 412b09a..0000000
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/ViewGenerator.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.android.processor.internal.androidentrypoint;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.Visibility;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.hilt.android.processor.internal.AndroidClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import java.util.List;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-
-/** Generates an Hilt View class for the @AndroidEntryPoint annotated class. */
-public final class ViewGenerator {
-  private final ProcessingEnvironment env;
-  private final AndroidEntryPointMetadata metadata;
-  private final ClassName generatedClassName;
-
-  public ViewGenerator(ProcessingEnvironment env, AndroidEntryPointMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-
-    generatedClassName = metadata.generatedClassName();
-  }
-
-  // @Generated("ViewGenerator")
-  // abstract class Hilt_$CLASS extends $BASE implements
-  //    ComponentManagerHolder<ViewComponentManager<$CLASS_EntryPoint>> {
-  //   ...
-  // }
-  public void generate() throws IOException {
-    // Note: we do not use the Generators helper methods here because injection is called
-    // from the constructor where the double-check pattern doesn't work (due to the super
-    // constructor being called before fields are initialized) and because it isn't necessary
-    // since the object isn't done constructing yet.
-
-    TypeSpec.Builder builder =
-        TypeSpec.classBuilder(generatedClassName.simpleName())
-            .addOriginatingElement(metadata.element())
-            .superclass(metadata.baseClassName())
-            .addModifiers(metadata.generatedClassModifiers());
-
-    Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT);
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-    Generators.copyLintAnnotations(metadata.element(), builder);
-
-    metadata.baseElement().getTypeParameters().stream()
-        .map(TypeVariableName::get)
-        .forEachOrdered(builder::addTypeVariable);
-
-    Generators.addComponentOverride(metadata, builder);
-
-    Generators.addInjectionMethods(metadata, builder);
-
-    ElementFilter.constructorsIn(metadata.baseElement().getEnclosedElements()).stream()
-        .filter(this::isConstructorVisibleToGeneratedClass)
-        .forEach(constructor -> builder.addMethod(constructorMethod(constructor)));
-
-    JavaFile.builder(generatedClassName.packageName(), builder.build())
-        .build()
-        .writeTo(env.getFiler());
-  }
-
-  private boolean isConstructorVisibleToGeneratedClass(ExecutableElement constructorElement) {
-    if (Visibility.ofElement(constructorElement) == Visibility.DEFAULT
-        && !isInOurPackage(constructorElement)) {
-      return false;
-    } else if (Visibility.ofElement(constructorElement) == Visibility.PRIVATE) {
-      return false;
-    }
-
-    // We extend the base class, so both protected and public methods are always accessible.
-    return true;
-  }
-
-  /**
-   * Returns a pass-through constructor matching the base class's provided constructorElement. The
-   * generated constructor simply calls super(), then inject().
-   *
-   * <p>Eg
-   *
-   * <pre>
-   *   Hilt_$CLASS(Context context, ...) {
-   *     super(context, ...);
-   *     inject();
-   *   }
-   * </pre>
-   */
-  private MethodSpec constructorMethod(ExecutableElement constructorElement) {
-    MethodSpec.Builder constructor =
-        Generators.copyConstructor(constructorElement).toBuilder();
-
-    if (isRestrictedApiConstructor(constructorElement)) {
-      // 4 parameter constructors are only available on @TargetApi(21).
-      constructor.addAnnotation(
-          AnnotationSpec.builder(AndroidClassNames.TARGET_API).addMember("value", "21").build());
-    }
-
-    constructor.addStatement("inject()");
-
-    return constructor.build();
-  }
-
-  private boolean isRestrictedApiConstructor(ExecutableElement constructor) {
-    if (constructor.getParameters().size() != 4) {
-      return false;
-    }
-
-    List<? extends VariableElement> constructorParams = constructor.getParameters();
-    for (int i = 0; i < constructorParams.size(); i++) {
-      TypeMirror type = constructorParams.get(i).asType();
-      Element element = env.getTypeUtils().asElement(type);
-      switch (i) {
-        case 0:
-          if (!isFirstRestrictedParameter(element)) {
-            return false;
-          }
-          break;
-        case 1:
-          if (!isSecondRestrictedParameter(element)) {
-            return false;
-          }
-          break;
-        case 2:
-          if (!isThirdRestrictedParameter(type)) {
-            return false;
-          }
-          break;
-        case 3:
-          if (!isFourthRestrictedParameter(type)) {
-            return false;
-          }
-          break;
-        default:
-          return false;
-      }
-    }
-
-    return true;
-  }
-
-  private static boolean isFourthRestrictedParameter(TypeMirror type) {
-    return type.getKind().isPrimitive()
-        && Processors.getPrimitiveType(type).getKind() == TypeKind.INT;
-  }
-
-  private static boolean isThirdRestrictedParameter(TypeMirror type) {
-    return type.getKind().isPrimitive()
-        && Processors.getPrimitiveType(type).getKind() == TypeKind.INT;
-  }
-
-  private static boolean isSecondRestrictedParameter(Element element) {
-    return element instanceof TypeElement
-        && Processors.isAssignableFrom(
-            MoreElements.asType(element), AndroidClassNames.ATTRIBUTE_SET);
-  }
-
-  private static boolean isFirstRestrictedParameter(Element element) {
-    return element instanceof TypeElement
-        && Processors.isAssignableFrom(MoreElements.asType(element), AndroidClassNames.CONTEXT);
-  }
-
-  private boolean isInOurPackage(ExecutableElement constructorElement) {
-    return MoreElements.getPackage(constructorElement)
-        .equals(MoreElements.getPackage(metadata.element()));
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/bindvalue/BUILD b/java/dagger/hilt/android/processor/internal/bindvalue/BUILD
deleted file mode 100644
index cbc51b3..0000000
--- a/java/dagger/hilt/android/processor/internal/bindvalue/BUILD
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (C) 2020 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.
-# Description:
-#   Hilt android library for binding values in test processors.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "bind_value_processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.android.processor.internal.bindvalue.BindValueProcessor",
-    deps = [
-        ":bind_value_processor_lib",
-    ],
-)
-
-java_library(
-    name = "bind_value_processor_lib",
-    srcs = [
-        "BindValueGenerator.java",
-        "BindValueMetadata.java",
-        "BindValueProcessor.java",
-    ],
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:components",
-        "//java/dagger/hilt/processor/internal:kotlin",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/jsr250_annotations",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueGenerator.java b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueGenerator.java
deleted file mode 100644
index 108a15d..0000000
--- a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueGenerator.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.bindvalue;
-
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static java.util.Comparator.comparing;
-
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.android.processor.internal.bindvalue.BindValueMetadata.BindValueElement;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Components;
-import dagger.hilt.processor.internal.Processors;
-import dagger.multibindings.ElementsIntoSet;
-import dagger.multibindings.IntoMap;
-import dagger.multibindings.IntoSet;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/**
- * Generates a SINGLETON module for all {@code BindValue} annotated fields in a test class.
- */
-final class BindValueGenerator {
-  private static final String SUFFIX = "_BindValueModule";
-
-  private final ProcessingEnvironment env;
-  private final BindValueMetadata metadata;
-  private final ClassName testClassName;
-  private final ClassName className;
-
-  BindValueGenerator(ProcessingEnvironment env, BindValueMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-    testClassName = ClassName.get(metadata.testElement());
-    className = Processors.append(testClassName, SUFFIX);
-  }
-
-  //  @Module
-  //  @InstallIn(SingletonComponent.class)
-  //  public final class FooTest_BindValueModule {
-  //     // providesMethods ...
-  //  }
-  void generate() throws IOException {
-    TypeSpec.Builder builder =
-        TypeSpec.classBuilder(className)
-            .addOriginatingElement(metadata.testElement())
-            .addAnnotation(Processors.getOriginatingElementAnnotation(metadata.testElement()))
-            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-            .addAnnotation(Module.class)
-            .addAnnotation(
-                Components.getInstallInAnnotationSpec(
-                    ImmutableSet.of(ClassNames.SINGLETON_COMPONENT)))
-            .addMethod(providesTestMethod());
-
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-
-    metadata.bindValueElements().stream()
-        .map(this::providesMethod)
-        .sorted(comparing(MethodSpec::toString))
-        .forEachOrdered(builder::addMethod);
-
-    JavaFile.builder(className.packageName(), builder.build())
-        .build()
-        .writeTo(env.getFiler());
-  }
-
-  // @Provides
-  // static FooTest providesFooTest(@ApplicationContext Context context) {
-  //   return (FooTest)
-  //       ((TestApplicationComponentManager)
-  //           ((TestApplicationComponentManagerHolder) context).componentManager())
-  //               .getTestInstance();
-  // }
-  private MethodSpec providesTestMethod() {
-    String methodName = "provides" + testClassName.simpleName();
-    MethodSpec.Builder builder =
-        MethodSpec.methodBuilder(methodName)
-            .addAnnotation(Provides.class)
-            .addModifiers(Modifier.STATIC)
-            .addParameter(
-                ParameterSpec.builder(ClassNames.CONTEXT, "context")
-                    .addAnnotation(ClassNames.APPLICATION_CONTEXT)
-                    .build())
-            .returns(testClassName)
-            .addStatement(
-                "return ($T) (($T) (($T) context).componentManager()).getTestInstance()",
-                testClassName,
-                ClassNames.TEST_APPLICATION_COMPONENT_MANAGER,
-                ClassNames.TEST_APPLICATION_COMPONENT_MANAGER_HOLDER);
-    return builder.build();
-  }
-
-  // @Provides
-  // @BarQualifier
-  // static Bar providesBarQualifierBar(FooTest test) {
-  //   return test.bar;
-  // }
-  private MethodSpec providesMethod(BindValueElement bindValue) {
-    // We only allow fields in the Test class, which should have unique variable names.
-    String methodName = "provides"
-        + LOWER_CAMEL.to(UPPER_CAMEL, bindValue.variableElement().getSimpleName().toString());
-    MethodSpec.Builder builder =
-        MethodSpec.methodBuilder(methodName)
-            .addAnnotation(Provides.class)
-            .addModifiers(Modifier.STATIC)
-            .returns(ClassName.get(bindValue.variableElement().asType()));
-
-    if (bindValue.variableElement().getModifiers().contains(Modifier.STATIC)) {
-      builder.addStatement(
-          "return $T.$L", testClassName, bindValue.variableElement().getSimpleName());
-    } else {
-      builder
-          .addParameter(testClassName, "test")
-          .addStatement(
-              "return $L",
-              bindValue.getterElement().isPresent()
-                  ? CodeBlock.of("test.$L()", bindValue.getterElement().get().getSimpleName())
-                  : CodeBlock.of("test.$L", bindValue.variableElement().getSimpleName()));
-    }
-
-    ClassName annotationClassName = bindValue.annotationName();
-    if (BindValueMetadata.BIND_VALUE_INTO_MAP_ANNOTATIONS.contains(annotationClassName)) {
-      builder.addAnnotation(IntoMap.class);
-      // It is safe to call get() on the Optional<AnnotationMirror> returned by mapKey()
-      // because a @BindValueIntoMap is required to have one and is checked in
-      // BindValueMetadata.BindValueElement.create().
-      builder.addAnnotation(AnnotationSpec.get(bindValue.mapKey().get()));
-    } else if (BindValueMetadata.BIND_VALUE_INTO_SET_ANNOTATIONS.contains(annotationClassName)) {
-      builder.addAnnotation(IntoSet.class);
-    } else if (BindValueMetadata.BIND_ELEMENTS_INTO_SET_ANNOTATIONS.contains(annotationClassName)) {
-      builder.addAnnotation(ElementsIntoSet.class);
-    }
-    bindValue.qualifier().ifPresent(q -> builder.addAnnotation(AnnotationSpec.get(q)));
-    return builder.build();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java
deleted file mode 100644
index bf50288..0000000
--- a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.bindvalue;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.KotlinMetadataUtils;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import java.util.Collection;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-
-/**
- * Represents metadata for a test class that has {@code BindValue} fields.
- */
-@AutoValue
-abstract class BindValueMetadata {
-  static final ImmutableSet<ClassName> BIND_VALUE_ANNOTATIONS =
-      ImmutableSet.of(
-          ClassNames.ANDROID_BIND_VALUE);
-  static final ImmutableSet<ClassName> BIND_VALUE_INTO_SET_ANNOTATIONS =
-      ImmutableSet.of(
-          ClassNames.ANDROID_BIND_VALUE_INTO_SET);
-  static final ImmutableSet<ClassName> BIND_ELEMENTS_INTO_SET_ANNOTATIONS =
-      ImmutableSet.of(
-          ClassNames.ANDROID_BIND_ELEMENTS_INTO_SET);
-  static final ImmutableSet<ClassName> BIND_VALUE_INTO_MAP_ANNOTATIONS =
-      ImmutableSet.of(
-          ClassNames.ANDROID_BIND_VALUE_INTO_MAP);
-
-  /** @return the {@code TestRoot} annotated class's name. */
-  abstract TypeElement testElement();
-
-  /** @return a {@link ImmutableSet} of elements annotated with @BindValue. */
-  abstract ImmutableSet<BindValueElement> bindValueElements();
-
-  /** @return a new BindValueMetadata instance. */
-  static BindValueMetadata create(TypeElement testElement, Collection<Element> bindValueElements) {
-
-    ImmutableSet.Builder<BindValueElement> elements = ImmutableSet.builder();
-    for (Element element : bindValueElements) {
-      elements.add(BindValueElement.create(element));
-    }
-
-    return new AutoValue_BindValueMetadata(testElement, elements.build());
-  }
-
-  @AutoValue
-  abstract static class BindValueElement {
-    abstract VariableElement variableElement();
-
-    abstract ClassName annotationName();
-
-    abstract Optional<AnnotationMirror> qualifier();
-
-    abstract Optional<AnnotationMirror> mapKey();
-
-    abstract Optional<ExecutableElement> getterElement();
-
-    static BindValueElement create(Element element) {
-      ImmutableList<ClassName> bindValues = BindValueProcessor.getBindValueAnnotations(element);
-      ProcessorErrors.checkState(
-          bindValues.size() == 1,
-          element,
-          "Fields can be annotated with only one of @BindValue, @BindValueIntoMap,"
-              + " @BindElementsIntoSet, @BindValueIntoSet. Found: %s",
-          bindValues.stream().map(m -> "@" + m.simpleName()).collect(toImmutableList()));
-      ClassName annotationClassName = bindValues.get(0);
-
-      ProcessorErrors.checkState(
-          element.getKind() == ElementKind.FIELD,
-          element,
-          "@%s can only be used with fields. Found: %s",
-          annotationClassName.simpleName(),
-          element);
-
-      KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
-      Optional<ExecutableElement> propertyGetter =
-          metadataUtil.hasMetadata(element)
-              ? metadataUtil.getPropertyGetter(MoreElements.asVariable(element))
-              : Optional.empty();
-      if (propertyGetter.isPresent()) {
-        ProcessorErrors.checkState(
-            !propertyGetter.get().getModifiers().contains(Modifier.PRIVATE),
-            element,
-            "@%s field getter cannot be private. Found: %s",
-            annotationClassName.simpleName(),
-            element);
-      } else {
-        ProcessorErrors.checkState(
-            !element.getModifiers().contains(Modifier.PRIVATE),
-            element,
-            "@%s fields cannot be private. Found: %s",
-            annotationClassName.simpleName(),
-            element);
-      }
-
-      ProcessorErrors.checkState(
-          !Processors.hasAnnotation(element, Inject.class),
-          element,
-          "@%s fields cannot be used with @Inject annotation. Found %s",
-          annotationClassName.simpleName(),
-          element);
-
-      ImmutableList<AnnotationMirror> qualifiers = Processors.getQualifierAnnotations(element);
-      ProcessorErrors.checkState(
-          qualifiers.size() <= 1,
-          element,
-          "@%s fields cannot have more than one qualifier. Found %s",
-          annotationClassName.simpleName(),
-          qualifiers);
-
-      ImmutableList<AnnotationMirror> mapKeys = Processors.getMapKeyAnnotations(element);
-      Optional<AnnotationMirror> optionalMapKeys;
-      if (BIND_VALUE_INTO_MAP_ANNOTATIONS.contains(annotationClassName)) {
-        ProcessorErrors.checkState(
-            mapKeys.size() == 1,
-            element,
-            "@BindValueIntoMap fields must have exactly one @MapKey. Found %s",
-            mapKeys);
-        optionalMapKeys = Optional.of(mapKeys.get(0));
-      } else {
-        ProcessorErrors.checkState(
-            mapKeys.isEmpty(),
-            element,
-            "@MapKey can only be used on @BindValueIntoMap fields, not @%s fields",
-            annotationClassName.simpleName());
-        optionalMapKeys = Optional.empty();
-      }
-
-      ImmutableList<AnnotationMirror> scopes = Processors.getScopeAnnotations(element);
-      ProcessorErrors.checkState(
-          scopes.isEmpty(),
-          element,
-          "@%s fields cannot be scoped. Found %s",
-          annotationClassName.simpleName(),
-          scopes);
-
-      return new AutoValue_BindValueMetadata_BindValueElement(
-          (VariableElement) element,
-          annotationClassName,
-          qualifiers.isEmpty()
-              ? Optional.<AnnotationMirror>empty()
-              : Optional.<AnnotationMirror>of(qualifiers.get(0)),
-          optionalMapKeys,
-          propertyGetter);
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueProcessor.java b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueProcessor.java
deleted file mode 100644
index 060b077..0000000
--- a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueProcessor.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.bindvalue;
-
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.TypeName;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import dagger.internal.codegen.extension.DaggerStreams;
-import java.util.Collection;
-import java.util.Map;
-import javax.annotation.processing.Processor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/** Provides a test's @BindValue fields to the SINGLETON component. */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class BindValueProcessor extends BaseProcessor {
-
-  private static final ImmutableSet<ClassName> SUPPORTED_ANNOTATIONS =
-      ImmutableSet.<ClassName>builder()
-          .addAll(BindValueMetadata.BIND_VALUE_ANNOTATIONS)
-          .addAll(BindValueMetadata.BIND_VALUE_INTO_SET_ANNOTATIONS)
-          .addAll(BindValueMetadata.BIND_ELEMENTS_INTO_SET_ANNOTATIONS)
-          .addAll(BindValueMetadata.BIND_VALUE_INTO_MAP_ANNOTATIONS)
-          .build();
-
-  private final Multimap<TypeElement, Element> testRootMap = ArrayListMultimap.create();
-
-  @Override
-  public ImmutableSet<String> getSupportedAnnotationTypes() {
-    return SUPPORTED_ANNOTATIONS.stream()
-        .map(TypeName::toString)
-        .collect(DaggerStreams.toImmutableSet());
-  }
-
-  @Override
-  protected void preRoundProcess(RoundEnvironment roundEnv) {
-    testRootMap.clear();
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    ClassName annotationClassName = ClassName.get(annotation);
-    Element enclosingElement = element.getEnclosingElement();
-    // Restrict BindValue to the direct test class (e.g. not allowed in a base test class) because
-    // otherwise generated BindValue modules from the base class will not associate with the
-    // correct test class. This would make the modules apply globally which would be a weird
-    // difference since just moving a declaration to the parent would change whether the module is
-    // limited to the test that declares it to global.
-    ProcessorErrors.checkState(
-        enclosingElement.getKind() == ElementKind.CLASS
-            && (Processors.hasAnnotation(enclosingElement, ClassNames.HILT_ANDROID_TEST)
-            ),
-        enclosingElement,
-        "@%s can only be used within a class annotated with "
-            + "@HiltAndroidTest. Found: %s",
-        annotationClassName.simpleName(),
-        enclosingElement);
-
-    testRootMap.put(MoreElements.asType(enclosingElement), element);
-  }
-
-  @Override
-  public void postRoundProcess(RoundEnvironment roundEnvironment) throws Exception {
-    // Generate a module for each testing class with a @BindValue field.
-    for (Map.Entry<TypeElement, Collection<Element>> e : testRootMap.asMap().entrySet()) {
-      BindValueMetadata metadata = BindValueMetadata.create(e.getKey(), e.getValue());
-      new BindValueGenerator(getProcessingEnv(), metadata).generate();
-    }
-  }
-
-  static ImmutableList<ClassName> getBindValueAnnotations(Element element) {
-    ImmutableList.Builder<ClassName> builder = ImmutableList.builder();
-    for (AnnotationMirror annotation : element.getAnnotationMirrors()) {
-      TypeName tn = AnnotationSpec.get(annotation).type;
-      if (SUPPORTED_ANNOTATIONS.contains(tn)) {
-        builder.add((ClassName) tn); // the cast is checked by .contains()
-      }
-    }
-    return builder.build();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/customtestapplication/BUILD b/java/dagger/hilt/android/processor/internal/customtestapplication/BUILD
deleted file mode 100644
index e9721d5..0000000
--- a/java/dagger/hilt/android/processor/internal/customtestapplication/BUILD
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   A processor for @dagger.hilt.android.testing.CustomTestApplication.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.android.processor.internal.customtestapplication.CustomTestApplicationProcessor",
-    deps = [":processor_lib"],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "CustomTestApplicationGenerator.java",
-        "CustomTestApplicationMetadata.java",
-        "CustomTestApplicationProcessor.java",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationGenerator.java b/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationGenerator.java
deleted file mode 100644
index 51b7ef4..0000000
--- a/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationGenerator.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.customtestapplication;
-
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/**
- * Generates an Android Application that holds the Singleton component.
- */
-final class CustomTestApplicationGenerator {
-  private static final ParameterSpec COMPONENT_MANAGER =
-      ParameterSpec.builder(ClassNames.TEST_APPLICATION_COMPONENT_MANAGER, "componentManager")
-          .build();
-
-  private final ProcessingEnvironment processingEnv;
-  private final CustomTestApplicationMetadata metadata;
-
-  public CustomTestApplicationGenerator(
-      ProcessingEnvironment processingEnv, CustomTestApplicationMetadata metadata) {
-    this.processingEnv = processingEnv;
-    this.metadata = metadata;
-  }
-
-  public void generate() throws IOException {
-    TypeSpec.Builder generator =
-        TypeSpec.classBuilder(metadata.appName())
-            .addOriginatingElement(metadata.element())
-            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-            .superclass(metadata.baseAppName())
-            .addSuperinterface(
-                ParameterizedTypeName.get(ClassNames.GENERATED_COMPONENT_MANAGER, TypeName.OBJECT))
-            .addSuperinterface(ClassNames.TEST_APPLICATION_COMPONENT_MANAGER_HOLDER)
-            .addField(getComponentManagerField())
-            .addMethod(getAttachBaseContextMethod())
-            .addMethod(getComponentManagerMethod())
-            .addMethod(getComponentMethod());
-
-    Processors.addGeneratedAnnotation(
-        generator, processingEnv, CustomTestApplicationProcessor.class);
-
-    JavaFile.builder(metadata.appName().packageName(), generator.build())
-        .build()
-        .writeTo(processingEnv.getFiler());
-  }
-
-  // Initialize this in attachBaseContext to not pull it into the main dex.
-  /** private TestApplicationComponentManager componentManager; */
-  private static FieldSpec getComponentManagerField() {
-    return FieldSpec.builder(COMPONENT_MANAGER.type, COMPONENT_MANAGER.name, Modifier.PRIVATE)
-        .build();
-  }
-
-  /**
-   * Initializes application fields. These fields are initialized in attachBaseContext to avoid
-   * potential multidexing issues.
-   *
-   * <pre><code>
-   * {@literal @Override} protected void attachBaseContext(Context base) {
-   *   super.attachBaseContext(base);
-   *   componentManager = new TestApplicationComponentManager(this);
-   * }
-   * </code></pre>
-   */
-  private static MethodSpec getAttachBaseContextMethod() {
-    return MethodSpec.methodBuilder("attachBaseContext")
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PROTECTED, Modifier.FINAL)
-        .addParameter(ClassNames.CONTEXT, "base")
-        .addStatement("super.attachBaseContext(base)")
-        .addStatement("$N = new $T(this)", COMPONENT_MANAGER, COMPONENT_MANAGER.type)
-        .build();
-  }
-
-  private static MethodSpec getComponentMethod() {
-    return MethodSpec.methodBuilder("generatedComponent")
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-        .returns(TypeName.OBJECT)
-        .addStatement("return $N.generatedComponent()", COMPONENT_MANAGER)
-        .build();
-  }
-
-  private static MethodSpec getComponentManagerMethod() {
-    return MethodSpec.methodBuilder("componentManager")
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-        .returns(TypeName.OBJECT)
-        .addStatement("return $N", COMPONENT_MANAGER)
-        .build();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationMetadata.java b/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationMetadata.java
deleted file mode 100644
index de8e3f7..0000000
--- a/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationMetadata.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.customtestapplication;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.Elements;
-
-/** Stores the metadata for a custom base test application. */
-@AutoValue
-abstract class CustomTestApplicationMetadata {
-  /** Returns the annotated element. */
-  abstract TypeElement element();
-
-  /** Returns the name of the base application. */
-  abstract ClassName baseAppName();
-
-  /** Returns the name of the generated application */
-  ClassName appName() {
-    return Processors.append(
-        Processors.getEnclosedClassName(ClassName.get(element())), "_Application");
-  }
-
-  static CustomTestApplicationMetadata of(Element element, Elements elements) {
-    Preconditions.checkState(
-        Processors.hasAnnotation(element, ClassNames.CUSTOM_TEST_APPLICATION),
-        "The given element, %s, is not annotated with @%s.",
-        element,
-        ClassNames.CUSTOM_TEST_APPLICATION.simpleName());
-
-    ProcessorErrors.checkState(
-        MoreElements.isType(element),
-        element,
-        "@%s should only be used on classes or interfaces but found: %s",
-        ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
-        element);
-
-    TypeElement baseAppElement = getBaseElement(element, elements);
-
-    return new AutoValue_CustomTestApplicationMetadata(
-        MoreElements.asType(element), ClassName.get(baseAppElement));
-  }
-
-  private static TypeElement getBaseElement(Element element, Elements elements) {
-    TypeElement baseElement =
-        Processors.getAnnotationClassValue(
-            elements,
-            Processors.getAnnotationMirror(element, ClassNames.CUSTOM_TEST_APPLICATION),
-            "value");
-
-    TypeElement baseSuperclassElement = baseElement;
-    while (!baseSuperclassElement.getSuperclass().getKind().equals(TypeKind.NONE)) {
-      ProcessorErrors.checkState(
-          !Processors.hasAnnotation(baseSuperclassElement, ClassNames.HILT_ANDROID_APP),
-          element,
-          "@%s value cannot be annotated with @%s. Found: %s",
-          ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
-          ClassNames.HILT_ANDROID_APP.simpleName(),
-          baseSuperclassElement);
-
-      ImmutableList<VariableElement> injectFields =
-          ElementFilter.fieldsIn(baseSuperclassElement.getEnclosedElements()).stream()
-              .filter(field -> Processors.hasAnnotation(field, ClassNames.INJECT))
-              .collect(toImmutableList());
-      ProcessorErrors.checkState(
-          injectFields.isEmpty(),
-          element,
-          "@%s does not support application classes (or super classes) with @Inject fields. Found "
-              + "%s with @Inject fields %s.",
-          ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
-          baseSuperclassElement,
-          injectFields);
-
-      ImmutableList<ExecutableElement> injectMethods =
-          ElementFilter.methodsIn(baseSuperclassElement.getEnclosedElements()).stream()
-              .filter(method -> Processors.hasAnnotation(method, ClassNames.INJECT))
-              .collect(toImmutableList());
-      ProcessorErrors.checkState(
-          injectMethods.isEmpty(),
-          element,
-          "@%s does not support application classes (or super classes) with @Inject methods. Found "
-              + "%s with @Inject methods %s.",
-          ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
-          baseSuperclassElement,
-          injectMethods);
-
-      ImmutableList<ExecutableElement> injectConstructors =
-          ElementFilter.constructorsIn(baseSuperclassElement.getEnclosedElements()).stream()
-              .filter(method -> Processors.hasAnnotation(method, ClassNames.INJECT))
-              .collect(toImmutableList());
-      ProcessorErrors.checkState(
-          injectConstructors.isEmpty(),
-          element,
-          "@%s does not support application classes (or super classes) with @Inject constructors. "
-              + "Found %s with @Inject constructors %s.",
-          ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
-          baseSuperclassElement,
-          injectConstructors);
-
-      baseSuperclassElement = MoreTypes.asTypeElement(baseSuperclassElement.getSuperclass());
-    }
-
-    // We check this last because if the base type is a @HiltAndroidApp we'd accidentally fail
-    // with this message instead of the one above when the superclass hasn't yet been generated.
-    ProcessorErrors.checkState(
-        Processors.isAssignableFrom(baseElement, ClassNames.APPLICATION),
-        element,
-        "@%s value should be an instance of %s. Found: %s",
-        ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
-        ClassNames.APPLICATION,
-        baseElement);
-
-    return baseElement;
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationProcessor.java b/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationProcessor.java
deleted file mode 100644
index fd1a6c8..0000000
--- a/java/dagger/hilt/android/processor/internal/customtestapplication/CustomTestApplicationProcessor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.customtestapplication;
-
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableSet;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/** Processes usages of {@link dagger.hilt.android.testing.CustomTestApplication}. */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class CustomTestApplicationProcessor extends BaseProcessor {
-
-  @Override
-  public ImmutableSet<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.of(ClassNames.CUSTOM_TEST_APPLICATION.toString());
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    CustomTestApplicationMetadata metadata =
-        CustomTestApplicationMetadata.of(element, getElementUtils());
-    new CustomTestApplicationGenerator(getProcessingEnv(), metadata).generate();
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/uninstallmodules/BUILD b/java/dagger/hilt/android/processor/internal/uninstallmodules/BUILD
deleted file mode 100644
index 73c4606..0000000
--- a/java/dagger/hilt/android/processor/internal/uninstallmodules/BUILD
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   A processor for @dagger.hilt.android.testing.UninstallModules.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.android.processor.internal.uninstallmodules.UninstallModulesProcessor",
-    deps = [":processor_lib"],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "UninstallModulesProcessor.java",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/processor/internal/uninstallmodules/UninstallModulesProcessor.java b/java/dagger/hilt/android/processor/internal/uninstallmodules/UninstallModulesProcessor.java
deleted file mode 100644
index e92f0f0..0000000
--- a/java/dagger/hilt/android/processor/internal/uninstallmodules/UninstallModulesProcessor.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.uninstallmodules;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import java.util.Set;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/** Validates {@link dagger.hilt.android.testing.UninstallModules} usages. */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class UninstallModulesProcessor extends BaseProcessor {
-
-  @Override
-  public Set<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.of(ClassNames.IGNORE_MODULES.toString());
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    // TODO(bcorso): Consider using RootType to check this?
-    // TODO(bcorso): Loosen this restriction to allow defining sets of ignored modules in libraries.
-    ProcessorErrors.checkState(
-        MoreElements.isType(element)
-            && Processors.hasAnnotation(element, ClassNames.HILT_ANDROID_TEST),
-        element,
-        "@%s should only be used on test classes annotated with @%s, but found: %s",
-        annotation.getSimpleName(),
-        ClassNames.HILT_ANDROID_TEST.simpleName(),
-        element);
-
-    ImmutableList<TypeElement> invalidModules =
-        Processors.getAnnotationClassValues(
-                getElementUtils(),
-                Processors.getAnnotationMirror(element, ClassNames.IGNORE_MODULES),
-                "value")
-            .stream()
-            .filter(
-                module ->
-                    !(Processors.hasAnnotation(module, ClassNames.MODULE)
-                        && Processors.hasAnnotation(module, ClassNames.INSTALL_IN)))
-            .collect(toImmutableList());
-
-    ProcessorErrors.checkState(
-        invalidModules.isEmpty(),
-        // TODO(b/152801981): Point to the annotation value rather than the annotated element.
-        element,
-        "@%s should only include modules annotated with both @Module and @InstallIn, but found: "
-          + "%s.",
-        annotation.getSimpleName(),
-        invalidModules);
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/BUILD b/java/dagger/hilt/android/processor/internal/viewmodel/BUILD
deleted file mode 100644
index b45925f..0000000
--- a/java/dagger/hilt/android/processor/internal/viewmodel/BUILD
+++ /dev/null
@@ -1,84 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   ViewModelInject processor.
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.android.processor.internal.viewmodel.ViewModelProcessor",
-    deps = [":processor_lib"],
-)
-
-kt_jvm_library(
-    name = "processor_lib",
-    srcs = [
-        "ViewModelMetadata.kt",
-        "ViewModelModuleGenerator.kt",
-        "ViewModelProcessor.kt",
-    ],
-    deps = [
-        "//java/dagger/hilt/android/processor/internal:android_classnames",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_plugin(
-    name = "validation_plugin",
-    deps = [":validation_plugin_lib"],
-)
-
-kt_jvm_library(
-    name = "validation_plugin_lib",
-    srcs = [
-        "ViewModelValidationPlugin.kt",
-    ],
-    deps = [
-        "//:spi",
-        "//java/dagger/hilt/android/processor/internal:android_classnames",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:graph",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-# See: https://github.com/bazelbuild/rules_kotlin/issues/324
-alias(
-    name = "libprocessor_lib-src.jar",
-    actual = ":processor_lib-sources.jar",
-)
-
-alias(
-    name = "libvalidation_plugin_lib-src.jar",
-    actual = ":validation_plugin_lib-sources.jar",
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelMetadata.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelMetadata.kt
deleted file mode 100644
index 789fbfe..0000000
--- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelMetadata.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.viewmodel
-
-import com.google.auto.common.MoreElements
-import com.squareup.javapoet.ClassName
-import dagger.hilt.android.processor.internal.AndroidClassNames
-import dagger.hilt.processor.internal.ClassNames
-import dagger.hilt.processor.internal.ProcessorErrors
-import dagger.hilt.processor.internal.Processors
-import javax.annotation.processing.ProcessingEnvironment
-import javax.lang.model.element.Modifier
-import javax.lang.model.element.NestingKind
-import javax.lang.model.element.TypeElement
-import javax.lang.model.util.ElementFilter
-
-/**
- * Data class that represents a Hilt injected ViewModel
- */
-internal class ViewModelMetadata private constructor(
-  val typeElement: TypeElement
-) {
-  val className = ClassName.get(typeElement)
-
-  val modulesClassName = ClassName.get(
-    MoreElements.getPackage(typeElement).qualifiedName.toString(),
-    "${className.simpleNames().joinToString("_")}_HiltModules"
-  )
-
-  companion object {
-    internal fun create(
-      processingEnv: ProcessingEnvironment,
-      typeElement: TypeElement,
-    ): ViewModelMetadata? {
-      val types = processingEnv.typeUtils
-      val elements = processingEnv.elementUtils
-
-      ProcessorErrors.checkState(
-        types.isSubtype(
-          typeElement.asType(),
-          elements.getTypeElement(AndroidClassNames.VIEW_MODEL.toString()).asType()
-        ),
-        typeElement,
-        "@HiltViewModel is only supported on types that subclass %s.",
-        AndroidClassNames.VIEW_MODEL
-      )
-
-      ElementFilter.constructorsIn(typeElement.enclosedElements).filter { constructor ->
-        ProcessorErrors.checkState(
-          !Processors.hasAnnotation(constructor, ClassNames.ASSISTED_INJECT),
-          constructor,
-          "ViewModel constructor should be annotated with @Inject instead of @AssistedInject."
-        )
-        Processors.hasAnnotation(constructor, ClassNames.INJECT)
-      }.let { injectConstructors ->
-        ProcessorErrors.checkState(
-          injectConstructors.size == 1,
-          typeElement,
-          "@HiltViewModel annotated class should contain exactly one @Inject " +
-            "annotated constructor."
-        )
-
-        injectConstructors.forEach { constructor ->
-          ProcessorErrors.checkState(
-            !constructor.modifiers.contains(Modifier.PRIVATE),
-            constructor,
-            "@Inject annotated constructors must not be private."
-          )
-        }
-      }
-
-      ProcessorErrors.checkState(
-        typeElement.nestingKind != NestingKind.MEMBER ||
-          typeElement.modifiers.contains(Modifier.STATIC),
-        typeElement,
-        "@HiltViewModel may only be used on inner classes if they are static."
-      )
-
-      Processors.getScopeAnnotations(typeElement).let { scopeAnnotations ->
-        ProcessorErrors.checkState(
-          scopeAnnotations.isEmpty(),
-          typeElement,
-          "@HiltViewModel classes should not be scoped. Found: %s",
-          scopeAnnotations.joinToString()
-        )
-      }
-
-      return ViewModelMetadata(
-        typeElement
-      )
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt
deleted file mode 100644
index 846f7d2..0000000
--- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.viewmodel
-
-import com.google.auto.common.GeneratedAnnotationSpecs
-import com.squareup.javapoet.AnnotationSpec
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.JavaFile
-import com.squareup.javapoet.MethodSpec
-import com.squareup.javapoet.TypeSpec
-import dagger.hilt.android.processor.internal.AndroidClassNames
-import dagger.hilt.processor.internal.ClassNames
-import javax.annotation.processing.ProcessingEnvironment
-import javax.lang.model.SourceVersion
-import javax.lang.model.element.Modifier
-import javax.lang.model.util.Elements
-
-/**
- * Source generator to support Hilt injection of ViewModels.
- *
- * Should generate:
- * ```
- * public final class $_HiltModules {
- *   @Module
- *   @InstallIn(ViewModelComponent.class)
- *   public static abstract class BindsModule {
- *     @Binds
- *     @IntoMap
- *     @StringKey("pkg.$")
- *     @HiltViewModelMap
- *     public abstract ViewModel bind($ vm)
- *   }
- *   @Module
- *   @InstallIn(ActivityRetainedComponent.class)
- *   public static final class KeyModule {
- *     @Provides
- *     @IntoSet
- *     @HiltViewModelMap.KeySet
- *     public static String provide() {
- *      return "pkg.$";
- *     }
- *   }
- * }
- * ```
- */
-internal class ViewModelModuleGenerator(
-  private val processingEnv: ProcessingEnvironment,
-  private val injectedViewModel: ViewModelMetadata
-) {
-  fun generate() {
-    val modulesTypeSpec = TypeSpec.classBuilder(injectedViewModel.modulesClassName)
-      .addOriginatingElement(injectedViewModel.typeElement)
-      .addGeneratedAnnotation(processingEnv.elementUtils, processingEnv.sourceVersion)
-      .addAnnotation(
-        AnnotationSpec.builder(ClassNames.ORIGINATING_ELEMENT)
-          .addMember(
-            "topLevelClass",
-            "$T.class",
-            injectedViewModel.className.topLevelClassName()
-          )
-          .build()
-      )
-      .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-      .addType(getBindsModuleTypeSpec())
-      .addType(getKeyModuleTypeSpec())
-      .addMethod(
-        MethodSpec.constructorBuilder()
-          .addModifiers(Modifier.PRIVATE)
-          .build()
-      )
-      .build()
-    JavaFile.builder(injectedViewModel.modulesClassName.packageName(), modulesTypeSpec)
-      .build()
-      .writeTo(processingEnv.filer)
-  }
-
-  private fun getBindsModuleTypeSpec() = createModuleTypeSpec(
-    className = "BindsModule",
-    component = AndroidClassNames.VIEW_MODEL_COMPONENT
-  )
-    .addModifiers(Modifier.ABSTRACT)
-    .addMethod(getViewModelBindsMethod())
-    .build()
-
-  private fun getViewModelBindsMethod() =
-    MethodSpec.methodBuilder("binds")
-      .addAnnotation(ClassNames.BINDS)
-      .addAnnotation(ClassNames.INTO_MAP)
-      .addAnnotation(
-        AnnotationSpec.builder(ClassNames.STRING_KEY)
-          .addMember("value", S, injectedViewModel.className.reflectionName())
-          .build()
-      )
-      .addAnnotation(AndroidClassNames.HILT_VIEW_MODEL_MAP_QUALIFIER)
-      .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
-      .returns(AndroidClassNames.VIEW_MODEL)
-      .addParameter(injectedViewModel.className, "vm")
-      .build()
-
-  private fun getKeyModuleTypeSpec() = createModuleTypeSpec(
-    className = "KeyModule",
-    component = AndroidClassNames.ACTIVITY_RETAINED_COMPONENT
-  )
-    .addModifiers(Modifier.FINAL)
-    .addMethod(
-      MethodSpec.constructorBuilder()
-        .addModifiers(Modifier.PRIVATE)
-        .build()
-    )
-    .addMethod(getViewModelKeyProvidesMethod())
-    .build()
-
-  private fun getViewModelKeyProvidesMethod() =
-    MethodSpec.methodBuilder("provide")
-      .addAnnotation(ClassNames.PROVIDES)
-      .addAnnotation(ClassNames.INTO_SET)
-      .addAnnotation(AndroidClassNames.HILT_VIEW_MODEL_KEYS_QUALIFIER)
-      .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
-      .returns(String::class.java)
-      .addStatement("return $S", injectedViewModel.className.reflectionName())
-      .build()
-
-  private fun createModuleTypeSpec(className: String, component: ClassName) =
-    TypeSpec.classBuilder(className)
-      .addOriginatingElement(injectedViewModel.typeElement)
-      .addAnnotation(ClassNames.MODULE)
-      .addAnnotation(
-        AnnotationSpec.builder(ClassNames.INSTALL_IN)
-          .addMember("value", "$T.class", component)
-          .build()
-      )
-      .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
-
-  companion object {
-
-    const val L = "\$L"
-    const val T = "\$T"
-    const val N = "\$N"
-    const val S = "\$S"
-    const val W = "\$W"
-
-    private fun TypeSpec.Builder.addGeneratedAnnotation(
-      elements: Elements,
-      sourceVersion: SourceVersion
-    ) = apply {
-      GeneratedAnnotationSpecs.generatedAnnotationSpec(
-        elements,
-        sourceVersion,
-        ViewModelProcessor::class.java
-      ).ifPresent { generatedAnnotation ->
-        addAnnotation(generatedAnnotation)
-      }
-    }
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessor.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessor.kt
deleted file mode 100644
index 97ebe52..0000000
--- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessor.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.viewmodel
-
-import com.google.auto.common.MoreElements
-import com.google.auto.service.AutoService
-import dagger.hilt.android.processor.internal.AndroidClassNames
-import dagger.hilt.processor.internal.BaseProcessor
-import javax.annotation.processing.Processor
-import javax.annotation.processing.RoundEnvironment
-import javax.lang.model.SourceVersion
-import javax.lang.model.element.Element
-import javax.lang.model.element.TypeElement
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType
-
-/**
- * Annotation processor for @ViewModelInject.
- */
-@AutoService(Processor::class)
-@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.ISOLATING)
-class ViewModelProcessor : BaseProcessor() {
-
-  private val parsedElements = mutableSetOf<TypeElement>()
-
-  override fun getSupportedAnnotationTypes() = setOf(
-    AndroidClassNames.HILT_VIEW_MODEL.toString()
-  )
-
-  override fun getSupportedSourceVersion() = SourceVersion.latest()
-
-  override fun processEach(annotation: TypeElement, element: Element) {
-    val typeElement = MoreElements.asType(element)
-    if (parsedElements.add(typeElement)) {
-      ViewModelMetadata.create(
-        processingEnv,
-        typeElement,
-      )?.let { viewModelMetadata ->
-        ViewModelModuleGenerator(
-          processingEnv,
-          viewModelMetadata
-        ).generate()
-      }
-    }
-  }
-
-  override fun postRoundProcess(roundEnv: RoundEnvironment?) {
-    parsedElements.clear()
-  }
-}
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPlugin.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPlugin.kt
deleted file mode 100644
index a8e57dc..0000000
--- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPlugin.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.viewmodel
-
-import com.google.auto.common.MoreTypes.asElement
-import com.google.auto.service.AutoService
-import com.google.common.graph.EndpointPair
-import com.google.common.graph.ImmutableNetwork
-import com.squareup.javapoet.ClassName
-import dagger.hilt.android.processor.internal.AndroidClassNames
-import dagger.hilt.processor.internal.Processors.hasAnnotation
-import dagger.model.Binding
-import dagger.model.BindingGraph
-import dagger.model.BindingGraph.Edge
-import dagger.model.BindingGraph.Node
-import dagger.model.BindingKind
-import dagger.spi.BindingGraphPlugin
-import dagger.spi.DiagnosticReporter
-import javax.tools.Diagnostic.Kind
-
-/**
- * Plugin to validate users do not inject @HiltViewModel classes.
- */
-@AutoService(BindingGraphPlugin::class)
-class ViewModelValidationPlugin : BindingGraphPlugin {
-
-  override fun visitGraph(bindingGraph: BindingGraph, diagnosticReporter: DiagnosticReporter) {
-    if (bindingGraph.rootComponentNode().isSubcomponent()) {
-      // This check does not work with partial graphs since it needs to take into account the source
-      // component.
-      return
-    }
-
-    val network: ImmutableNetwork<Node, Edge> = bindingGraph.network()
-    bindingGraph.dependencyEdges().forEach { edge ->
-      val pair: EndpointPair<Node> = network.incidentNodes(edge)
-      val target: Node = pair.target()
-      val source: Node = pair.source()
-      if (target is Binding &&
-        isHiltViewModelBinding(target) &&
-        !isInternalHiltViewModelUsage(source)
-      ) {
-        diagnosticReporter.reportDependency(
-          Kind.ERROR,
-          edge,
-          "\nInjection of an @HiltViewModel class is prohibited since it does not create a " +
-            "ViewModel instance correctly.\nAccess the ViewModel via the Android APIs " +
-            "(e.g. ViewModelProvider) instead." +
-            "\nInjected ViewModel: ${target.key().type()}\n"
-        )
-      }
-    }
-  }
-
-  private fun isHiltViewModelBinding(target: Binding): Boolean {
-    // Make sure this is from an @Inject constructor rather than an overridden binding like an
-    // @Provides and that the class is annotated with @HiltViewModel.
-    return target.kind() == BindingKind.INJECTION &&
-      hasAnnotation(asElement(target.key().type()), AndroidClassNames.HILT_VIEW_MODEL)
-  }
-
-  private fun isInternalHiltViewModelUsage(source: Node): Boolean {
-    // We expect @HiltViewModel classes to be bound into a map with an @Binds like
-    // @Binds
-    // @IntoMap
-    // @StringKey(...)
-    // @HiltViewModelMap
-    // abstract ViewModel bindViewModel(FooViewModel vm)
-    //
-    // So we check that it is a multibinding contribution with the internal qualifier.
-    // TODO(erichang): Should we check for even more things?
-    return source is Binding &&
-      source.key().qualifier().isPresent() &&
-      ClassName.get(source.key().qualifier().get().getAnnotationType()) ==
-      AndroidClassNames.HILT_VIEW_MODEL_MAP_QUALIFIER &&
-      source.key().multibindingContributionIdentifier().isPresent()
-  }
-}
diff --git a/java/dagger/hilt/android/qualifiers/ActivityContext.java b/java/dagger/hilt/android/qualifiers/ActivityContext.java
deleted file mode 100644
index cfcc40e..0000000
--- a/java/dagger/hilt/android/qualifiers/ActivityContext.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.qualifiers;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import javax.inject.Qualifier;
-
-/** Annotation for a {@code Context} that corresponds to the activity. */
-@Qualifier
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
-public @interface ActivityContext {}
diff --git a/java/dagger/hilt/android/qualifiers/ApplicationContext.java b/java/dagger/hilt/android/qualifiers/ApplicationContext.java
deleted file mode 100644
index 226ef75..0000000
--- a/java/dagger/hilt/android/qualifiers/ApplicationContext.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.qualifiers;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-import javax.inject.Qualifier;
-
-/** Annotation for an Application Context dependency. */
-@Qualifier
-@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
-public @interface ApplicationContext {}
diff --git a/java/dagger/hilt/android/qualifiers/BUILD b/java/dagger/hilt/android/qualifiers/BUILD
deleted file mode 100644
index 26b45ec..0000000
--- a/java/dagger/hilt/android/qualifiers/BUILD
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Hilt Android qualifiers
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "qualifiers",
-    srcs = [
-        "ActivityContext.java",
-        "ApplicationContext.java",
-    ],
-    deps = [
-        ":package_info",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/qualifiers/package-info.java b/java/dagger/hilt/android/qualifiers/package-info.java
deleted file mode 100644
index 2cbd744..0000000
--- a/java/dagger/hilt/android/qualifiers/package-info.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/** This package contains Hilt's built-in Android {@link javax.inject.Qualifier} annotations. */
-package dagger.hilt.android.qualifiers;
diff --git a/java/dagger/hilt/android/scopes/ActivityRetainedScoped.java b/java/dagger/hilt/android/scopes/ActivityRetainedScoped.java
deleted file mode 100644
index c61325d..0000000
--- a/java/dagger/hilt/android/scopes/ActivityRetainedScoped.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.scopes;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import javax.inject.Scope;
-
-/**
- * Scope annotation for bindings that should exist for the life of an activity, surviving
- * configuration.
- */
-@Scope
-@Retention(CLASS)
-public @interface ActivityRetainedScoped {}
diff --git a/java/dagger/hilt/android/scopes/ActivityScoped.java b/java/dagger/hilt/android/scopes/ActivityScoped.java
deleted file mode 100644
index 9f128f7..0000000
--- a/java/dagger/hilt/android/scopes/ActivityScoped.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.scopes;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import javax.inject.Scope;
-
-/**
- * Scope annotation for bindings that should exist for the life of an activity.
- */
-@Scope
-@Retention(CLASS)
-public @interface ActivityScoped {}
diff --git a/java/dagger/hilt/android/scopes/BUILD b/java/dagger/hilt/android/scopes/BUILD
deleted file mode 100644
index e74ac9e..0000000
--- a/java/dagger/hilt/android/scopes/BUILD
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (C) 2020 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(default_visibility = ["//:src"])
-
-# Description:
-# Hilt scopes.
-
-android_library(
-    name = "scopes",
-    srcs = [
-        "ActivityScoped.java",
-        "FragmentScoped.java",
-        "ServiceScoped.java",
-        "ViewScoped.java",
-    ],
-    deps = [
-        ":package_info",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-    ],
-)
-
-android_library(
-    name = "activity_retained_scoped",
-    srcs = ["ActivityRetainedScoped.java"],
-    deps = [
-        ":package_info",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-    ],
-)
-
-android_library(
-    name = "view_model_scoped",
-    srcs = ["ViewModelScoped.java"],
-    deps = [
-        ":package_info",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/scopes/FragmentScoped.java b/java/dagger/hilt/android/scopes/FragmentScoped.java
deleted file mode 100644
index bc6c75e..0000000
--- a/java/dagger/hilt/android/scopes/FragmentScoped.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.scopes;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import javax.inject.Scope;
-
-/**
- * Scope annotation for bindings that should exist for the life of a fragment.
- */
-@Scope
-@Retention(CLASS)
-public @interface FragmentScoped {}
diff --git a/java/dagger/hilt/android/scopes/ServiceScoped.java b/java/dagger/hilt/android/scopes/ServiceScoped.java
deleted file mode 100644
index 84205f2..0000000
--- a/java/dagger/hilt/android/scopes/ServiceScoped.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.scopes;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import javax.inject.Scope;
-
-/**
- * Scope annotation for bindings that should exist for the life of a service.
- */
-@Scope
-@Retention(CLASS)
-public @interface ServiceScoped {}
diff --git a/java/dagger/hilt/android/scopes/ViewModelScoped.java b/java/dagger/hilt/android/scopes/ViewModelScoped.java
deleted file mode 100644
index 8861125..0000000
--- a/java/dagger/hilt/android/scopes/ViewModelScoped.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.scopes;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import javax.inject.Scope;
-
-/**
- * Scope annotation for bindings that should exist for the life of a a single {@link
- * androidx.lifecycle.ViewModel}.
- *
- * <p>Use this scope annotation when you want to define a dependency in the {@link
- * dagger.hilt.android.components.ViewModelComponent} for which a single instance will be provided
- * across all other dependencies for a single {@link
- * dagger.hilt.android.lifecycle.HiltViewModel}-annotated {@code ViewModel}. Other {@code
- * ViewModel}s that request the scoped dependency will receive a different instance. For sharing the
- * same instance of a dependency across all {@code ViewModel}s use a scope from one of the parent
- * components of {@code dagger.hilt.android.components.ViewModelComponent}, such as {@link
- * javax.inject.Singleton} or {@link dagger.hilt.android.scopes.ActivityRetainedScoped}.
- *
- * <p>For example:
- *
- * <pre>
- * &#64;Module
- * &#64;InstallIn(ViewModelComponent.class)
- * public final class ViewModelMovieModule {
- *     &#64;Provides
- *     &#64;ViewModelScoped
- *     public static MovieRepository provideRepo(SavedStateHandle handle) {
- *         return new MovieRepository(handle.getString("movie-id"));
- *     }
- * }
- *
- * public final class MovieDetailFetcher {
- *     &#64;Inject MovieDetailFetcher(MovieRepository movieRepo) {
- *         // ...
- *     }
- * }
- *
- * public final class MoviePosterFetcher {
- *     &#64;Inject MoviePosterFetcher(MovieRepository movieRepo) {
- *         // ...
- *     }
- * }
- *
- * &#64;HiltViewModel
- * public class MovieViewModel extends ViewModel {
- *     &#64;Inject
- *     public MovieViewModel(MovieDetailFetcher detailFetcher, MoviePosterFetcher posterFetcher) {
- *         // Both detailFetcher and posterFetcher will contain the same instance of
- *         // the MovieRepository.
- *     }
- * }
- * </pre>
- *
- * @see dagger.hilt.android.lifecycle.HiltViewModel
- * @see dagger.hilt.android.components.ViewModelComponent
- */
-@Scope
-@Retention(RetentionPolicy.CLASS)
-public @interface ViewModelScoped {}
diff --git a/java/dagger/hilt/android/scopes/ViewScoped.java b/java/dagger/hilt/android/scopes/ViewScoped.java
deleted file mode 100644
index abf7c0a..0000000
--- a/java/dagger/hilt/android/scopes/ViewScoped.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.scopes;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import javax.inject.Scope;
-
-/**
- * Scope annotation for bindings that should exist for the life of a View.
- */
-@Scope
-@Retention(CLASS)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface ViewScoped {}
diff --git a/java/dagger/hilt/android/scopes/package-info.java b/java/dagger/hilt/android/scopes/package-info.java
deleted file mode 100644
index 6f8f989..0000000
--- a/java/dagger/hilt/android/scopes/package-info.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains Hilt's built-in Android {@link javax.inject.Scope} annotations.
- *
- * @see <a href="https://dagger.dev/hilt/components.md#component-lifetimes">Component Lifetimes</a>
- */
-package dagger.hilt.android.scopes;
diff --git a/java/dagger/hilt/android/testing/AndroidManifest.xml b/java/dagger/hilt/android/testing/AndroidManifest.xml
deleted file mode 100644
index 26ec669..0000000
--- a/java/dagger/hilt/android/testing/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
- Copyright (C) 2020 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.testing">
-  <uses-sdk android:minSdkVersion="14" />
-</manifest>
diff --git a/java/dagger/hilt/android/testing/BUILD b/java/dagger/hilt/android/testing/BUILD
deleted file mode 100644
index 47db287..0000000
--- a/java/dagger/hilt/android/testing/BUILD
+++ /dev/null
@@ -1,238 +0,0 @@
-# Copyright (C) 2020 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.
-# Description:
-#   Testing libraries for Hilt Android.
-
-load("//:build_defs.bzl", "POM_VERSION_ALPHA")
-load("//tools:maven.bzl", "gen_maven_artifact")
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "custom_test_application",
-    testonly = 1,
-    srcs = ["CustomTestApplication.java"],
-    exported_plugins = [
-        "//java/dagger/hilt/android/processor/internal/customtestapplication:processor",
-    ],
-    exports = [
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager",
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager_holder",
-        "//java/dagger/hilt/internal:component_manager",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-android_library(
-    name = "hilt_android_test",
-    testonly = 1,
-    srcs = ["HiltAndroidTest.java"],
-    exported_plugins = [
-        "//java/dagger/hilt/processor/internal/root:plugin",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:plugin",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:validation_plugin",
-    ],
-    exports = [
-        ":hilt_android_rule",
-        ":hilt_test_application",
-        ":on_component_ready_runner",
-        ":package_info",
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/internal/builders",
-        "//java/dagger/hilt/android/internal/managers",
-        "//java/dagger/hilt/android/internal/modules",
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager",
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager_holder",
-        "//java/dagger/hilt/android/internal/testing:test_injector",
-        "//java/dagger/hilt/android/scopes",
-        "//java/dagger/hilt/internal:component_entry_point",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:generated_entry_point",
-        "//java/dagger/hilt/internal:preconditions",
-        "//java/dagger/hilt/migration:disable_install_in_check",
-        "@maven//:androidx_annotation_annotation",
-        "@maven//:androidx_multidex_multidex",
-        "@maven//:androidx_test_core",
-    ],
-    deps = [
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-android_library(
-    name = "hilt_android_rule",
-    testonly = 1,
-    srcs = ["HiltAndroidRule.java"],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt/android/internal/testing:mark_that_rules_ran_rule",
-        "//java/dagger/hilt/internal:preconditions",
-        "@maven//:junit_junit",
-    ],
-)
-
-android_library(
-    name = "hilt_test_application",
-    testonly = 1,
-    srcs = [
-        "HiltTestApplication.java",
-    ],
-    deps = [
-        ":on_component_ready_runner",
-        ":package_info",
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager",
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager_holder",
-        "//java/dagger/hilt/internal:component_manager",
-        "@maven//:androidx_multidex_multidex",
-    ],
-)
-
-android_library(
-    name = "on_component_ready_runner",
-    testonly = 1,
-    srcs = ["OnComponentReadyRunner.java"],
-    deps = [
-        ":package_info",
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:entry_point",
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager_holder",
-        "//java/dagger/hilt/internal:component_manager",
-        "//java/dagger/hilt/internal:preconditions",
-        "@google_bazel_common//third_party/java/auto:value",
-    ],
-)
-
-android_library(
-    name = "uninstall_modules",
-    testonly = 1,
-    srcs = ["UninstallModules.java"],
-    exported_plugins = [
-        "//java/dagger/hilt/android/processor/internal/uninstallmodules:processor",
-    ],
-    deps = [
-        ":package_info",
-    ],
-)
-
-java_library(
-    name = "bind_value",
-    testonly = 1,
-    srcs = [
-        "BindElementsIntoSet.java",
-        "BindValue.java",
-        "BindValueIntoMap.java",
-        "BindValueIntoSet.java",
-    ],
-    exported_plugins = [
-        "//java/dagger/hilt/android/processor/internal/bindvalue:bind_value_processor",
-    ],
-    exports = [
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android/qualifiers",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-    deps = [
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-    ],
-)
-
-android_library(
-    name = "artifact-lib",
-    testonly = 1,
-    tags = ["maven_coordinates=com.google.dagger:hilt-android-testing:" + POM_VERSION_ALPHA],
-    exports = [
-        ":bind_value",
-        ":custom_test_application",
-        ":hilt_android_test",
-        ":package_info",
-        ":uninstall_modules",
-        "//java/dagger/hilt/android:artifact-lib",
-        "//java/dagger/hilt/testing:test_install_in",
-    ],
-)
-
-gen_maven_artifact(
-    name = "artifact",
-    testonly = 1,
-    artifact_coordinates = "com.google.dagger:hilt-android-testing:" + POM_VERSION_ALPHA,
-    artifact_name = "Hilt Android Testing",
-    artifact_target = ":artifact-lib",
-    artifact_target_libs = [
-        "//java/dagger/hilt/android/internal/testing:mark_that_rules_ran_rule",
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager",
-        "//java/dagger/hilt/android/internal/testing:test_application_component_manager_holder",
-        "//java/dagger/hilt/android/internal/testing:test_component_data",
-        "//java/dagger/hilt/android/internal/testing:test_injector",
-        "//java/dagger/hilt/android/testing:bind_value",
-        "//java/dagger/hilt/android/testing:custom_test_application",
-        "//java/dagger/hilt/android/testing:hilt_android_rule",
-        "//java/dagger/hilt/android/testing:hilt_android_test",
-        "//java/dagger/hilt/android/testing:hilt_test_application",
-        "//java/dagger/hilt/android/testing:on_component_ready_runner",
-        "//java/dagger/hilt/android/testing:package_info",
-        "//java/dagger/hilt/testing:test_install_in",
-        "//java/dagger/hilt/testing:package_info",
-        "//java/dagger/hilt/android/testing:uninstall_modules",
-    ],
-    artifact_target_maven_deps = [
-        "androidx.activity:activity",
-        "androidx.annotation:annotation",
-        "androidx.fragment:fragment",
-        "androidx.lifecycle:lifecycle-viewmodel",
-        "androidx.lifecycle:lifecycle-viewmodel-savedstate",
-        "androidx.multidex:multidex",
-        "androidx.test:core",
-        "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger",
-        "com.google.dagger:hilt-android",
-        "javax.inject:javax.inject",
-        "junit:junit",
-    ],
-    artifact_target_maven_deps_banned = [
-        "com.google.guava:guava",
-        "javax.annotation:jsr250-api",
-    ],
-    javadoc_android_api_level = 30,
-    javadoc_exclude_packages = [
-        "dagger.hilt.internal",
-        "dagger.hilt.android.internal",
-    ],
-    javadoc_root_packages = [
-        "dagger.hilt.android.testing",
-    ],
-    javadoc_srcs = [
-        "//java/dagger/hilt:hilt_android_testing_filegroup",
-        "//java/dagger/hilt:hilt_testing_filegroup",
-    ],
-    manifest = "AndroidManifest.xml",
-    packaging = "aar",
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/android/testing/BindElementsIntoSet.java b/java/dagger/hilt/android/testing/BindElementsIntoSet.java
deleted file mode 100644
index 620e0c5..0000000
--- a/java/dagger/hilt/android/testing/BindElementsIntoSet.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * An annotation that can be used on a test field to contribute the value into the {@link
- * dagger.hilt.components.SingletonComponent} as an {@link
- * dagger.multibindings.ElementsIntoSet} for the given type. Example usage:
- *
- * <pre><code>
- * public class FooTest{
- *   ...
- *   {@literal @}BindElementsIntoSet Set<String> bindedSet = ImmutableSet.of("bar", "baz");
- *   ...
- * }
- * </code></pre>
- *
- * Here, bindedSet will be accessible to the entire application for your test. This is functionally
- * equivalent to installing the following module in your test:
- *
- * <pre><code>
- * {@literal @}Module
- * {@literal @}InstallIn
- * interface MyModule {
- *  {@literal @}Provides
- *  {@literal @}ElementsIntoSet
- *  Set<String> bindSet() {
- *    return ImmutableSet.of("bar", "baz");
- *  }
- * }
- * </code></pre>
- *
- * Also see {@link BindValueIntoSet}, where you can gather individual elements into one set and bind
- * it to the application.
- */
-@Retention(CLASS)
-@Target({ElementType.FIELD})
-@GeneratesRootInput
-public @interface BindElementsIntoSet {}
diff --git a/java/dagger/hilt/android/testing/BindValue.java b/java/dagger/hilt/android/testing/BindValue.java
deleted file mode 100644
index c0164f8..0000000
--- a/java/dagger/hilt/android/testing/BindValue.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * An annotation that can be used on a test field to contribute the value into the {@link
- * dagger.hilt.components.SingletonComponent}. Example usage:
- *
- * <pre><code>
- * public class FooTest{
- *   ...
- *   {@literal @}BindValue Bar boundBar = new Bar();
- *   ...
- * }
- * </code></pre>
- *
- * Here {@code boundBar} will be accessible to the entire application for your test.
- */
-@Retention(CLASS)
-@Target({ElementType.FIELD})
-@GeneratesRootInput
-public @interface BindValue {}
diff --git a/java/dagger/hilt/android/testing/BindValueIntoMap.java b/java/dagger/hilt/android/testing/BindValueIntoMap.java
deleted file mode 100644
index b1dfcb3..0000000
--- a/java/dagger/hilt/android/testing/BindValueIntoMap.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * An annotation that can be used on a test field to contribute the value into the {@link
- * dagger.hilt.components.SingletonComponent} as an {@link dagger.multibindings.IntoMap}
- * for the given type. Example usage:
- *
- * <pre><code>
- * public class FooTest{
- *   ...
- *   {@literal @}BindValueIntoMap
- *   {@literal @}MyMapKey(KEY1)
- *   String boundBar = "bar";
- *
- *   {@literal @}BindValueIntoMap
- *   {@literal @}MyMapKey(KEY2)
- *   String boundBaz = "baz";
- *   ...
- * }
- * </code></pre>
- *
- * Here the map that contains all the bound elements (in this case "bar" and "baz") will be
- * accessible to the entire application for your test.
- */
-@Retention(CLASS)
-@Target({ElementType.FIELD})
-@GeneratesRootInput
-public @interface BindValueIntoMap {}
diff --git a/java/dagger/hilt/android/testing/BindValueIntoSet.java b/java/dagger/hilt/android/testing/BindValueIntoSet.java
deleted file mode 100644
index 690a55c..0000000
--- a/java/dagger/hilt/android/testing/BindValueIntoSet.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * An annotation that can be used on a test field to contribute the value into the {@link
- * dagger.hilt.components.SingletonComponent} as an {@link dagger.multibindings.IntoSet}
- * for the given type. Example usage:
- *
- * <pre><code>
- * public class FooTest{
- *   ...
- *   {@literal @}BindValueIntoSet String boundBar = "bar";
- *   {@literal @}BindValueIntoSet String boundBaz = "baz";
- *   ...
- * }
- * </code></pre>
- *
- * Here the set that contains all the bound elements (in this case "bar" and "baz") will be
- * accessible to the entire application for your test. Also see {@link BindElementsIntoSet}, where
- * you can gather individual elements into one set and bind it to the application.
- */
-@Retention(CLASS)
-@Target({ElementType.FIELD})
-@GeneratesRootInput
-public @interface BindValueIntoSet {}
diff --git a/java/dagger/hilt/android/testing/CustomTestApplication.java b/java/dagger/hilt/android/testing/CustomTestApplication.java
deleted file mode 100644
index 36a4410..0000000
--- a/java/dagger/hilt/android/testing/CustomTestApplication.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * An annotation that creates an application with the given base type that can be used for any
- * test in the given build.
- *
- * <p>This annotation is useful for creating an application that can be used with instrumentation
- * tests in gradle, since every instrumentation test must share the same application type.
- */
-@Target({ElementType.TYPE})
-@GeneratesRootInput
-public @interface CustomTestApplication {
-
-  /** Returns the base {@link android.app.Application} class. */
-  Class<?> value();
-}
diff --git a/java/dagger/hilt/android/testing/HiltAndroidRule.java b/java/dagger/hilt/android/testing/HiltAndroidRule.java
deleted file mode 100644
index 32a34f7..0000000
--- a/java/dagger/hilt/android/testing/HiltAndroidRule.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import static dagger.hilt.internal.Preconditions.checkNotNull;
-
-import dagger.hilt.android.internal.testing.MarkThatRulesRanRule;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-/**
- * A {@link TestRule} for Hilt that can be used with JVM or Instrumentation tests.
- *
- * <p>This rule is required. The Dagger component will not be created without this test rule.
- */
-public final class HiltAndroidRule implements TestRule {
-  private final MarkThatRulesRanRule rule;
-
-  /** Creates a new instance of the rules. Tests should pass {@code this}. */
-  public HiltAndroidRule(Object testInstance) {
-    this.rule = new MarkThatRulesRanRule(checkNotNull(testInstance));
-  }
-
-  @Override public Statement apply(Statement baseStatement, Description description) {
-    return rule.apply(baseStatement, description);
-  }
-
-  /**
-   * Completes Dagger injection. Must be called before accessing inject types. Must be called after
-   * any non-static test module have been added. If {@link #delayComponentReady} was used, this must
-   * be called after {@link #componentReady}.
-   */
-  public void inject() {
-    rule.inject();
-  }
-
-  /**
-   * Delays creating the component until {@link #componentReady} is called. This is only necessary
-   * in the case that a dynamically bound value (e.g. configuring an @BindValue field in @Before
-   * or @Test method) is requested before test case execution begins.
-   *
-   * <p>Examples of early binding requests include an Activity launched by a test rule, or an entry
-   * points in a {@link OnComponentReadyRunner}.
-   *
-   * <p>If this method is called, {@link #componentReady} must be called before the test case
-   * finishes.
-   */
-  public HiltAndroidRule delayComponentReady() {
-    rule.delayComponentReady();
-    return this;
-  }
-
-  /**
-   * Completes Dagger component creation if {@link delayComponentReady} was used. Binds the current
-   * value of {@link BindValue} fields. Normally this happens automatically. This method may only be
-   * called if {@link delayComponentReady} was used to delay value binding.
-   *
-   * @return an instance of the test rule for chaining
-   */
-  public HiltAndroidRule componentReady() {
-    rule.componentReady();
-    return this;
-  }
-}
diff --git a/java/dagger/hilt/android/testing/HiltAndroidTest.java b/java/dagger/hilt/android/testing/HiltAndroidTest.java
deleted file mode 100644
index fa15f92..0000000
--- a/java/dagger/hilt/android/testing/HiltAndroidTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/** Annotation used for marking an Android emulator tests that require injection. */
-// Set the retention to RUNTIME because we check it via reflection in the HiltAndroidRule.
-@Retention(RUNTIME)
-@Target({ElementType.TYPE})
-@GeneratesRootInput
-public @interface HiltAndroidTest {}
diff --git a/java/dagger/hilt/android/testing/HiltTestApplication.java b/java/dagger/hilt/android/testing/HiltTestApplication.java
deleted file mode 100644
index 97eb4cb..0000000
--- a/java/dagger/hilt/android/testing/HiltTestApplication.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import android.content.Context;
-import androidx.multidex.MultiDexApplication;
-import dagger.hilt.android.internal.testing.TestApplicationComponentManager;
-import dagger.hilt.android.internal.testing.TestApplicationComponentManagerHolder;
-import dagger.hilt.internal.GeneratedComponentManager;
-
-/**
- * An application that can be used for Android instrumentation or Robolectric tests using Hilt.
- */
-public final class HiltTestApplication extends MultiDexApplication
-    implements GeneratedComponentManager<Object>, TestApplicationComponentManagerHolder {
-
-  // This field is initialized in attachBaseContext to avoid pulling the generated component into
-  // the main dex. We could possibly avoid this by class loading TestComponentDataSupplier lazily
-  // rather than in the TestApplicationComponentManager constructor.
-  private TestApplicationComponentManager componentManager;
-
-  @Override
-  protected final void attachBaseContext(Context base) {
-    super.attachBaseContext(base);
-    componentManager = new TestApplicationComponentManager(this);
-  }
-
-  @Override
-  public final Object componentManager() {
-    return componentManager;
-  }
-
-  @Override
-  public final Object generatedComponent() {
-    return componentManager.generatedComponent();
-  }
-}
diff --git a/java/dagger/hilt/android/testing/OnComponentReadyRunner.java b/java/dagger/hilt/android/testing/OnComponentReadyRunner.java
deleted file mode 100644
index 925a19f..0000000
--- a/java/dagger/hilt/android/testing/OnComponentReadyRunner.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import android.app.Application;
-import android.content.Context;
-import com.google.auto.value.AutoValue;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.android.internal.testing.TestApplicationComponentManagerHolder;
-import dagger.hilt.internal.GeneratedComponentManager;
-import dagger.hilt.internal.Preconditions;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Provides access to the Singleton component in tests, so that Rules can access it after custom
- * test modules have been added.
- */
-public final class OnComponentReadyRunner {
-  private final List<EntryPointListener<?>> listeners = new ArrayList<>();
-  private GeneratedComponentManager<?> componentManager;
-  private boolean componentHostSet = false;
-
-  /** Used by generated code, to notify listeners that the component has been created. */
-  public void setComponentManager(GeneratedComponentManager<?> componentManager) {
-    Preconditions.checkState(!componentHostSet, "Component host was already set.");
-    componentHostSet = true;
-    this.componentManager = componentManager;
-    for (EntryPointListener<?> listener : listeners) {
-      listener.deliverComponent(componentManager);
-    }
-  }
-
-  /** Must be called on the test thread, before the Statement is evaluated. */
-  public static <T> void addListener(
-      Context context, Class<T> entryPoint, OnComponentReadyListener<T> listener) {
-    Application application = (Application) context.getApplicationContext();
-    if (application instanceof TestApplicationComponentManagerHolder) {
-      TestApplicationComponentManagerHolder managerHolder =
-          (TestApplicationComponentManagerHolder) application;
-      OnComponentReadyRunnerHolder runnerHolder =
-          (OnComponentReadyRunnerHolder) managerHolder.componentManager();
-      runnerHolder.getOnComponentReadyRunner().addListenerInternal(entryPoint, listener);
-    }
-  }
-
-  private <T> void addListenerInternal(Class<T> entryPoint, OnComponentReadyListener<T> listener) {
-    if (componentHostSet) {
-      // If the componentHost was already set, just call through immediately
-      runListener(componentManager, entryPoint, listener);
-    } else {
-      listeners.add(EntryPointListener.create(entryPoint, listener));
-    }
-  }
-
-  public boolean isEmpty() {
-    return listeners.isEmpty();
-  }
-
-  @AutoValue
-  abstract static class EntryPointListener<T> {
-    static <T> EntryPointListener<T> create(
-        Class<T> entryPoint, OnComponentReadyListener<T> listener) {
-      return new AutoValue_OnComponentReadyRunner_EntryPointListener<T>(entryPoint, listener);
-    }
-
-    abstract Class<T> entryPoint();
-
-    abstract OnComponentReadyListener<T> listener();
-
-    private void deliverComponent(GeneratedComponentManager<?> object) {
-      runListener(object, entryPoint(), listener());
-    }
-  }
-
-  private static <T> void runListener(
-      GeneratedComponentManager<?> componentManager,
-      Class<T> entryPoint,
-      OnComponentReadyListener<T> listener) {
-    try {
-      listener.onComponentReady(EntryPoints.get(componentManager, entryPoint));
-    } catch (RuntimeException | Error t) {
-      throw t;
-    } catch (Throwable t) {
-      throw new RuntimeException(t);
-    }
-  }
-
-  /** Public for use by generated code and {@link TestApplicationComponentManager} */
-  public interface OnComponentReadyRunnerHolder {
-    OnComponentReadyRunner getOnComponentReadyRunner();
-  }
-
-  /** Rules should register an implementation of this to get access to the singleton component */
-  public interface OnComponentReadyListener<T> {
-    void onComponentReady(T entryPoint) throws Throwable;
-  }
-}
diff --git a/java/dagger/hilt/android/testing/UninstallModules.java b/java/dagger/hilt/android/testing/UninstallModules.java
deleted file mode 100644
index 6480c10..0000000
--- a/java/dagger/hilt/android/testing/UninstallModules.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.testing;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * An annotation used to uninstall modules that have previously been installed with {@link
- * dagger.hilt.InstallIn}.
- *
- * <p>This feature should only be used in tests. It is useful for replacing production bindings with
- * fake bindings. The basic idea is to allow users to uninstall the module that provided the
- * production binding so that a fake binding can be provided by the test.
- *
- * <p>Example:
- *
- * <pre><code>
- *   {@literal @}HiltAndroidTest
- *   {@literal @}UninstallModules({
- *       ProdFooModule.class,
- *   })
- *   public class MyTest {
- *     {@literal @}Module
- *     {@literal @}InstallIn(SingletonComponent.class)
- *     interface FakeFooModule {
- *       {@literal @}Binds Foo bindFoo(FakeFoo fakeFoo);
- *     }
- *   }
- * </code></pre>
- */
-@Target({ElementType.TYPE})
-public @interface UninstallModules {
-
-  /**
-   * Returns the list of classes to uninstall.
-   *
-   * <p>These classes must be annotated with both {@link dagger.Module} and {@link
-   * dagger.hilt.InstallIn}.
-   *
-   * <p>Note:A module that is included as part of another module's {@link dagger.Module#includes()}
-   * cannot be truly uninstalled until the including module is also uninstalled.
-   */
-  Class<?>[] value() default {};
-}
diff --git a/java/dagger/hilt/android/testing/package-info.java b/java/dagger/hilt/android/testing/package-info.java
deleted file mode 100644
index fae8e7d..0000000
--- a/java/dagger/hilt/android/testing/package-info.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains APIs for writing Android local or instrumentation tests with Hilt.
- *
- * @see <a href="https://dagger.dev/hilt/testing">Hilt Testing</a>
- */
-@ParametersAreNonnullByDefault
-package dagger.hilt.android.testing;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/java/dagger/hilt/codegen/BUILD b/java/dagger/hilt/codegen/BUILD
deleted file mode 100644
index c88182b..0000000
--- a/java/dagger/hilt/codegen/BUILD
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   This package contains sources used within code generated sources.
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "originating_element",
-    srcs = ["OriginatingElement.java"],
-    exported_plugins = [
-        "//java/dagger/hilt/processor/internal/originatingelement:processor",
-    ],
-    deps = [
-        ":package_info",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/codegen/OriginatingElement.java b/java/dagger/hilt/codegen/OriginatingElement.java
deleted file mode 100644
index c53a430..0000000
--- a/java/dagger/hilt/codegen/OriginatingElement.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.codegen;
-
-/**
- * An annotation used to specify the originating element that triggered the code generation of a
- * type. This annotation should only be used on generated code and is meant to be used by code
- * generators that generate Hilt modules, entry points, etc. Failure to use this annotation may mean
- * improper test isolation for generated classes.
- *
- * <p>This annotation should be used on any generated top-level class that either contains generated
- * modules (or entry points) or contains annotations that will generate modules (or entry points).
- *
- * <p>Example: Suppose we have the following use of an annotation, {@code MyAnnotation}.
- *
- * <pre><code>
- *   class Outer {
- *     static class Inner {
- *       {@literal @}MyAnnotation Foo foo;
- *     }
- *   }
- * </code></pre>
- *
- * <p>If {@code MyAnnotation} generates an entry point, it should be annotated as follows:
- *
- * <pre><code>
- *   {@literal @}OriginatingElement(topLevelClass = Outer.class)
- *   {@literal @}EntryPoint
- *   {@literal @}InstallIn(SingletonComponent.class) {
- *       ...
- *   }
- * </code></pre>
- */
-// TODO(bcorso): Consider just advising/enforcing that all top-level classes use this annotation.
-public @interface OriginatingElement {
-  /** Returns the top-level class enclosing the originating element. */
-  Class<?> topLevelClass();
-}
diff --git a/java/dagger/hilt/codegen/package-info.java b/java/dagger/hilt/codegen/package-info.java
deleted file mode 100644
index b6bf709..0000000
--- a/java/dagger/hilt/codegen/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains APIs for code generators that produce code that will be processed by Hilt.
- */
-// TODO(danysantiago): Add documentation about other code generators that produce input for Hilt
-package dagger.hilt.codegen;
diff --git a/java/dagger/hilt/components/BUILD b/java/dagger/hilt/components/BUILD
deleted file mode 100644
index 48dc8cd..0000000
--- a/java/dagger/hilt/components/BUILD
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Hilt components
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "components",
-    srcs = [
-        "SingletonComponent.java",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:define_component",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/components/SingletonComponent.java b/java/dagger/hilt/components/SingletonComponent.java
deleted file mode 100644
index 07e8fe7..0000000
--- a/java/dagger/hilt/components/SingletonComponent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.components;
-
-import dagger.hilt.DefineComponent;
-import javax.inject.Singleton;
-
-/** A Hilt component for singleton bindings. */
-@Singleton
-@DefineComponent
-public interface SingletonComponent {}
diff --git a/java/dagger/hilt/components/package-info.java b/java/dagger/hilt/components/package-info.java
deleted file mode 100644
index 3c8cb18..0000000
--- a/java/dagger/hilt/components/package-info.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains Hilt's built-in {@link dagger.Component}s.
- *
- * @see <a href="https://dagger.dev/hilt/components.md">Hilt Components</a>
- */
-package dagger.hilt.components;
diff --git a/java/dagger/hilt/internal/BUILD b/java/dagger/hilt/internal/BUILD
deleted file mode 100644
index dc245d1..0000000
--- a/java/dagger/hilt/internal/BUILD
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Internal Hilt libraries
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "generated_component",
-    srcs = [
-        "GeneratedComponent.java",
-    ],
-)
-
-java_library(
-    name = "component_manager",
-    srcs = [
-        "GeneratedComponentManager.java",
-        "GeneratedComponentManagerHolder.java",
-    ],
-    exports = [
-        ":preconditions",
-        ":unsafe_casts",
-    ],
-)
-
-java_library(
-    name = "preconditions",
-    srcs = [
-        "Preconditions.java",
-    ],
-)
-
-java_library(
-    name = "unsafe_casts",
-    srcs = [
-        "UnsafeCasts.java",
-    ],
-)
-
-java_library(
-    name = "component_entry_point",
-    srcs = ["ComponentEntryPoint.java"],
-    deps = ["//java/dagger/hilt:generates_root_input"],
-)
-
-java_library(
-    name = "generated_entry_point",
-    srcs = ["GeneratedEntryPoint.java"],
-    deps = ["//java/dagger/hilt:generates_root_input"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/internal/ComponentEntryPoint.java b/java/dagger/hilt/internal/ComponentEntryPoint.java
deleted file mode 100644
index 3967e1b..0000000
--- a/java/dagger/hilt/internal/ComponentEntryPoint.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.internal;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Annotation marking generated interfaces for entry points for which there is also a corresponding
- * generated Component. Component entry points differ from normal entry points in that they may be
- * filtered out in tests.
- */
-@Target(ElementType.TYPE)
-@Retention(CLASS)
-@GeneratesRootInput
-// TODO(bcorso): Rename and publicly strip these references out of hilt.
-public @interface ComponentEntryPoint {}
diff --git a/java/dagger/hilt/internal/GeneratedComponent.java b/java/dagger/hilt/internal/GeneratedComponent.java
deleted file mode 100644
index 4d85d37..0000000
--- a/java/dagger/hilt/internal/GeneratedComponent.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.internal;
-
-/** A marker interface indicating that this is a Hilt generated component. */
-public interface GeneratedComponent {}
diff --git a/java/dagger/hilt/internal/GeneratedComponentManager.java b/java/dagger/hilt/internal/GeneratedComponentManager.java
deleted file mode 100644
index bd837a3..0000000
--- a/java/dagger/hilt/internal/GeneratedComponentManager.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.internal;
-
-/** An interface that provides a managed generated component. */
-// TODO(bcorso): Consider either removing type parameter or using actual component type in usages.
-public interface GeneratedComponentManager<T> {
-  T generatedComponent();
-}
diff --git a/java/dagger/hilt/internal/GeneratedComponentManagerHolder.java b/java/dagger/hilt/internal/GeneratedComponentManagerHolder.java
deleted file mode 100644
index f65e2df..0000000
--- a/java/dagger/hilt/internal/GeneratedComponentManagerHolder.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.internal;
-
-/** An interface that provides a managed generated component holder. */
-public interface GeneratedComponentManagerHolder extends GeneratedComponentManager<Object> {
-
-  public GeneratedComponentManager<?> componentManager();
-}
diff --git a/java/dagger/hilt/internal/GeneratedEntryPoint.java b/java/dagger/hilt/internal/GeneratedEntryPoint.java
deleted file mode 100644
index 76319b9..0000000
--- a/java/dagger/hilt/internal/GeneratedEntryPoint.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.internal;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/** Do not use. Only for use from Hilt generators. */
-@Target(ElementType.TYPE)
-@GeneratesRootInput
-public @interface GeneratedEntryPoint {}
diff --git a/java/dagger/hilt/internal/Preconditions.java b/java/dagger/hilt/internal/Preconditions.java
deleted file mode 100644
index b2a84db..0000000
--- a/java/dagger/hilt/internal/Preconditions.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.internal;
-
-/**
- * A partial copy of Guava's {@code com.google.common.base.Preconditions} meant to be used by
- * generated code. TODO(danysantiago): Consolidate with dagger.internal.Preconditions
- */
-public final class Preconditions {
-
-  /**
-   * Ensures that an object reference passed as a parameter to the calling method is not null.
-   *
-   * @param reference an object reference
-   * @return the non-null reference that was validated
-   * @throws NullPointerException if {@code reference} is null
-   */
-  public static <T> T checkNotNull(T reference) {
-    if (reference == null) {
-      throw new NullPointerException();
-    }
-    return reference;
-  }
-
-  /**
-   * Ensures that an object reference passed as a parameter to the calling method is not null.
-   *
-   * @param reference an object reference
-   * @param errorMessage the exception message to use if the check fails
-   * @return the non-null reference that was validated
-   * @throws NullPointerException if {@code reference} is null
-   */
-  public static <T> T checkNotNull(T reference, String errorMessage) {
-    if (reference == null) {
-      throw new NullPointerException(errorMessage);
-    }
-    return reference;
-  }
-
-  /**
-   * Ensures the truth of an expression involving one or more parameters to the calling method.
-   *
-   * @param expression a boolean expression
-   * @param errorMessageTemplate a template for the exception message should the check fail. The
-   *     message is formed by replacing each occurrence of {@code "%s"} with the corresponding
-   *     argument value from {@code args}.
-   * @param args the arguments to be substituted into the message template.
-   * @throws IllegalArgumentException if {@code expression} is false
-   */
-  public static void checkArgument(
-      boolean expression, String errorMessageTemplate, Object... args) {
-    if (!expression) {
-      throw new IllegalArgumentException(String.format(errorMessageTemplate, args));
-    }
-  }
-
-  /**
-   * Ensures the truth of an expression involving one or more parameters to the calling method.
-   *
-   * @param expression a boolean expression
-   * @param errorMessageTemplate a template for the exception message should the check fail. The
-   *     message is formed by replacing each occurrence of {@code "%s"} with the corresponding
-   *     argument value from {@code args}.
-   * @param args the arguments to be substituted into the message template.
-   * @throws IllegalStateException if {@code expression} is false
-   */
-  public static void checkState(boolean expression, String errorMessageTemplate, Object... args) {
-    if (!expression) {
-      throw new IllegalStateException(String.format(errorMessageTemplate, args));
-    }
-  }
-
-  private Preconditions() {}
-}
diff --git a/java/dagger/hilt/internal/UnsafeCasts.java b/java/dagger/hilt/internal/UnsafeCasts.java
deleted file mode 100644
index 796dfce..0000000
--- a/java/dagger/hilt/internal/UnsafeCasts.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.internal;
-
-/** Runtime utility method for performing a casting in generated code. */
-public final class UnsafeCasts {
-
-  // Only used where code generations makes it safe.
-  @SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"})
-  public static <T> T unsafeCast(Object obj) {
-    return (T) obj;
-  }
-
-  private UnsafeCasts() {}
-}
diff --git a/java/dagger/hilt/internal/aliasof/AliasOfPropagatedData.java b/java/dagger/hilt/internal/aliasof/AliasOfPropagatedData.java
deleted file mode 100644
index 25ea704..0000000
--- a/java/dagger/hilt/internal/aliasof/AliasOfPropagatedData.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.internal.aliasof;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/** An annotation used to aggregate AliasOf values in a common location. */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.CLASS)
-public @interface AliasOfPropagatedData {
-  Class<? extends Annotation> defineComponentScope();
-
-  Class<? extends Annotation> alias();
-}
diff --git a/java/dagger/hilt/internal/aliasof/BUILD b/java/dagger/hilt/internal/aliasof/BUILD
deleted file mode 100644
index 3e96ed4..0000000
--- a/java/dagger/hilt/internal/aliasof/BUILD
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   The annotation for classes generated by @AliasOf.
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "aliasof",
-    srcs = ["AliasOfPropagatedData.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/internal/definecomponent/BUILD b/java/dagger/hilt/internal/definecomponent/BUILD
deleted file mode 100644
index b1d56c4..0000000
--- a/java/dagger/hilt/internal/definecomponent/BUILD
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   The annotations for classes generated by @DefineComponent and @DefineComponent.Factory.
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "definecomponent",
-    srcs = glob(["*.java"]),
-    visibility = [
-        "//java/dagger/hilt:__pkg__",
-        "//java/dagger/hilt/android:__pkg__",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/internal/definecomponent/DefineComponentClasses.java b/java/dagger/hilt/internal/definecomponent/DefineComponentClasses.java
deleted file mode 100644
index 25555fb..0000000
--- a/java/dagger/hilt/internal/definecomponent/DefineComponentClasses.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.internal.definecomponent;
-
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * An annotation used to aggregate {@link dagger.hilt.DefineComponent} types in a common location.
- *
- * <p>Note: The types are given using {@link String} rather than {@link Class} since the {@link
- * dagger.hilt.DefineComponent} type is not necessarily in the same package and not necessarily
- * public.
- */
-@Retention(CLASS)
-@Target(TYPE)
-public @interface DefineComponentClasses {
-  /**
-   * Returns the fully qualified name of the {@link dagger.hilt.DefineComponent} type, or an empty
-   * string if it wasn't given.
-   */
-  String component() default "";
-
-  /**
-   * Returns the fully qualified name of the {@link dagger.hilt.DefineComponent.Builder} type, or an
-   * empty string if it wasn't given.
-   */
-  String builder() default "";
-}
diff --git a/java/dagger/hilt/internal/definecomponent/DefineComponentNoParent.java b/java/dagger/hilt/internal/definecomponent/DefineComponentNoParent.java
deleted file mode 100644
index d5da760..0000000
--- a/java/dagger/hilt/internal/definecomponent/DefineComponentNoParent.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.internal.definecomponent;
-
-/** A class used by {@link DefineComponent#parent()} as the default type when no parent is given. */
-public final class DefineComponentNoParent {
-  private DefineComponentNoParent() {}
-}
diff --git a/java/dagger/hilt/internal/generatesrootinput/BUILD b/java/dagger/hilt/internal/generatesrootinput/BUILD
deleted file mode 100644
index 8e54ac4..0000000
--- a/java/dagger/hilt/internal/generatesrootinput/BUILD
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   The annotations for classes generated by @GeneratesRootInput.
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "generatesrootinput",
-    srcs = ["GeneratesRootInputPropagatedData.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/internal/generatesrootinput/GeneratesRootInputPropagatedData.java b/java/dagger/hilt/internal/generatesrootinput/GeneratesRootInputPropagatedData.java
deleted file mode 100644
index d4917f8..0000000
--- a/java/dagger/hilt/internal/generatesrootinput/GeneratesRootInputPropagatedData.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.internal.generatesrootinput;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * An annotation used to aggregate {@link dagger.hilt.GeneratesRootInput} types in a common
- * location.
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.CLASS)
-public @interface GeneratesRootInputPropagatedData {
-  Class<? extends Annotation> value();
-}
diff --git a/java/dagger/hilt/migration/AliasOf.java b/java/dagger/hilt/migration/AliasOf.java
deleted file mode 100644
index b68d4f1..0000000
--- a/java/dagger/hilt/migration/AliasOf.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.migration;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Defines an alias between an existing Hilt scope and the annotated scope. For example, the
- * following code makes {@literal @}MyScope a functional replacement for {@literal @}ActivityScope.
- *
- * <p>
- *
- * <pre>
- *   {@literal @}Scope
- *   {@literal @}AliasOf(ActivityScope.class)
- *   public {@literal @}interface MyScope{}
- * </pre>
- *
- * <p>
- */
-@Target(ElementType.ANNOTATION_TYPE)
-@Retention(RetentionPolicy.CLASS)
-@GeneratesRootInput
-public @interface AliasOf {
-  /** Returns the existing Hilt scope that the annotated scope is aliasing. */
-  Class<? extends Annotation> value();
-}
diff --git a/java/dagger/hilt/migration/BUILD b/java/dagger/hilt/migration/BUILD
deleted file mode 100644
index a14410d..0000000
--- a/java/dagger/hilt/migration/BUILD
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (C) 2020 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.
-# Description:
-#   Libraries for migration.
-
-package(default_visibility = ["//:src"])
-
-android_library(
-    name = "alias_of",
-    srcs = [
-        "AliasOf.java",
-    ],
-    exported_plugins = [
-        "//java/dagger/hilt/processor/internal/aliasof:processor",
-    ],
-    exports = [
-        "//java/dagger/hilt/internal/aliasof",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-java_library(
-    name = "disable_install_in_check",
-    srcs = ["DisableInstallInCheck.java"],
-    exported_plugins = [
-        "//java/dagger/hilt/processor/internal/disableinstallincheck:processor",
-    ],
-    exports = [
-    ],
-    deps = [
-        ":package_info",
-    ],
-)
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/migration/DisableInstallInCheck.java b/java/dagger/hilt/migration/DisableInstallInCheck.java
deleted file mode 100644
index acb6252..0000000
--- a/java/dagger/hilt/migration/DisableInstallInCheck.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.migration;
-
-/**
- * Marks a {@link dagger.Module}-annotated class to allow it to have no {@link
- * dagger.hilt.InstallIn} annotation.
- *
- * <p>Use this annotation on modules to suppress the error of a missing {@link
- * dagger.hilt.InstallIn} annotation. This is useful in cases where non-Hilt Dagger code must be
- * used long-term. If the issue is widespread, consider changing the error behavior with the
- * compiler flag {@code dagger.hilt.disableModulesHaveInstallInCheck} instead.
- */
-public @interface DisableInstallInCheck {}
diff --git a/java/dagger/hilt/migration/package-info.java b/java/dagger/hilt/migration/package-info.java
deleted file mode 100644
index bc269e3..0000000
--- a/java/dagger/hilt/migration/package-info.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains APIs to help migrating a codebase to Hilt.
- *
- * @see <a href="https://dagger.dev/hilt/migration">Migration to Hilt</a>
- */
-package dagger.hilt.migration;
diff --git a/java/dagger/hilt/package-info.java b/java/dagger/hilt/package-info.java
deleted file mode 100644
index 568b060..0000000
--- a/java/dagger/hilt/package-info.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains the core APIs for Hilt.
- *
- * <p>Hilt provides a standard way to incorporate Dagger dependency injection into an Android
- * application.
- *
- * @see <a href="https://dagger.dev/hilt">Hilt Developer Docs</a>
- */
-@ParametersAreNonnullByDefault
-package dagger.hilt;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/java/dagger/hilt/processor/BUILD b/java/dagger/hilt/processor/BUILD
deleted file mode 100644
index 87adcf3..0000000
--- a/java/dagger/hilt/processor/BUILD
+++ /dev/null
@@ -1,120 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Hilt android processors.
-
-load("//:build_defs.bzl", "POM_VERSION_ALPHA")
-load("//tools:maven.bzl", "gen_maven_artifact")
-
-package(default_visibility = ["//:src"])
-
-# TODO(bcorso): merge this into :artifact-lib once we remove hilt-android-compiler artifact.
-java_library(
-    name = "artifact-lib-shared",
-    exports = [
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/bindvalue:bind_value_processor_lib",
-        "//java/dagger/hilt/android/processor/internal/customtestapplication:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/uninstallmodules:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:validation_plugin_lib",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:processor_lib",
-        "//java/dagger/hilt/processor/internal/aliasof:processor_lib",
-        "//java/dagger/hilt/processor/internal/definecomponent:processor_lib",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:processor_lib",
-        "//java/dagger/hilt/processor/internal/originatingelement:processor_lib",
-        "//java/dagger/hilt/processor/internal/root:processor_lib",
-        "//java/dagger/internal/codegen:processor",
-    ],
-)
-
-java_library(
-    name = "artifact-lib",
-    tags = ["maven_coordinates=com.google.dagger:hilt-compiler:" + POM_VERSION_ALPHA],
-    visibility = ["//visibility:private"],
-    exports = [
-        ":artifact-lib-shared",
-    ],
-)
-
-gen_maven_artifact(
-    name = "artifact",
-    artifact_coordinates = "com.google.dagger:hilt-compiler:" + POM_VERSION_ALPHA,
-    artifact_name = "Hilt Processor",
-    artifact_target = ":artifact-lib",
-    artifact_target_libs = [
-        "//java/dagger/hilt/android/processor/internal:android_classnames",
-        "//java/dagger/hilt/android/processor/internal:utils",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:android_generators",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:compiler_options",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:metadata",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/bindvalue:bind_value_processor_lib",
-        "//java/dagger/hilt/android/processor/internal/customtestapplication:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:validation_plugin_lib",
-        "//java/dagger/hilt/android/processor/internal/uninstallmodules:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:component_descriptor",
-        "//java/dagger/hilt/processor/internal:component_names",
-        "//java/dagger/hilt/processor/internal:components",
-        "//java/dagger/hilt/processor/internal:kotlin",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:component_dependencies",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:processor_lib",
-        "//java/dagger/hilt/processor/internal/aliasof:alias_ofs",
-        "//java/dagger/hilt/processor/internal/aliasof:processor_lib",
-        "//java/dagger/hilt/processor/internal/definecomponent:define_components",
-        "//java/dagger/hilt/processor/internal/definecomponent:processor_lib",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:generates_root_inputs",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:processor_lib",
-        "//java/dagger/hilt/processor/internal/originatingelement:processor_lib",
-        "//java/dagger/hilt/processor/internal/root:processor_lib",
-        "//java/dagger/hilt/processor/internal/root:root_metadata",
-        "//java/dagger/hilt/processor/internal/root:root_type",
-    ],
-    artifact_target_maven_deps = [
-        "com.google.auto:auto-common",
-        "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger-compiler",
-        "com.google.dagger:dagger",
-        "com.google.dagger:dagger-spi",
-        "com.google.guava:failureaccess",
-        "com.google.guava:guava",
-        "com.squareup:javapoet",
-        "javax.annotation:jsr250-api",
-        "javax.inject:javax.inject",
-        "net.ltgt.gradle.incap:incap",
-        "org.jetbrains.kotlin:kotlin-stdlib",
-        "org.jetbrains.kotlinx:kotlinx-metadata-jvm",
-    ],
-    javadoc_android_api_level = 30,
-    javadoc_root_packages = [
-        "dagger.hilt.processor",
-        "dagger.hilt.android.processor",
-    ],
-    javadoc_srcs = [
-        "//java/dagger/hilt:hilt_processing_filegroup",
-    ],
-    shaded_deps = ["@maven//:com_google_auto_auto_common"],
-    shaded_rules = ["rule com.google.auto.common.** dagger.hilt.android.shaded.auto.common.@1"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/AnnotationValues.java b/java/dagger/hilt/processor/internal/AnnotationValues.java
deleted file mode 100644
index 584d8f9..0000000
--- a/java/dagger/hilt/processor/internal/AnnotationValues.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.AnnotationValueVisitor;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleAnnotationValueVisitor8;
-
-/** A utility class for working with {@link AnnotationValue} instances. */
-// TODO(bcorso): Update auto-common maven import so we can use it rather than this copy.
-public final class AnnotationValues {
-
-  private AnnotationValues() {}
-
-  private static class DefaultVisitor<T> extends SimpleAnnotationValueVisitor8<T, Void> {
-    final Class<T> clazz;
-
-    DefaultVisitor(Class<T> clazz) {
-      this.clazz = checkNotNull(clazz);
-    }
-
-    @Override
-    public T defaultAction(Object o, Void unused) {
-      throw new IllegalArgumentException(
-          "Expected a " + clazz.getSimpleName() + ", got instead: " + o);
-    }
-  }
-
-  private static final class TypeMirrorVisitor extends DefaultVisitor<DeclaredType> {
-    static final TypeMirrorVisitor INSTANCE = new TypeMirrorVisitor();
-
-    TypeMirrorVisitor() {
-      super(DeclaredType.class);
-    }
-
-    @Override
-    public DeclaredType visitType(TypeMirror value, Void unused) {
-      return MoreTypes.asDeclared(value);
-    }
-  }
-
-  /**
-   * Returns the value as a class.
-   *
-   * @throws IllegalArgumentException if the value is not a class.
-   */
-  public static DeclaredType getTypeMirror(AnnotationValue value) {
-    return TypeMirrorVisitor.INSTANCE.visit(value);
-  }
-
-  private static final class EnumVisitor extends DefaultVisitor<VariableElement> {
-    static final EnumVisitor INSTANCE = new EnumVisitor();
-
-    EnumVisitor() {
-      super(VariableElement.class);
-    }
-
-    @Override
-    public VariableElement visitEnumConstant(VariableElement value, Void unused) {
-      return value;
-    }
-  }
-
-  /**
-   * Returns the value as a VariableElement.
-   *
-   * @throws IllegalArgumentException if the value is not an enum.
-   */
-  public static VariableElement getEnum(AnnotationValue value) {
-    return EnumVisitor.INSTANCE.visit(value);
-  }
-
-  /**
-   * Returns the value as a string.
-   *
-   * @throws IllegalArgumentException if the value is not a string.
-   */
-  public static String getString(AnnotationValue value) {
-    return valueOfType(value, String.class);
-  }
-
-  private static <T> T valueOfType(AnnotationValue annotationValue, Class<T> type) {
-    Object value = annotationValue.getValue();
-    if (!type.isInstance(value)) {
-      throw new IllegalArgumentException(
-          "Expected " + type.getSimpleName() + ", got instead: " + value);
-    }
-    return type.cast(value);
-  }
-
-  /** Returns the int value of an annotation */
-  public static int getIntValue(AnnotationMirror annotation, String valueName) {
-    return (int) getAnnotationValue(annotation, valueName).getValue();
-  }
-
-  /** Returns an optional int value of an annotation if the value name is present */
-  public static Optional<Integer> getOptionalIntValue(
-      AnnotationMirror annotation, String valueName) {
-    return isValuePresent(annotation, valueName)
-        ? Optional.of(getIntValue(annotation, valueName))
-        : Optional.empty();
-  }
-
-  /** Returns the String value of an annotation */
-  public static String getStringValue(AnnotationMirror annotation, String valueName) {
-    return (String) getAnnotationValue(annotation, valueName).getValue();
-  }
-
-  /** Returns an optional String value of an annotation if the value name is present */
-  public static Optional<String> getOptionalStringValue(
-      AnnotationMirror annotation, String valueName) {
-    return isValuePresent(annotation, valueName)
-        ? Optional.of(getStringValue(annotation, valueName))
-        : Optional.empty();
-  }
-
-  /** Returns the int array value of an annotation */
-  public static int[] getIntArrayValue(AnnotationMirror annotation, String valueName) {
-    return getAnnotationValues(getAnnotationValue(annotation, valueName)).stream()
-        .mapToInt(it -> (int) it.getValue())
-        .toArray();
-  }
-
-  /** Returns the String array value of an annotation */
-  public static String[] getStringArrayValue(AnnotationMirror annotation, String valueName) {
-    return getAnnotationValues(getAnnotationValue(annotation, valueName)).stream()
-        .map(it -> (String) it.getValue())
-        .toArray(String[]::new);
-  }
-
-  private static boolean isValuePresent(AnnotationMirror annotation, String valueName) {
-    return getAnnotationValuesWithDefaults(annotation).keySet().stream()
-        .anyMatch(member -> member.getSimpleName().contentEquals(valueName));
-  }
-
-  /**
-   * Returns the list of values represented by an array annotation value.
-   *
-   * @throws IllegalArgumentException unless {@code annotationValue} represents an array
-   */
-  public static ImmutableList<AnnotationValue> getAnnotationValues(
-      AnnotationValue annotationValue) {
-    return annotationValue.accept(AS_ANNOTATION_VALUES, null);
-  }
-
-  private static final AnnotationValueVisitor<ImmutableList<AnnotationValue>, String>
-      AS_ANNOTATION_VALUES =
-          new SimpleAnnotationValueVisitor8<ImmutableList<AnnotationValue>, String>() {
-            @Override
-            public ImmutableList<AnnotationValue> visitArray(
-                List<? extends AnnotationValue> vals, String elementName) {
-              return ImmutableList.copyOf(vals);
-            }
-
-            @Override
-            protected ImmutableList<AnnotationValue> defaultAction(Object o, String elementName) {
-              throw new IllegalArgumentException(elementName + " is not an array: " + o);
-            }
-          };
-}
diff --git a/java/dagger/hilt/processor/internal/BUILD b/java/dagger/hilt/processor/internal/BUILD
deleted file mode 100644
index baff1d8..0000000
--- a/java/dagger/hilt/processor/internal/BUILD
+++ /dev/null
@@ -1,149 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Internal code for implementing Hilt processors.
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "base_processor",
-    srcs = [
-        "BaseProcessor.java",
-        "ProcessorErrorHandler.java",
-    ],
-    deps = [
-        ":processor_errors",
-        ":processors",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_library(
-    name = "processor_errors",
-    srcs = [
-        "BadInputException.java",
-        "ErrorTypeException.java",
-        "ProcessorErrors.java",
-    ],
-    deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_library(
-    name = "processors",
-    srcs = [
-        "AnnotationValues.java",
-        "Processors.java",
-    ],
-    deps = [
-        ":classnames",
-        ":kotlin",
-        ":processor_errors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-        "@maven//:org_jetbrains_kotlin_kotlin_stdlib",
-        "@maven//:org_jetbrains_kotlinx_kotlinx_metadata_jvm",
-    ],
-)
-
-java_library(
-    name = "classnames",
-    srcs = [
-        "ClassNames.java",
-    ],
-    deps = [
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-java_library(
-    name = "component_names",
-    srcs = [
-        "ComponentNames.java",
-    ],
-    deps = [
-        ":processors",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-java_library(
-    name = "component_descriptor",
-    srcs = [
-        "ComponentDescriptor.java",
-        "ComponentGenerator.java",
-        "ComponentTree.java",
-    ],
-    deps = [
-        ":classnames",
-        ":processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:graph",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-java_library(
-    name = "components",
-    srcs = [
-        "Components.java",
-    ],
-    deps = [
-        ":classnames",
-        ":component_descriptor",
-        ":kotlin",
-        ":processor_errors",
-        ":processors",
-        "//java/dagger/hilt/processor/internal/definecomponent:define_components",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_library(
-    name = "kotlin",
-    srcs = ["KotlinMetadataUtils.java"],
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/internal/codegen/kotlin",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/BadInputException.java b/java/dagger/hilt/processor/internal/BadInputException.java
deleted file mode 100644
index d961768..0000000
--- a/java/dagger/hilt/processor/internal/BadInputException.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import com.google.common.collect.ImmutableList;
-import javax.lang.model.element.Element;
-
-/**
- * Exception to throw when input code has caused an error.
- * Includes elements to point to for the cause of the error
- */
-public final class BadInputException extends RuntimeException {
-  private final ImmutableList<Element> badElements;
-
-  public BadInputException(String message, Element badElement) {
-    super(message);
-    this.badElements = ImmutableList.of(badElement);
-  }
-
-  public BadInputException(String message, Iterable<? extends Element> badElements) {
-    super(message);
-    this.badElements = ImmutableList.copyOf(badElements);
-  }
-
-  public ImmutableList<Element> getBadElements() {
-    return badElements;
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/BaseProcessor.java b/java/dagger/hilt/processor/internal/BaseProcessor.java
deleted file mode 100644
index 4961cd5..0000000
--- a/java/dagger/hilt/processor/internal/BaseProcessor.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.SetMultimap;
-import com.squareup.javapoet.ClassName;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Messager;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.annotation.processing.RoundEnvironment;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
-
-/**
- * Implements default configurations for Processors, and provides structure for exception handling.
- *
- * <p>By default #process() will do the following:
- *
- * <ol>
- *   <li> #preRoundProcess()
- *   <li> foreach element:
- *     <ul><li> #processEach()</ul>
- *   </li>
- *   <li> #postRoundProcess()
- *   <li> #claimAnnotation()
- * </ol>
- *
- * <p>#processEach() allows each element to be processed, even if exceptions are thrown. Due to the
- * non-deterministic ordering of the processed elements, this is needed to ensure a consistent set
- * of exceptions are thrown with each build.
- */
-public abstract class BaseProcessor extends AbstractProcessor {
-  /** Stores the state of processing for a given annotation and element. */
-  @AutoValue
-  abstract static class ProcessingState {
-    private static ProcessingState of(TypeElement annotation, Element element) {
-      // We currently only support TypeElements directly annotated with the annotation.
-      // TODO(bcorso): Switch to using BasicAnnotationProcessor if we need more than this.
-      // Note: Switching to BasicAnnotationProcessor is currently not possible because of cyclic
-      // references to generated types in our API. For example, an @AndroidEntryPoint annotated
-      // element will indefinitely defer its own processing because it extends a generated type
-      // that it's responsible for generating.
-      checkState(MoreElements.isType(element));
-      checkState(Processors.hasAnnotation(element, ClassName.get(annotation)));
-      return new AutoValue_BaseProcessor_ProcessingState(
-          ClassName.get(annotation),
-          ClassName.get(MoreElements.asType(element)));
-    }
-
-    /** Returns the class name of the annotation. */
-    abstract ClassName annotationClassName();
-
-    /** Returns the type name of the annotated element. */
-    abstract ClassName elementClassName();
-
-    /** Returns the annotation that triggered the processing. */
-    TypeElement annotation(Elements elements) {
-      return elements.getTypeElement(elementClassName().toString());
-    }
-
-    /** Returns the annotated element to process. */
-    TypeElement element(Elements elements) {
-      return elements.getTypeElement(annotationClassName().toString());
-    }
-  }
-
-  private final Set<ProcessingState> stateToReprocess = new LinkedHashSet<>();
-  private Elements elements;
-  private Types types;
-  private Messager messager;
-  private ProcessorErrorHandler errorHandler;
-
-  /** Used to perform initialization before each round of processing. */
-  protected void preRoundProcess(RoundEnvironment roundEnv) {};
-
-  /**
-   * Called for each element in a round that uses a supported annotation.
-   *
-   * Note that an exception can be thrown for each element in the round. This is usually preferred
-   * over throwing only the first exception in a round. Only throwing the first exception in the
-   * round can lead to flaky errors that are dependent on the non-deterministic ordering that the
-   * elements are processed in.
-   */
-  protected void processEach(TypeElement annotation, Element element) throws Exception {};
-
-  /**
-   * Used to perform post processing at the end of a round. This is especially useful for handling
-   * additional processing that depends on aggregate data, that cannot be handled in #processEach().
-   *
-   * <p>Note: this will not be called if an exception is thrown during #processEach() -- if we have
-   * already detected errors on an annotated element, performing post processing on an aggregate
-   * will just produce more (perhaps non-deterministic) errors.
-   */
-  protected void postRoundProcess(RoundEnvironment roundEnv) throws Exception {};
-
-  /** @return true if you want to claim annotations after processing each round. Default false. */
-  protected boolean claimAnnotations() {
-    return false;
-  }
-
-  /**
-   * @return true if you want to delay errors to the last round. Useful if the processor
-   * generates code for symbols used a lot in the user code. Delaying allows as much code to
-   * compile as possible for correctly configured types and reduces error spam.
-   */
-  protected boolean delayErrors() {
-    return false;
-  }
-
-
-  @Override
-  public synchronized void init(ProcessingEnvironment processingEnvironment) {
-    super.init(processingEnvironment);
-    this.messager = processingEnv.getMessager();
-    this.elements = processingEnv.getElementUtils();
-    this.types = processingEnv.getTypeUtils();
-    this.errorHandler = new ProcessorErrorHandler(processingEnvironment);
-  }
-
-  @Override
-  public SourceVersion getSupportedSourceVersion() {
-    return SourceVersion.latestSupported();
-  }
-
-  /**
-   * This should not be overridden, as it defines the order of the processing.
-   */
-  @Override
-  public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
-    preRoundProcess(roundEnv);
-
-    boolean roundError = false;
-
-    // Gather the set of new and deferred elements to process, grouped by annotation.
-    SetMultimap<TypeElement, Element> elementMultiMap = LinkedHashMultimap.create();
-    for (ProcessingState processingState : stateToReprocess) {
-      elementMultiMap.put(processingState.annotation(elements), processingState.element(elements));
-    }
-    for (TypeElement annotation : annotations) {
-      elementMultiMap.putAll(annotation, roundEnv.getElementsAnnotatedWith(annotation));
-    }
-
-    // Clear the processing state before reprocessing.
-    stateToReprocess.clear();
-
-    for (Map.Entry<TypeElement, Collection<Element>> entry : elementMultiMap.asMap().entrySet()) {
-      TypeElement annotation = entry.getKey();
-      for (Element element : entry.getValue()) {
-        try {
-          processEach(annotation, element);
-        } catch (Exception e) {
-          if (e instanceof ErrorTypeException && !roundEnv.processingOver()) {
-            // Allow an extra round to reprocess to try to resolve this type.
-            stateToReprocess.add(ProcessingState.of(annotation, element));
-          } else {
-            errorHandler.recordError(e);
-            roundError = true;
-          }
-        }
-      }
-    }
-
-    if (!roundError) {
-      try {
-        postRoundProcess(roundEnv);
-      } catch (Exception e) {
-        errorHandler.recordError(e);
-      }
-    }
-
-    if (!delayErrors() || roundEnv.processingOver()) {
-      errorHandler.checkErrors();
-    }
-
-    return claimAnnotations();
-  }
-
-  /** @return the error handle for the processor. */
-  protected final ProcessorErrorHandler getErrorHandler() {
-    return errorHandler;
-  }
-
-  public final ProcessingEnvironment getProcessingEnv() {
-    return processingEnv;
-  }
-
-  public final Elements getElementUtils() {
-    return elements;
-  }
-
-  public final Types getTypeUtils() {
-    return types;
-  }
-
-  public final Messager getMessager() {
-    return messager;
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/ClassNames.java b/java/dagger/hilt/processor/internal/ClassNames.java
deleted file mode 100644
index 234ea7b..0000000
--- a/java/dagger/hilt/processor/internal/ClassNames.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import static com.squareup.javapoet.ClassName.get;
-
-import com.squareup.javapoet.ClassName;
-
-/** Holder for commonly used class names. */
-public final class ClassNames {
-  public static final ClassName ORIGINATING_ELEMENT =
-      get("dagger.hilt.codegen", "OriginatingElement");
-  public static final ClassName AGGREGATED_DEPS =
-      get("dagger.hilt.processor.internal.aggregateddeps", "AggregatedDeps");
-  public static final ClassName GENERATED_COMPONENT =
-      get("dagger.hilt.internal", "GeneratedComponent");
-  public static final ClassName GENERATED_COMPONENT_MANAGER =
-      get("dagger.hilt.internal", "GeneratedComponentManager");
-  public static final ClassName GENERATED_COMPONENT_MANAGER_HOLDER =
-      get("dagger.hilt.internal", "GeneratedComponentManagerHolder");
-  public static final ClassName IGNORE_MODULES =
-      get("dagger.hilt.android.testing", "UninstallModules");
-
-  public static final ClassName DEFINE_COMPONENT = get("dagger.hilt", "DefineComponent");
-  public static final ClassName DEFINE_COMPONENT_BUILDER =
-      get("dagger.hilt", "DefineComponent", "Builder");
-  public static final ClassName DEFINE_COMPONENT_NO_PARENT =
-      get("dagger.hilt.internal.definecomponent", "DefineComponentNoParent");
-  public static final ClassName DEFINE_COMPONENT_CLASSES =
-      get("dagger.hilt.internal.definecomponent", "DefineComponentClasses");
-
-  public static final ClassName ASSISTED_INJECT = get("dagger.assisted", "AssistedInject");
-  public static final ClassName BINDS =
-      get("dagger", "Binds");
-  public static final ClassName BINDS_OPTIONAL_OF =
-      get("dagger", "BindsOptionalOf");
-  public static final ClassName MODULE = get("dagger", "Module");
-  public static final ClassName MULTIBINDS =
-      get("dagger.multibindings", "Multibinds");
-  public static final ClassName INTO_MAP = get("dagger.multibindings", "IntoMap");
-  public static final ClassName INTO_SET = get("dagger.multibindings", "IntoSet");
-  public static final ClassName STRING_KEY = get("dagger.multibindings", "StringKey");
-  public static final ClassName PROVIDES =
-      get("dagger", "Provides");
-  public static final ClassName COMPONENT = get("dagger", "Component");
-  public static final ClassName COMPONENT_BUILDER = get("dagger", "Component", "Builder");
-  public static final ClassName SUBCOMPONENT = get("dagger", "Subcomponent");
-  public static final ClassName SUBCOMPONENT_BUILDER =
-      get("dagger", "Subcomponent", "Builder");
-  public static final ClassName PRODUCTION_COMPONENT =
-      get("dagger.producers", "ProductionComponent");
-
-  public static final ClassName CONTRIBUTES_ANDROID_INJECTOR =
-      get("dagger.android", "ContributesAndroidInjector");
-
-  public static final ClassName INJECT =
-      get("javax.inject", "Inject");
-  public static final ClassName QUALIFIER =
-      get("javax.inject", "Qualifier");
-  public static final ClassName SCOPE =
-      get("javax.inject", "Scope");
-  public static final ClassName PROVIDER = get("javax.inject", "Provider");
-  public static final ClassName DISABLE_INSTALL_IN_CHECK =
-      get("dagger.hilt.migration", "DisableInstallInCheck");
-  public static final ClassName ALIAS_OF = get("dagger.hilt.migration", "AliasOf");
-  public static final ClassName ALIAS_OF_PROPAGATED_DATA =
-      get("dagger.hilt.internal.aliasof", "AliasOfPropagatedData");
-
-  public static final ClassName GENERATES_ROOT_INPUT = get("dagger.hilt", "GeneratesRootInput");
-  public static final ClassName GENERATES_ROOT_INPUT_PROPAGATED_DATA =
-      get("dagger.hilt.internal.generatesrootinput", "GeneratesRootInputPropagatedData");
-
-  public static final ClassName ACTIVITY_SCOPED =
-      get("dagger.hilt.android.scopes", "ActivityScoped");
-  public static final ClassName FRAGMENT_SCOPED =
-      get("dagger.hilt.android.scopes", "FragmentScoped");
-  public static final ClassName SERVICE_SCOPED = get("dagger.hilt.android.scopes", "ServiceScoped");
-  public static final ClassName VIEW_SCOPED = get("dagger.hilt.android.scopes", "ViewScoped");
-
-  public static final ClassName INSTALL_IN =
-      get("dagger.hilt", "InstallIn");
-  public static final ClassName TEST_INSTALL_IN = get("dagger.hilt.testing", "TestInstallIn");
-  public static final ClassName ENTRY_POINT =
-      get("dagger.hilt", "EntryPoint");
-  public static final ClassName ENTRY_POINTS = get("dagger.hilt", "EntryPoints");
-  public static final ClassName COMPONENT_ENTRY_POINT =
-      get("dagger.hilt.internal", "ComponentEntryPoint");
-  public static final ClassName GENERATED_ENTRY_POINT =
-      get("dagger.hilt.internal", "GeneratedEntryPoint");
-  public static final ClassName UNSAFE_CASTS = get("dagger.hilt.internal", "UnsafeCasts");
-  public static final ClassName ROOT_PROCESSOR =
-      get("dagger.hilt.processor.internal.root", "RootProcessor");
-
-  public static final ClassName SINGLETON = get("javax.inject", "Singleton");
-
-  // TODO(erichang): Move these class names out when we factor out the android portion
-  public static final ClassName APPLICATION = get("android.app", "Application");
-  public static final ClassName MULTI_DEX_APPLICATION =
-      get("androidx.multidex", "MultiDexApplication");
-  public static final ClassName ANDROID_ENTRY_POINT =
-      get("dagger.hilt.android", "AndroidEntryPoint");
-  public static final ClassName HILT_ANDROID_APP =
-      get("dagger.hilt.android", "HiltAndroidApp");
-  public static final ClassName CONTEXT = get("android.content", "Context");
-  public static final ClassName APPLICATION_PROVIDER =
-      get("androidx.test.core.app", "ApplicationProvider");
-  public static final ClassName COMPONENT_SUPPLIER =
-      get("dagger.hilt.android.internal.managers", "ComponentSupplier");
-  public static final ClassName APPLICATION_CONTEXT_MODULE =
-      get("dagger.hilt.android.internal.modules", "ApplicationContextModule");
-  public static final ClassName INTERNAL_TEST_ROOT =
-      get("dagger.hilt.android.internal.testing", "InternalTestRoot");
-  public static final ClassName TEST_INJECTOR =
-      get("dagger.hilt.android.internal.testing", "TestInjector");
-  public static final ClassName TEST_APPLICATION_INJECTOR =
-      get("dagger.hilt.android.internal.testing", "TestApplicationInjector");
-  public static final ClassName TEST_APPLICATION_COMPONENT_MANAGER =
-      get("dagger.hilt.android.internal.testing", "TestApplicationComponentManager");
-  public static final ClassName TEST_APPLICATION_COMPONENT_MANAGER_HOLDER =
-      get("dagger.hilt.android.internal.testing", "TestApplicationComponentManagerHolder");
-  public static final ClassName TEST_INSTANCE_HOLDER =
-      get("dagger.hilt.android.internal.testing", "TestInstanceHolder");
-  public static final ClassName HILT_ANDROID_TEST =
-      get("dagger.hilt.android.testing", "HiltAndroidTest");
-  public static final ClassName CUSTOM_TEST_APPLICATION =
-      get("dagger.hilt.android.testing", "CustomTestApplication");
-  public static final ClassName ON_COMPONENT_READY_RUNNER =
-      get("dagger.hilt.android.testing", "OnComponentReadyRunner");
-  public static final ClassName ON_COMPONENT_READY_RUNNER_HOLDER =
-      get("dagger.hilt.android.testing", "OnComponentReadyRunner", "OnComponentReadyRunnerHolder");
-  public static final ClassName ANDROID_BIND_VALUE =
-      get("dagger.hilt.android.testing", "BindValue");
-  public static final ClassName ANDROID_BIND_ELEMENTS_INTO_SET =
-      get("dagger.hilt.android.testing", "BindElementsIntoSet");
-  public static final ClassName ANDROID_BIND_VALUE_INTO_MAP =
-      get("dagger.hilt.android.testing", "BindValueIntoMap");
-  public static final ClassName ANDROID_BIND_VALUE_INTO_SET =
-      get("dagger.hilt.android.testing", "BindValueIntoSet");
-  public static final ClassName APPLICATION_CONTEXT =
-      get("dagger.hilt.android.qualifiers", "ApplicationContext");
-  public static final ClassName TEST_COMPONENT_DATA =
-      get("dagger.hilt.android.internal.testing", "TestComponentData");
-  public static final ClassName TEST_COMPONENT_DATA_SUPPLIER =
-      get("dagger.hilt.android.internal.testing", "TestComponentDataSupplier");
-
-  public static final ClassName CLASS = get("java.lang", "Class");
-  public static final ClassName LIST = get("java.util", "List");
-  public static final ClassName SET = get("java.util", "Set");
-  public static final ClassName MAP = get("java.util", "Map");
-  public static final ClassName HASH_MAP = get("java.util", "HashMap");
-  public static final ClassName HASH_SET = get("java.util", "HashSet");
-  public static final ClassName COLLECTIONS = get("java.util", "Collections");
-  public static final ClassName ARRAYS = get("java.util", "Arrays");
-
-  // Standard components
-  public static final ClassName SINGLETON_COMPONENT =
-      get("dagger.hilt.components", "SingletonComponent");
-  public static final ClassName ACTIVITY_COMPONENT =
-      get("dagger.hilt.android.components", "ActivityComponent");
-
-  public static final ClassName PRECONDITIONS = get("dagger.hilt.internal", "Preconditions");
-
-  public static final ClassName OBJECT = get("java.lang", "Object");
-
-  // Kotlin-specific class names
-  public static final ClassName KOTLIN_METADATA = get("kotlin", "Metadata");
-
-  private ClassNames() {}
-}
diff --git a/java/dagger/hilt/processor/internal/ComponentDescriptor.java b/java/dagger/hilt/processor/internal/ComponentDescriptor.java
deleted file mode 100644
index 5d3cef9..0000000
--- a/java/dagger/hilt/processor/internal/ComponentDescriptor.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import java.util.Optional;
-
-// TODO(bcorso): Reduce the visibility of this class and return ClassNames instead.
-// TODO(erichang): Rename this class so it doesn't conflict with
-// dagger.internal.codegen.ComponentDescriptor
-/** Represents a single component in the hierarchy. */
-@AutoValue
-public abstract class ComponentDescriptor {
-  public static Builder builder() {
-    return new AutoValue_ComponentDescriptor.Builder()
-        .scopes(ImmutableSet.of());
-  }
-
-  /** Returns the {@link ClassName} for this component descriptor. */
-  public abstract ClassName component();
-
-  /** Returns the {@link ClassName}s for the scopes of this component descriptor. */
-  public abstract ImmutableSet<ClassName> scopes();
-
-  /** Returns the {@link ClassName} for the creator interface. if it exists. */
-  public abstract Optional<ClassName> creator();
-
-  /** Returns the {@link ClassName} for the parent, if it exists. */
-  public abstract Optional<ComponentDescriptor> parent();
-
-  /** Returns {@code true} if the descriptor represents a root component. */
-  public boolean isRoot() {
-    return !parent().isPresent();
-  }
-
-  /**
-   * Returns {@code true} if the given {@link ComponentDescriptor} represents the same {@link
-   * #component()}.
-   */
-  // TODO(b/144939893): Remove equals and hashcode once we have unique ComponentDescriptor instances
-  @Override
-  public final boolean equals(Object obj) {
-    if (obj == this) {
-      return true;
-    }
-    if (!(obj instanceof ComponentDescriptor)) {
-      return false;
-    }
-    ComponentDescriptor that = (ComponentDescriptor) obj;
-
-    // Only check the component name, which should map 1:1 to each component descriptor created
-    // by DefineComponents#componentDescriptor(Element). However, if users are building their own
-    // ComponentDescriptors manually, then this might not be true. We should lock down the builder
-    // method to avoid that.
-    return component().equals(that.component());
-  }
-
-  @Override
-  public final int hashCode() {
-    return component().hashCode();
-  }
-
-  /** Builder for ComponentDescriptor. */
-  @AutoValue.Builder
-  public interface Builder {
-    Builder component(ClassName component);
-
-    Builder scopes(ImmutableSet<ClassName> scopes);
-
-    Builder scopes(ClassName... scopes);
-
-    Builder creator(ClassName creator);
-
-    Builder parent(ComponentDescriptor parent);
-
-
-    ComponentDescriptor build();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/ComponentGenerator.java b/java/dagger/hilt/processor/internal/ComponentGenerator.java
deleted file mode 100644
index 3a4bf1e..0000000
--- a/java/dagger/hilt/processor/internal/ComponentGenerator.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static java.util.Comparator.comparing;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Utf8;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-
-/** Generates a Dagger component or subcomponent interface. */
-// TODO(bcorso): Make this non-public
-public final class ComponentGenerator {
-  private static final Joiner JOINER = Joiner.on(".");
-  private static final Comparator<ClassName> SIMPLE_NAME_SORTER =
-      Comparator.comparing((ClassName c) -> JOINER.join(c.simpleNames()))
-          .thenComparing(ClassName::compareTo);
-  private static final Comparator<TypeName> TYPE_NAME_SORTER = comparing(TypeName::toString);
-
-  private final ProcessingEnvironment processingEnv;
-  private final ClassName name;
-  private final TypeElement rootElement;
-  private final Optional<ClassName> superclass;
-  private final ImmutableList<ClassName> modules;
-  private final ImmutableList<TypeName> entryPoints;
-  private final ImmutableCollection<ClassName> scopes;
-  private final ImmutableList<AnnotationSpec> extraAnnotations;
-  private final ClassName componentAnnotation;
-  private final Optional<TypeSpec> componentBuilder;
-
-  public ComponentGenerator(
-      ProcessingEnvironment processingEnv,
-      ClassName name,
-      TypeElement rootElement,
-      Optional<ClassName> superclass,
-      Set<? extends ClassName> modules,
-      Set<? extends TypeName> entryPoints,
-      ImmutableCollection<ClassName> scopes,
-      ImmutableList<AnnotationSpec> extraAnnotations,
-      ClassName componentAnnotation,
-      Optional<TypeSpec> componentBuilder) {
-    this.processingEnv = processingEnv;
-    this.name = name;
-    this.rootElement = rootElement;
-    this.superclass = superclass;
-    this.modules = modules.stream().sorted(SIMPLE_NAME_SORTER).collect(toImmutableList());
-    this.entryPoints = entryPoints.stream().sorted(TYPE_NAME_SORTER).collect(toImmutableList());
-    this.scopes = scopes;
-    this.extraAnnotations = extraAnnotations;
-    this.componentAnnotation = componentAnnotation;
-    this.componentBuilder = componentBuilder;
-  }
-
-  public TypeSpec generate() throws IOException {
-    TypeSpec.Builder generator =
-        TypeSpec.classBuilder(name)
-            // Public because components from a scope below must reference to create
-            .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
-            .addOriginatingElement(rootElement)
-            .addAnnotation(getComponentAnnotation());
-
-    componentBuilder.ifPresent(generator::addType);
-
-    scopes.forEach(generator::addAnnotation);
-
-    addEntryPoints(generator);
-
-    superclass.ifPresent(generator::superclass);
-
-    generator.addAnnotations(extraAnnotations);
-
-    return generator.build();
-  }
-
-  /** Returns the component annotation with the list of modules to install for the component. */
-  private AnnotationSpec getComponentAnnotation() {
-    AnnotationSpec.Builder builder = AnnotationSpec.builder(componentAnnotation);
-    modules.forEach(module -> builder.addMember("modules", "$T.class", module));
-    return builder.build();
-  }
-
-  /**
-   * Adds entry points to the component.
-   *
-   * See b/140979968. If the entry points exceed 65763 bytes, we have to partition them to avoid the
-   * limit. To be safe, we split at 60000 bytes.
-   */
-  private void addEntryPoints(TypeSpec.Builder builder) throws IOException {
-    int currBytes = 0;
-    List<Integer> partitionIndexes = new ArrayList<>();
-
-    partitionIndexes.add(0);
-    for (int i = 0; i < entryPoints.size(); i++) {
-      // This over estimates the actual length because it includes the fully qualified name (FQN).
-      // TODO(bcorso): Have a better way to estimate the upper bound. For example, most types will
-      // not include the FQN, but we'll have to consider all of the different subtypes of TypeName,
-      // simple name collisions, etc...
-      int nextBytes = Utf8.encodedLength(entryPoints.get(i).toString());
-
-      // To be safe, we split at 60000 to account for the component name, spaces, commas, etc...
-      if (currBytes + nextBytes > 60000) {
-        partitionIndexes.add(i);
-        currBytes = 0;
-      }
-
-      currBytes += nextBytes;
-    }
-    partitionIndexes.add(entryPoints.size());
-
-    if (partitionIndexes.size() <= 2) {
-      // No extra partitions are needed, so just add all of the entrypoints as is.
-      builder.addSuperinterfaces(entryPoints);
-    } else {
-      // Create interfaces for each partition.
-      // The partitioned interfaces will be added to the component instead of the real entry points.
-      for (int i = 1; i < partitionIndexes.size(); i++) {
-        int startIndex = partitionIndexes.get(i - 1);
-        int endIndex = partitionIndexes.get(i);
-        builder.addSuperinterface(
-            createPartitionInterface(entryPoints.subList(startIndex, endIndex), i));
-      }
-    }
-  }
-
-  private ClassName createPartitionInterface(List<TypeName> partition, int partitionIndex)
-      throws IOException {
-    // TODO(bcorso): Nest the partion inside the HiltComponents wrapper rather than appending name
-    ClassName partitionName =
-        Processors.append(
-            Processors.getEnclosedClassName(name), "_EntryPointPartition" + partitionIndex);
-    TypeSpec.Builder builder =
-        TypeSpec.interfaceBuilder(partitionName)
-            .addOriginatingElement(rootElement)
-            .addModifiers(Modifier.ABSTRACT)
-            .addSuperinterfaces(partition);
-
-    Processors.addGeneratedAnnotation(builder, processingEnv, ClassNames.ROOT_PROCESSOR.toString());
-
-    JavaFile.builder(name.packageName(), builder.build()).build().writeTo(processingEnv.getFiler());
-    return partitionName;
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/ComponentNames.java b/java/dagger/hilt/processor/internal/ComponentNames.java
deleted file mode 100644
index fab4d19..0000000
--- a/java/dagger/hilt/processor/internal/ComponentNames.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal;
-
-import com.squareup.javapoet.ClassName;
-
-/**
- * Utility class for getting the generated component name.
- *
- * <p>This should not be used externally.
- */
-public final class ComponentNames {
-  private ComponentNames() {}
-
-  /** Returns the name of the generated component wrapper. */
-  public static ClassName generatedComponentsWrapper(ClassName root) {
-    return Processors.append(Processors.getEnclosedClassName(root), "_HiltComponents");
-  }
-
-  /** Returns the name of the generated component. */
-  public static ClassName generatedComponent(ClassName root, ClassName component) {
-    return generatedComponentsWrapper(root).nestedClass(componentName(component));
-  }
-
-  /**
-   * Returns the shortened component name by replacing the ending "Component" with "C" if it exists.
-   *
-   * <p>This is a hack because nested subcomponents in Dagger generate extremely long class names
-   * that hit the 256 character limit.
-   */
-  // TODO(bcorso): See if this issue can be fixed in Dagger, e.g. by using static subcomponents.
-  private static String componentName(ClassName component) {
-    // TODO(bcorso): How do we want to handle collisions across packages? Currently, we only handle
-    // collisions across enclosing elements since namespacing by package would likely lead to too
-    // long of class names.
-    // Note: This uses regex matching so we only match if the name ends in "Component"
-    return Processors.getEnclosedName(component).replaceAll("Component$", "C");
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/ComponentTree.java b/java/dagger/hilt/processor/internal/ComponentTree.java
deleted file mode 100644
index 6d2137a..0000000
--- a/java/dagger/hilt/processor/internal/ComponentTree.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.graph.GraphBuilder;
-import com.google.common.graph.Graphs;
-import com.google.common.graph.ImmutableGraph;
-import com.google.common.graph.MutableGraph;
-import com.squareup.javapoet.ClassName;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/** A representation of the full tree of scopes. */
-public final class ComponentTree {
-  private final ImmutableGraph<ComponentDescriptor> graph;
-  private final ComponentDescriptor root;
-
-  /** Creates a new tree from a set of descriptors. */
-  public static ComponentTree from(Set<ComponentDescriptor> descriptors) {
-    MutableGraph<ComponentDescriptor> graph =
-        GraphBuilder.directed().allowsSelfLoops(false).build();
-
-    descriptors.forEach(
-        descriptor -> {
-          graph.addNode(descriptor);
-          descriptor.parent().ifPresent(parent -> graph.putEdge(parent, descriptor));
-        });
-
-    return new ComponentTree(ImmutableGraph.copyOf(graph));
-  }
-
-  private ComponentTree(ImmutableGraph<ComponentDescriptor> graph) {
-    this.graph = Preconditions.checkNotNull(graph);
-    Preconditions.checkState(
-        !Graphs.hasCycle(graph),
-        "Component graph has cycles: %s",
-        graph.nodes());
-
-    // Check that each component has a unique descriptor
-    Map<ClassName, ComponentDescriptor> descriptors = new HashMap<>();
-    for (ComponentDescriptor descriptor : graph.nodes()) {
-      if (descriptors.containsKey(descriptor.component())) {
-        ComponentDescriptor prevDescriptor = descriptors.get(descriptor.component());
-        Preconditions.checkState(
-            // TODO(b/144939893): Use "==" instead of ".equals()"?
-            descriptor.equals(prevDescriptor),
-            "%s has mismatching descriptors:\n"
-            + "    %s\n\n"
-            + "    %s\n\n",
-            prevDescriptor.component(),
-            prevDescriptor,
-            descriptor);
-      }
-      descriptors.put(descriptor.component(), descriptor);
-    }
-
-    ImmutableList<ComponentDescriptor> roots =
-        graph.nodes().stream()
-            .filter(node -> graph.inDegree(node) == 0)
-            .collect(toImmutableList());
-
-    Preconditions.checkState(
-        roots.size() == 1,
-        "Component graph must have exactly 1 root. Found: %s",
-        roots.stream().map(ComponentDescriptor::component).collect(toImmutableList()));
-
-    root = Iterables.getOnlyElement(roots);
-  }
-
-  public ImmutableSet<ComponentDescriptor> getComponentDescriptors() {
-    return ImmutableSet.copyOf(graph.nodes());
-  }
-
-  public ImmutableSet<ComponentDescriptor> childrenOf(ComponentDescriptor componentDescriptor) {
-    return ImmutableSet.copyOf(graph.successors(componentDescriptor));
-  }
-
-  public ImmutableGraph<ComponentDescriptor> graph() {
-    return graph;
-  }
-
-  public ComponentDescriptor root() {
-    return root;
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/Components.java b/java/dagger/hilt/processor/internal/Components.java
deleted file mode 100644
index 661dd8a..0000000
--- a/java/dagger/hilt/processor/internal/Components.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.definecomponent.DefineComponents;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.Elements;
-
-/** Helper methods for defining components and the component hierarchy. */
-public final class Components {
-  // TODO(bcorso): Remove this once all usages are replaced with #getComponents().
-  /**
-   * Returns the {@link ComponentDescriptor}s for a given element annotated with {@link
-   * dagger.hilt.InstallIn}.
-   */
-  public static ImmutableSet<ComponentDescriptor> getComponentDescriptors(
-      Elements elements, Element element) {
-    DefineComponents defineComponents = DefineComponents.create();
-    return getComponents(elements, element).stream()
-        .map(component -> elements.getTypeElement(component.canonicalName()))
-        // TODO(b/144939893): Memoize ComponentDescriptors so we're not recalculating.
-        .map(defineComponents::componentDescriptor)
-        .collect(toImmutableSet());
-  }
-
-  /** Returns the {@link dagger.hilt.InstallIn} components for a given element. */
-  public static ImmutableSet<ClassName> getComponents(Elements elements, Element element) {
-    ImmutableSet<ClassName> components;
-    if (Processors.hasAnnotation(element, ClassNames.INSTALL_IN)
-        || Processors.hasAnnotation(element, ClassNames.TEST_INSTALL_IN)) {
-      components = getHiltInstallInComponents(elements, element);
-    } else {
-      // Check the enclosing element in case it passed in module is a companion object. This helps
-      // in cases where the element was arrived at by checking a binding method and moving outward.
-      Element enclosing = element.getEnclosingElement();
-      if (enclosing != null
-          && MoreElements.isType(enclosing)
-          && MoreElements.isType(element)
-          && Processors.hasAnnotation(enclosing, ClassNames.MODULE)
-          && KotlinMetadataUtils.getMetadataUtil().isCompanionObjectClass(
-              MoreElements.asType(element))) {
-        return getComponents(elements, enclosing);
-      }
-      if (Processors.hasErrorTypeAnnotation(element)) {
-        throw new BadInputException(
-            "Error annotation found on element " + element + ". Look above for compilation errors",
-            element);
-      } else {
-        throw new BadInputException(
-            String.format(
-                "An @InstallIn annotation is required for: %s." ,
-                element),
-            element);
-      }
-    }
-
-    return components;
-  }
-
-  public static AnnotationSpec getInstallInAnnotationSpec(ImmutableSet<ClassName> components) {
-    Preconditions.checkArgument(!components.isEmpty());
-    AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassNames.INSTALL_IN);
-    components.forEach(component -> builder.addMember("value", "$T.class", component));
-    return builder.build();
-  }
-
-  private static ImmutableSet<ClassName> getHiltInstallInComponents(
-      Elements elements, Element element) {
-    Preconditions.checkArgument(
-        Processors.hasAnnotation(element, ClassNames.INSTALL_IN)
-            || Processors.hasAnnotation(element, ClassNames.TEST_INSTALL_IN));
-
-    ImmutableSet<TypeElement> components =
-        ImmutableSet.copyOf(
-            Processors.hasAnnotation(element, ClassNames.INSTALL_IN)
-                ? Processors.getAnnotationClassValues(
-                    elements,
-                    Processors.getAnnotationMirror(element, ClassNames.INSTALL_IN),
-                    "value")
-                : Processors.getAnnotationClassValues(
-                    elements,
-                    Processors.getAnnotationMirror(element, ClassNames.TEST_INSTALL_IN),
-                    "components"));
-
-    ImmutableSet<TypeElement> undefinedComponents =
-        components.stream()
-            .filter(component -> !Processors.hasAnnotation(component, ClassNames.DEFINE_COMPONENT))
-            .collect(toImmutableSet());
-
-    ProcessorErrors.checkState(
-        undefinedComponents.isEmpty(),
-        element,
-        "@InstallIn, can only be used with @DefineComponent-annotated classes, but found: %s",
-        undefinedComponents);
-
-    return components.stream().map(ClassName::get).collect(toImmutableSet());
-  }
-
-  private Components() {}
-}
diff --git a/java/dagger/hilt/processor/internal/ErrorTypeException.java b/java/dagger/hilt/processor/internal/ErrorTypeException.java
deleted file mode 100644
index 6f8f67e..0000000
--- a/java/dagger/hilt/processor/internal/ErrorTypeException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import javax.lang.model.element.Element;
-
-/**
- * Exception to throw when a required {@link Element} is or inherits from an error kind.
- *
- * <p>Includes element to point to for the cause of the error
- */
-public final class ErrorTypeException extends RuntimeException {
-  private final Element badElement;
-
-  public ErrorTypeException(String message, Element badElement) {
-    super(message);
-    this.badElement = badElement;
-  }
-
-  public Element getBadElement() {
-    return badElement;
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/KotlinMetadataUtils.java b/java/dagger/hilt/processor/internal/KotlinMetadataUtils.java
deleted file mode 100644
index ec5ddf8..0000000
--- a/java/dagger/hilt/processor/internal/KotlinMetadataUtils.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal;
-
-import dagger.Component;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import javax.inject.Singleton;
-
-/** A single-use provider of {@link KotlinMetadataUtil}. */
-// TODO(erichang):  Revert this, should be wrapped with a Dagger module.
-public final class KotlinMetadataUtils {
-
-  @Singleton
-  @Component
-  interface MetadataComponent {
-    KotlinMetadataUtil get();
-  }
-
-  /** Gets the metadata util. */
-  public static KotlinMetadataUtil getMetadataUtil() {
-    return DaggerKotlinMetadataUtils_MetadataComponent.create().get();
-  }
-
-  private KotlinMetadataUtils() {}
-}
diff --git a/java/dagger/hilt/processor/internal/ProcessorErrorHandler.java b/java/dagger/hilt/processor/internal/ProcessorErrorHandler.java
deleted file mode 100644
index 460e8a9..0000000
--- a/java/dagger/hilt/processor/internal/ProcessorErrorHandler.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Throwables;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import javax.annotation.processing.Messager;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.util.Elements;
-import javax.tools.Diagnostic.Kind;
-
-/** Utility class to handle keeping track of errors during processing. */
-final class ProcessorErrorHandler {
-
-  private static final String FAILURE_PREFIX = "[Hilt]\n";
-
-  // Special characters to make the tag red and bold to draw attention since
-  // this error can get drowned out by other errors resulting from missing
-  // symbols when we can't generate code.
-  private static final String FAILURE_SUFFIX =
-      "\n\033[1;31m[Hilt] Processing did not complete. See error above for details.\033[0m";
-
-  private final Messager messager;
-  private final Elements elements;
-  private final List<HiltError> hiltErrors;
-
-  ProcessorErrorHandler(ProcessingEnvironment env) {
-    this.messager = env.getMessager();
-    this.elements = env.getElementUtils();
-    this.hiltErrors = new ArrayList<>();
-  }
-
-  /**
-   * Records an error message for some exception to the messager. This can be used to handle
-   * exceptions gracefully that would otherwise be propagated out of the {@code process} method. The
-   * message is stored in order to allow the build to continue as far as it can. The build will be
-   * failed with a {@link Kind#ERROR} in {@link #checkErrors} if an error was recorded with this
-   * method.
-   */
-  void recordError(Throwable t) {
-    // Store messages to allow the build to continue as far as it can. The build will
-    // be failed in checkErrors when processing is over.
-
-    if (t instanceof BadInputException) {
-      BadInputException badInput = (BadInputException) t;
-      for (Element element : badInput.getBadElements()) {
-        hiltErrors.add(HiltError.of(badInput.getMessage(), element));
-      }
-    } else if (t instanceof ErrorTypeException) {
-      ErrorTypeException badInput = (ErrorTypeException) t;
-      hiltErrors.add(HiltError.of(badInput.getMessage(), badInput.getBadElement()));
-    } else if (t.getMessage() != null) {
-      hiltErrors.add(HiltError.of(t.getMessage() + ": " + Throwables.getStackTraceAsString(t)));
-    } else {
-      hiltErrors.add(HiltError.of(t.getClass() + ": " + Throwables.getStackTraceAsString(t)));
-    }
-  }
-
-  /** Checks for any recorded errors. This should be called at the end of process every round. */
-  void checkErrors() {
-    if (!hiltErrors.isEmpty()) {
-      hiltErrors.forEach(
-          hiltError -> {
-            if (hiltError.element().isPresent()) {
-              Element element = hiltError.element().get();
-              if (MoreElements.isType(element)) {
-                // If the error type is a TypeElement, get a new one just in case it was thrown in a
-                // previous round we can report the correct instance. Otherwise, this leads to
-                // issues in AndroidStudio when linking an error to the proper element.
-                // TODO(bcorso): Consider only allowing TypeElement errors when delaying errors,
-                // or maybe even removing delayed errors altogether.
-                element =
-                    elements.getTypeElement(
-                        MoreElements.asType(element).getQualifiedName().toString());
-              }
-              messager.printMessage(Kind.ERROR, hiltError.message(), element);
-            } else {
-              messager.printMessage(Kind.ERROR, hiltError.message());
-            }
-          });
-      hiltErrors.clear();
-    }
-  }
-
-  @AutoValue
-  abstract static class HiltError {
-    static HiltError of(String message) {
-      return of(message, Optional.empty());
-    }
-
-    static HiltError of(String message, Element element) {
-      return of(message, Optional.of(element));
-    }
-
-    private static HiltError of(String message, Optional<Element> element) {
-      return new AutoValue_ProcessorErrorHandler_HiltError(
-          FAILURE_PREFIX + message + FAILURE_SUFFIX, element);
-    }
-
-    abstract String message();
-
-    abstract Optional<Element> element();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/ProcessorErrors.java b/java/dagger/hilt/processor/internal/ProcessorErrors.java
deleted file mode 100644
index b1578da..0000000
--- a/java/dagger/hilt/processor/internal/ProcessorErrors.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.errorprone.annotations.FormatMethod;
-import com.google.errorprone.annotations.FormatString;
-import java.util.Collection;
-import java.util.stream.Collectors;
-import javax.annotation.Nullable;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-
-/** Static helper methods for throwing errors during code generation. */
-public final class ProcessorErrors {
-  /**
-   * Ensures the truth of an expression involving the state of the calling instance, but not
-   * involving any parameters to the calling method.
-   *
-   * @param expression a boolean expression
-   * @param badElement the element that was at fault
-   * @param errorMessage the exception message to use if the check fails; will be converted to a
-   *     string using {@link String#valueOf(Object)}
-   * @throws BadInputException if {@code expression} is false
-   */
-  public static void checkState(
-      boolean expression,
-      Element badElement,
-      @Nullable Object errorMessage) {
-    Preconditions.checkNotNull(badElement);
-    if (!expression) {
-      throw new BadInputException(String.valueOf(errorMessage), badElement);
-    }
-  }
-
-  /**
-   * Ensures the truth of an expression involving the state of the calling instance, but not
-   * involving any parameters to the calling method.
-   *
-   * <p>e.g. checkState(foo.isABar(), "Failed because of %s is not a bar", foo);
-   *
-   * @param expression a boolean expression
-   * @param badElement the element that was at fault
-   * @param errorMessageTemplate a template for the exception message should the check fail. The
-   *     message is formed by replacing each {@code %s} placeholder in the template with an
-   *     argument. These are matched by position - the first {@code %s} gets {@code
-   *     errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message in
-   *     square braces. Unmatched placeholders will be left as-is.
-   * @param errorMessageArgs the arguments to be substituted into the message template. Arguments
-   *     are converted to strings using {@link String#valueOf(Object)}.
-   * @throws BadInputException if {@code expression} is false
-   * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
-   *     {@code errorMessageArgs} is null (don't let this happen)
-   */
-  @FormatMethod
-  public static void checkState(
-      boolean expression,
-      Element badElement,
-      @Nullable @FormatString String errorMessageTemplate,
-      @Nullable Object... errorMessageArgs) {
-    Preconditions.checkNotNull(badElement);
-    if (!expression) {
-      throw new BadInputException(
-          String.format(errorMessageTemplate, errorMessageArgs), badElement);
-    }
-  }
-
-  /**
-   * Ensures the truth of an expression involving the state of the calling instance, but not
-   * involving any parameters to the calling method.
-   *
-   * @param expression a boolean expression
-   * @param badElements the element that were at fault
-   * @param errorMessage the exception message to use if the check fails; will be converted to a
-   *     string using {@link String#valueOf(Object)}
-   * @throws BadInputException if {@code expression} is false
-   */
-  public static void checkState(
-      boolean expression,
-      Collection<? extends Element> badElements,
-      @Nullable Object errorMessage) {
-    Preconditions.checkNotNull(badElements);
-    if (!expression) {
-      Preconditions.checkState(!badElements.isEmpty());
-      throw new BadInputException(String.valueOf(errorMessage), badElements);
-    }
-  }
-
-  /**
-   * Ensures the truth of an expression involving the state of the calling instance, but not
-   * involving any parameters to the calling method.
-   *
-   * @param expression a boolean expression
-   * @param badElements the elements that were at fault
-   * @param errorMessageTemplate a template for the exception message should the check fail. The
-   *     message is formed by replacing each {@code %s} placeholder in the template with an
-   *     argument. These are matched by position - the first {@code %s} gets {@code
-   *     errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message in
-   *     square braces. Unmatched placeholders will be left as-is.
-   * @param errorMessageArgs the arguments to be substituted into the message template. Arguments
-   *     are converted to strings using {@link String#valueOf(Object)}.
-   * @throws BadInputException if {@code expression} is false
-   * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
-   *     {@code errorMessageArgs} is null (don't let this happen)
-   */
-  @FormatMethod
-  public static void checkState(
-      boolean expression,
-      Collection<? extends Element> badElements,
-      @Nullable @FormatString String errorMessageTemplate,
-      @Nullable Object... errorMessageArgs) {
-    Preconditions.checkNotNull(badElements);
-    if (!expression) {
-      Preconditions.checkState(!badElements.isEmpty());
-      throw new BadInputException(
-          String.format(errorMessageTemplate, errorMessageArgs), badElements);
-    }
-  }
-
-  /**
-   * Ensures that the given element is not an error kind and does not inherit from an error kind.
-   *
-   * @param element the element to check
-   * @throws ErrorTypeException if {@code element} inherits from an error kind.
-   */
-  public static void checkNotErrorKind(TypeElement element) {
-    TypeMirror currType = element.asType();
-    ImmutableList.Builder<String> typeHierarchy = ImmutableList.builder();
-    while (currType.getKind() != TypeKind.NONE) {
-      typeHierarchy.add(currType.toString());
-      if (currType.getKind() == TypeKind.ERROR) {
-        throw new ErrorTypeException(
-            String.format(
-                "%s, type hierarchy contains error kind, %s."
-                + "\n\tThe partially resolved hierarchy is:\n\t\t%s",
-                element,
-                currType,
-                typeHierarchy.build().stream().collect(Collectors.joining(" -> "))),
-            element);
-      }
-      currType = MoreTypes.asTypeElement(currType).getSuperclass();
-    }
-  }
-
-  private ProcessorErrors() {}
-}
diff --git a/java/dagger/hilt/processor/internal/Processors.java b/java/dagger/hilt/processor/internal/Processors.java
deleted file mode 100644
index b33c19d..0000000
--- a/java/dagger/hilt/processor/internal/Processors.java
+++ /dev/null
@@ -1,940 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import static com.google.auto.common.MoreElements.asPackage;
-import static com.google.auto.common.MoreElements.asVariable;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.AnnotationMirrors;
-import com.google.auto.common.GeneratedAnnotations;
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.base.CaseFormat;
-import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.SetMultimap;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.extension.DaggerStreams;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import java.lang.annotation.Annotation;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.annotation.processing.RoundEnvironment;
-import javax.inject.Qualifier;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ErrorType;
-import javax.lang.model.type.PrimitiveType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.SimpleAnnotationValueVisitor7;
-import javax.lang.model.util.SimpleTypeVisitor7;
-
-/** Static helper methods for writing a processor. */
-public final class Processors {
-
-  public static final String CONSTRUCTOR_NAME = "<init>";
-
-  public static final String STATIC_INITIALIZER_NAME = "<clinit>";
-
-  private static final String JAVA_CLASS = "java.lang.Class";
-
-  /** Returns a map from {@link AnnotationMirror} attribute name to {@link AnnotationValue}s */
-  public static ImmutableMap<String, AnnotationValue> getAnnotationValues(Elements elements,
-      AnnotationMirror annotation) {
-    ImmutableMap.Builder<String, AnnotationValue> annotationMembers = ImmutableMap.builder();
-    for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e
-        : elements.getElementValuesWithDefaults(annotation).entrySet()) {
-      annotationMembers.put(e.getKey().getSimpleName().toString(), e.getValue());
-    }
-    return annotationMembers.build();
-  }
-
-  /**
-   * Returns a multimap from attribute name to the values that are an array of annotation mirrors.
-   * The returned map will not contain mappings for any attributes that are not Annotation Arrays.
-   *
-   * <p>e.g. if the input was the annotation mirror for
-   * <pre>
-   *   {@literal @}Foo({{@literal @}Bar("hello"), {@literal @}Bar("world")})
-   * </pre>
-   * the map returned would have "value" map to a set containing the two @Bar annotation mirrors.
-   */
-  public static Multimap<String, AnnotationMirror> getAnnotationAnnotationArrayValues(
-      Elements elements, AnnotationMirror annotation) {
-    SetMultimap<String, AnnotationMirror> annotationMembers = LinkedHashMultimap.create();
-    for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e
-        : elements.getElementValuesWithDefaults(annotation).entrySet()) {
-      String attribute = e.getKey().getSimpleName().toString();
-      Set<AnnotationMirror> annotationMirrors = new LinkedHashSet<>();
-      e.getValue().accept(new AnnotationMirrorAnnotationValueVisitor(), annotationMirrors);
-      annotationMembers.putAll(attribute, annotationMirrors);
-    }
-    return annotationMembers;
-  }
-
-  private static final class AnnotationMirrorAnnotationValueVisitor
-      extends SimpleAnnotationValueVisitor7<Void, Set<AnnotationMirror>> {
-
-    @Override
-    public Void visitArray(List<? extends AnnotationValue> vals, Set<AnnotationMirror> types) {
-      for (AnnotationValue val : vals) {
-        val.accept(this, types);
-      }
-      return null;
-    }
-
-    @Override
-    public Void visitAnnotation(AnnotationMirror a, Set<AnnotationMirror> annotationMirrors) {
-      annotationMirrors.add(a);
-      return null;
-    }
-  }
-
-  /** Returns the {@link TypeElement} for a class attribute on an annotation. */
-  public static TypeElement getAnnotationClassValue(
-      Elements elements, AnnotationMirror annotation, String key) {
-    return Iterables.getOnlyElement(getAnnotationClassValues(elements, annotation, key));
-  }
-
-  /** Returns a list of {@link TypeElement}s for a class attribute on an annotation. */
-  public static ImmutableList<TypeElement> getAnnotationClassValues(
-      Elements elements, AnnotationMirror annotation, String key) {
-    ImmutableList<TypeElement> values = getOptionalAnnotationClassValues(elements, annotation, key);
-
-    ProcessorErrors.checkState(
-        values.size() >= 1,
-        // TODO(b/152801981): Point to the annotation value rather than the annotated element.
-        annotation.getAnnotationType().asElement(),
-        "@%s, '%s' class is invalid or missing: %s",
-        annotation.getAnnotationType().asElement().getSimpleName(),
-        key,
-        annotation);
-
-    return values;
-  }
-
-  /** Returns a multimap from attribute name to elements for class valued attributes. */
-  private static Multimap<String, DeclaredType> getAnnotationClassValues(
-      Elements elements, AnnotationMirror annotation) {
-    Element javaClass = elements.getTypeElement(JAVA_CLASS);
-    SetMultimap<String, DeclaredType> annotationMembers = LinkedHashMultimap.create();
-    for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e :
-        elements.getElementValuesWithDefaults(annotation).entrySet()) {
-      Optional<DeclaredType> returnType = getOptionalDeclaredType(e.getKey().getReturnType());
-      if (returnType.isPresent() && returnType.get().asElement().equals(javaClass)) {
-        String attribute = e.getKey().getSimpleName().toString();
-        Set<DeclaredType> declaredTypes = new LinkedHashSet<DeclaredType>();
-        e.getValue().accept(new DeclaredTypeAnnotationValueVisitor(), declaredTypes);
-        annotationMembers.putAll(attribute, declaredTypes);
-      }
-    }
-    return annotationMembers;
-  }
-
-  /** Returns an optional {@link TypeElement} for a class attribute on an annotation. */
-  public static Optional<TypeElement> getOptionalAnnotationClassValue(
-      Elements elements, AnnotationMirror annotation, String key) {
-    return getAnnotationClassValues(elements, annotation).get(key).stream()
-        .map(MoreTypes::asTypeElement)
-        .collect(toOptional());
-  }
-
-  /** Returns a list of {@link TypeElement}s for a class attribute on an annotation. */
-  public static ImmutableList<TypeElement> getOptionalAnnotationClassValues(
-      Elements elements, AnnotationMirror annotation, String key) {
-    return ImmutableList.copyOf(
-        getAnnotationClassValues(elements, annotation).get(key).stream()
-            .map(MoreTypes::asTypeElement)
-            .collect(Collectors.toList()));
-  }
-
-  private static final class DeclaredTypeAnnotationValueVisitor
-      extends SimpleAnnotationValueVisitor7<Void, Set<DeclaredType>> {
-
-    @Override public Void visitArray(
-        List<? extends AnnotationValue> vals, Set<DeclaredType> types) {
-      for (AnnotationValue val : vals) {
-        val.accept(this, types);
-      }
-      return null;
-    }
-
-    @Override public Void visitType(TypeMirror t, Set<DeclaredType> types) {
-      DeclaredType declared = MoreTypes.asDeclared(t);
-      checkNotNull(declared);
-      types.add(declared);
-      return null;
-    }
-  }
-
-  /**
-   * If the received mirror represents a primitive type or an array of primitive types, this returns
-   * the represented primitive type. Otherwise throws an IllegalStateException.
-   */
-  public static PrimitiveType getPrimitiveType(TypeMirror type) {
-    return type.accept(
-        new SimpleTypeVisitor7<PrimitiveType, Void> () {
-          @Override public PrimitiveType visitArray(ArrayType type, Void unused) {
-            return getPrimitiveType(type.getComponentType());
-          }
-
-          @Override public PrimitiveType visitPrimitive(PrimitiveType type, Void unused) {
-            return type;
-          }
-
-          @Override public PrimitiveType defaultAction(TypeMirror type, Void unused) {
-            throw new IllegalStateException("Unhandled type: " + type);
-          }
-        }, null /* the Void accumulator */);
-  }
-
-  /**
-   * Returns an {@link Optional#of} the declared type if the received mirror represents a declared
-   * type or an array of declared types, otherwise returns {@link Optional#empty}.
-   */
-  public static Optional<DeclaredType> getOptionalDeclaredType(TypeMirror type) {
-    return Optional.ofNullable(
-        type.accept(
-            new SimpleTypeVisitor7<DeclaredType, Void>(null /* defaultValue */) {
-              @Override
-              public DeclaredType visitArray(ArrayType type, Void unused) {
-                return MoreTypes.asDeclared(type.getComponentType());
-              }
-
-              @Override
-              public DeclaredType visitDeclared(DeclaredType type, Void unused) {
-                return type;
-              }
-
-              @Override
-              public DeclaredType visitError(ErrorType type, Void unused) {
-                return type;
-              }
-            },
-            null /* the Void accumulator */));
-  }
-
-  /**
-   * Returns the declared type if the received mirror represents a declared type or an array of
-   * declared types, otherwise throws an {@link IllegalStateException}.
-   */
-  public static DeclaredType getDeclaredType(TypeMirror type) {
-    return getOptionalDeclaredType(type)
-        .orElseThrow(() -> new IllegalStateException("Not a declared type: " + type));
-  }
-
-  /** Gets the values from an annotation value representing a string array. */
-  public static ImmutableList<String> getStringArrayAnnotationValue(AnnotationValue value) {
-    return value.accept(new SimpleAnnotationValueVisitor7<ImmutableList<String>, Void>() {
-      @Override
-      public ImmutableList<String> defaultAction(Object o, Void unused) {
-        throw new IllegalStateException("Expected an array, got instead: " + o);
-      }
-
-      @Override
-      public ImmutableList<String> visitArray(List<? extends AnnotationValue> values,
-          Void unused) {
-        ImmutableList.Builder<String> builder = ImmutableList.builder();
-        for (AnnotationValue value : values) {
-          builder.add(getStringAnnotationValue(value));
-        }
-        return builder.build();
-      }
-    }, /* unused accumulator */ null);
-  }
-
-  /** Gets the values from an annotation value representing an int. */
-  public static Boolean getBooleanAnnotationValue(AnnotationValue value) {
-    return value.accept(
-        new SimpleAnnotationValueVisitor7<Boolean, Void>() {
-          @Override
-          public Boolean defaultAction(Object o, Void unused) {
-            throw new IllegalStateException("Expected a boolean, got instead: " + o);
-          }
-
-          @Override
-          public Boolean visitBoolean(boolean value, Void unused) {
-            return value;
-          }
-        }, /* unused accumulator */
-        null);
-  }
-
-  /** Gets the values from an annotation value representing an int. */
-  public static Integer getIntAnnotationValue(AnnotationValue value) {
-    return value.accept(new SimpleAnnotationValueVisitor7<Integer, Void>() {
-      @Override
-      public Integer defaultAction(Object o, Void unused) {
-        throw new IllegalStateException("Expected an int, got instead: " + o);
-      }
-
-      @Override
-      public Integer visitInt(int value, Void unused) {
-        return value;
-      }
-    }, /* unused accumulator */ null);
-  }
-
-  /** Gets the values from an annotation value representing a long. */
-  public static Long getLongAnnotationValue(AnnotationValue value) {
-    return value.accept(
-        new SimpleAnnotationValueVisitor7<Long, Void>() {
-          @Override
-          public Long defaultAction(Object o, Void unused) {
-            throw new IllegalStateException("Expected an int, got instead: " + o);
-          }
-
-          @Override
-          public Long visitLong(long value, Void unused) {
-            return value;
-          }
-        },
-        null /* unused accumulator */);
-  }
-
-  /** Gets the values from an annotation value representing a string. */
-  public static String getStringAnnotationValue(AnnotationValue value) {
-    return value.accept(new SimpleAnnotationValueVisitor7<String, Void>() {
-      @Override
-      public String defaultAction(Object o, Void unused) {
-        throw new IllegalStateException("Expected a string, got instead: " + o);
-      }
-
-      @Override
-      public String visitString(String value, Void unused) {
-        return value;
-      }
-    }, /* unused accumulator */ null);
-  }
-
-  /** Gets the values from an annotation value representing a DeclaredType. */
-  public static DeclaredType getDeclaredTypeAnnotationValue(AnnotationValue value) {
-    return value.accept(
-        new SimpleAnnotationValueVisitor7<DeclaredType, Void>() {
-          @Override
-          public DeclaredType defaultAction(Object o, Void unused) {
-            throw new IllegalStateException("Expected a TypeMirror, got instead: " + o);
-          }
-
-          @Override
-          public DeclaredType visitType(TypeMirror typeMirror, Void unused) {
-            return MoreTypes.asDeclared(typeMirror);
-          }
-        }, /* unused accumulator */
-        null);
-  }
-
-  private static final SimpleAnnotationValueVisitor7<ImmutableSet<VariableElement>, Void>
-      ENUM_ANNOTATION_VALUE_VISITOR =
-          new SimpleAnnotationValueVisitor7<ImmutableSet<VariableElement>, Void>() {
-            @Override
-            public ImmutableSet<VariableElement> defaultAction(Object o, Void unused) {
-              throw new IllegalStateException(
-                  "Expected an Enum or an Enum array, got instead: " + o);
-            }
-
-            @Override
-            public ImmutableSet<VariableElement> visitArray(
-                List<? extends AnnotationValue> values, Void unused) {
-              ImmutableSet.Builder<VariableElement> builder = ImmutableSet.builder();
-              for (AnnotationValue value : values) {
-                builder.addAll(value.accept(this, null));
-              }
-              return builder.build();
-            }
-
-            @Override
-            public ImmutableSet<VariableElement> visitEnumConstant(
-                VariableElement value, Void unused) {
-              return ImmutableSet.of(value);
-            }
-          };
-
-  /** Gets the values from an annotation value representing a Enum array. */
-  public static ImmutableSet<VariableElement> getEnumArrayAnnotationValue(AnnotationValue value) {
-    return value.accept(ENUM_ANNOTATION_VALUE_VISITOR, /* unused accumulator */ null);
-  }
-
-  /** Converts an annotation value map to be keyed by the attribute name. */
-  public static ImmutableMap<String, AnnotationValue> convertToAttributeNameMap(
-      Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValues) {
-    ImmutableMap.Builder<String, AnnotationValue> builder = ImmutableMap.builder();
-    for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e
-        : annotationValues.entrySet()) {
-      String attribute = e.getKey().getSimpleName().toString();
-      builder.put(attribute, e.getValue());
-    }
-    return builder.build();
-  }
-
-  /** Returns the given elements containing package element. */
-  public static PackageElement getPackageElement(Element originalElement) {
-    checkNotNull(originalElement);
-    for (Element e = originalElement; e != null; e = e.getEnclosingElement()) {
-      if (e instanceof PackageElement) {
-        return (PackageElement) e;
-      }
-    }
-    throw new IllegalStateException("Cannot find a package for " + originalElement);
-  }
-
-  public static TypeElement getTopLevelType(Element originalElement) {
-    checkNotNull(originalElement);
-    for (Element e = originalElement; e != null; e = e.getEnclosingElement()) {
-      if (isTopLevel(e)) {
-        return MoreElements.asType(e);
-      }
-    }
-    throw new IllegalStateException("Cannot find a top-level type for " + originalElement);
-  }
-
-  /** Returns true if the given element is a top-level element. */
-  public static boolean isTopLevel(Element element) {
-    return element.getEnclosingElement().getKind() == ElementKind.PACKAGE;
-  }
-
-  /** Returns true if the given element is annotated with the given annotation. */
-  public static boolean hasAnnotation(Element element, Class<? extends Annotation> annotation) {
-    return element.getAnnotation(annotation) != null;
-  }
-
-  /** Returns true if the given element has an annotation with the given class name. */
-  public static boolean hasAnnotation(Element element, ClassName className) {
-    return getAnnotationMirrorOptional(element, className).isPresent();
-  }
-
-  /** Returns true if the given element has an annotation with the given class name. */
-  public static boolean hasAnnotation(AnnotationMirror mirror, ClassName className) {
-    return hasAnnotation(mirror.getAnnotationType().asElement(), className);
-  }
-
-  /** Returns true if the given element is annotated with the given annotation. */
-  public static boolean hasAnnotation(
-      AnnotationMirror mirror, Class<? extends Annotation> annotation) {
-    return hasAnnotation(mirror.getAnnotationType().asElement(), annotation);
-  }
-
-  /** Returns true if the given element has an annotation that is an error kind. */
-  public static boolean hasErrorTypeAnnotation(Element element) {
-    for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
-      if (annotationMirror.getAnnotationType().getKind() == TypeKind.ERROR) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-
-  /**
-   * Returns all elements in the round that are annotated with at least 1 of the given
-   * annotations.
-   */
-  @SafeVarargs
-  public static ImmutableSet<Element> getElementsAnnotatedWith(RoundEnvironment roundEnv,
-      Class<? extends Annotation>... annotations) {
-    ImmutableSet.Builder<Element> builder = ImmutableSet.builder();
-    for (Class<? extends Annotation> annotation : annotations){
-      builder.addAll(roundEnv.getElementsAnnotatedWith(annotation));
-    }
-
-    return builder.build();
-  }
-
-  /**
-   * Returns the name of a class, including prefixing with enclosing class names. i.e. for inner
-   * class Foo enclosed by Bar, returns Bar_Foo instead of just Foo
-   */
-  public static String getEnclosedName(ClassName name) {
-    return Joiner.on('_').join(name.simpleNames());
-  }
-
-  /** Returns the name of a class. See {@link #getEnclosedName(ClassName)}. */
-  public static String getEnclosedName(TypeElement element) {
-    return getEnclosedName(ClassName.get(element));
-  }
-
-  /**
-   * Returns an equivalent class name with the {@code .} (dots) used for inner classes replaced with
-   * {@code _}.
-   */
-  public static ClassName getEnclosedClassName(ClassName className) {
-    return ClassName.get(className.packageName(), getEnclosedName(className));
-  }
-
-  /** Returns the fully qualified class name, with _ instead of . */
-  public static String getFullyQualifiedEnclosedClassName(ClassName className) {
-    return className.packageName().replace('.', '_') + getEnclosedName(className);
-  }
-
-  /**
-   * Returns the fully qualified class name, with _ instead of . For elements that are not type
-   * elements, this continues to append the simple name of elements. For example,
-   * foo_bar_Outer_Inner_fooMethod.
-   */
-  public static String getFullEnclosedName(Element element) {
-    Preconditions.checkNotNull(element);
-    String qualifiedName = "";
-    while (element != null) {
-      if (element.getKind().equals(ElementKind.PACKAGE)) {
-        qualifiedName = asPackage(element).getQualifiedName() + qualifiedName;
-      } else {
-        // This check is needed to keep the name stable when compiled with jdk8 vs jdk11. jdk11
-        // contains newly added "module" enclosing elements of packages, which adds an addtional "_"
-        // prefix to the name due to an empty module element compared with jdk8.
-        if (!element.getSimpleName().toString().isEmpty()) {
-          qualifiedName = "." + element.getSimpleName() + qualifiedName;
-        }
-      }
-      element = element.getEnclosingElement();
-    }
-    return qualifiedName.replace('.', '_');
-  }
-
-  /** Appends the given string to the end of the class name. */
-  public static ClassName append(ClassName name, String suffix) {
-    return name.peerClass(name.simpleName() + suffix);
-  }
-
-  /** Prepends the given string to the beginning of the class name. */
-  public static ClassName prepend(ClassName name, String prefix) {
-    return name.peerClass(prefix + name.simpleName());
-  }
-
-  /**
-   * Removes the string {@code suffix} from the simple name of {@code type} and returns it.
-   *
-   * @throws BadInputException if the simple name of {@code type} does not end with {@code suffix}
-   */
-  public static ClassName removeNameSuffix(TypeElement type, String suffix) {
-    ClassName originalName = ClassName.get(type);
-    String originalSimpleName = originalName.simpleName();
-    ProcessorErrors.checkState(originalSimpleName.endsWith(suffix),
-        type, "Name of type %s must end with '%s'", originalName, suffix);
-    String withoutSuffix =
-        originalSimpleName.substring(0, originalSimpleName.length() - suffix.length());
-    return originalName.peerClass(withoutSuffix);
-  }
-
-  /** @see #getAnnotationMirror(Element, ClassName) */
-  public static AnnotationMirror getAnnotationMirror(
-      Element element, Class<? extends Annotation> annotationClass) {
-    return getAnnotationMirror(element, ClassName.get(annotationClass));
-  }
-
-  /** @see #getAnnotationMirror(Element, ClassName) */
-  public static AnnotationMirror getAnnotationMirror(Element element, String annotationClassName) {
-    return getAnnotationMirror(element, ClassName.bestGuess(annotationClassName));
-  }
-
-  /**
-   * Returns the annotation mirror from the given element that corresponds to the given class.
-   *
-   * @throws IllegalStateException if the given element isn't annotated with that annotation.
-   */
-  public static AnnotationMirror getAnnotationMirror(Element element, ClassName className) {
-    Optional<AnnotationMirror> annotationMirror = getAnnotationMirrorOptional(element, className);
-    if (annotationMirror.isPresent()) {
-      return annotationMirror.get();
-    } else {
-      throw new IllegalStateException(
-          String.format(
-              "Couldn't find annotation %s on element %s. Found annotations: %s",
-              className, element.getSimpleName(), element.getAnnotationMirrors()));
-    }
-  }
-
-  /**
-   * Returns the annotation mirror from the given element that corresponds to the given class.
-   *
-   * @throws {@link IllegalArgumentException} if 2 or more annotations are found.
-   * @return {@link Optional#empty()} if no annotation is found on the element.
-   */
-  static Optional<AnnotationMirror> getAnnotationMirrorOptional(
-      Element element, ClassName className) {
-    return element.getAnnotationMirrors().stream()
-        .filter(mirror -> ClassName.get(mirror.getAnnotationType()).equals(className))
-        .collect(toOptional());
-  }
-
-  /** @return true if element inherits directly or indirectly from the className */
-  public static boolean isAssignableFrom(TypeElement element, ClassName className) {
-    return isAssignableFromAnyOf(element, ImmutableSet.of(className));
-  }
-
-  /** @return true if element inherits directly or indirectly from any of the classNames */
-  public static boolean isAssignableFromAnyOf(TypeElement element,
-      ImmutableSet<ClassName> classNames) {
-    for (ClassName className : classNames) {
-      if (ClassName.get(element).equals(className)) {
-        return true;
-      }
-    }
-
-    TypeMirror superClass = element.getSuperclass();
-    // None type is returned if this is an interface or Object
-    // Error type is returned for classes that are generated by this processor
-    if ((superClass.getKind() != TypeKind.NONE) && (superClass.getKind() != TypeKind.ERROR)) {
-      Preconditions.checkState(superClass.getKind() == TypeKind.DECLARED);
-      if (isAssignableFromAnyOf(MoreTypes.asTypeElement(superClass), classNames)) {
-        return true;
-      }
-    }
-
-    for (TypeMirror iface : element.getInterfaces()) {
-      // Skip errors and keep looking. This is especially needed for classes generated by this
-      // processor.
-      if (iface.getKind() == TypeKind.ERROR) {
-        continue;
-      }
-      Preconditions.checkState(iface.getKind() == TypeKind.DECLARED,
-          "Interface type is %s", iface.getKind());
-      if (isAssignableFromAnyOf(MoreTypes.asTypeElement(iface), classNames)) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  /** Returns methods from a given TypeElement, not including constructors. */
-  public static ImmutableList<ExecutableElement> getMethods(TypeElement element) {
-    ImmutableList.Builder<ExecutableElement> builder = ImmutableList.builder();
-    for (Element e : element.getEnclosedElements()) {
-      // Only look for executable elements, not fields, etc
-      if (e instanceof ExecutableElement) {
-        ExecutableElement method = (ExecutableElement) e;
-        if (!method.getSimpleName().contentEquals(CONSTRUCTOR_NAME)
-            && !method.getSimpleName().contentEquals(STATIC_INITIALIZER_NAME)) {
-          builder.add(method);
-        }
-      }
-    }
-    return builder.build();
-  }
-
-  public static ImmutableList<ExecutableElement> getConstructors(TypeElement element) {
-    ImmutableList.Builder<ExecutableElement> builder = ImmutableList.builder();
-    for (Element enclosed : element.getEnclosedElements()) {
-      // Only look for executable elements, not fields, etc
-      if (enclosed instanceof ExecutableElement) {
-        ExecutableElement method = (ExecutableElement) enclosed;
-        if (method.getSimpleName().contentEquals(CONSTRUCTOR_NAME)) {
-          builder.add(method);
-        }
-      }
-    }
-    return builder.build();
-  }
-
-  /**
-   * Returns all transitive methods from a given TypeElement, not including constructors. Also does
-   * not include methods from Object or that override methods on Object.
-   */
-  public static ImmutableList<ExecutableElement> getAllMethods(TypeElement element) {
-    ImmutableList.Builder<ExecutableElement> builder = ImmutableList.builder();
-    builder.addAll(
-        Iterables.filter(
-            getMethods(element),
-            method -> {
-              return !isObjectMethod(method);
-            }));
-    TypeMirror superclass = element.getSuperclass();
-    if (superclass.getKind() != TypeKind.NONE) {
-      TypeElement superclassElement = MoreTypes.asTypeElement(superclass);
-      builder.addAll(getAllMethods(superclassElement));
-    }
-    for (TypeMirror iface : element.getInterfaces()) {
-      builder.addAll(getAllMethods(MoreTypes.asTypeElement(iface)));
-    }
-    return builder.build();
-  }
-
-  /** Checks that the given element is not the error type. */
-  public static void checkForCompilationError(TypeElement e) {
-    ProcessorErrors.checkState(e.asType().getKind() != TypeKind.ERROR, e,
-        "Unable to resolve the type %s. Look for compilation errors above related to this type.",
-        e);
-  }
-
-  private static void addInterfaceMethods(
-      TypeElement type, ImmutableList.Builder<ExecutableElement> interfaceMethods) {
-    for (TypeMirror interfaceMirror : type.getInterfaces()) {
-      TypeElement interfaceElement = MoreTypes.asTypeElement(interfaceMirror);
-      interfaceMethods.addAll(getMethods(interfaceElement));
-      addInterfaceMethods(interfaceElement, interfaceMethods);
-    }
-  }
-
-  /**
-   * Finds methods of interfaces implemented by {@code type}. This method also checks the
-   * superinterfaces of those interfaces. This method does not check the interfaces of any
-   * superclass of {@code type}.
-   */
-  public static ImmutableList<ExecutableElement> methodsOnInterfaces(TypeElement type) {
-    ImmutableList.Builder<ExecutableElement> interfaceMethods = new ImmutableList.Builder<>();
-    addInterfaceMethods(type, interfaceMethods);
-    return interfaceMethods.build();
-  }
-
-  /** Returns MapKey annotated annotations found on an element. */
-  public static ImmutableList<AnnotationMirror> getMapKeyAnnotations(Element element) {
-    return getAnnotationsAnnotatedWith(element, ClassName.get("dagger", "MapKey"));
-  }
-
-  /** Returns Qualifier annotated annotations found on an element. */
-  public static ImmutableList<AnnotationMirror> getQualifierAnnotations(Element element) {
-    // TODO(bcorso): Consolidate this logic with InjectionAnnotations in Dagger
-    ImmutableSet<? extends AnnotationMirror> qualifiers =
-        AnnotationMirrors.getAnnotatedAnnotations(element, Qualifier.class);
-    KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
-    if (element.getKind() == ElementKind.FIELD
-        // static fields are generally not supported, no need to get qualifier from kotlin metadata
-        && !element.getModifiers().contains(STATIC)
-        && metadataUtil.hasMetadata(element)) {
-      VariableElement fieldElement = asVariable(element);
-      return Stream.concat(
-              qualifiers.stream(),
-              metadataUtil.isMissingSyntheticPropertyForAnnotations(fieldElement)
-                  ? Stream.empty()
-                  : metadataUtil
-                      .getSyntheticPropertyAnnotations(fieldElement, Qualifier.class)
-                      .stream())
-          .map(AnnotationMirrors.equivalence()::wrap)
-          .distinct()
-          .map(Wrapper::get)
-          .collect(DaggerStreams.toImmutableList());
-    } else {
-      return ImmutableList.copyOf(qualifiers);
-    }
-  }
-
-  /** Returns Scope annotated annotations found on an element. */
-  public static ImmutableList<AnnotationMirror> getScopeAnnotations(Element element) {
-    return getAnnotationsAnnotatedWith(element, ClassNames.SCOPE);
-  }
-
-  /** Returns annotations of element that are annotated with subAnnotation */
-  public static ImmutableList<AnnotationMirror> getAnnotationsAnnotatedWith(
-      Element element, ClassName subAnnotation) {
-    ImmutableList.Builder<AnnotationMirror> builder = ImmutableList.builder();
-    element.getAnnotationMirrors().stream()
-        .filter(annotation -> hasAnnotation(annotation, subAnnotation))
-        .forEach(builder::add);
-    return builder.build();
-  }
-
-  /** Returns true if there are any annotations of element that are annotated with subAnnotation */
-  public static boolean hasAnnotationsAnnotatedWith(Element element, ClassName subAnnotation) {
-    return !getAnnotationsAnnotatedWith(element, subAnnotation).isEmpty();
-  }
-
-  /**
-   * Returns true iff the given {@code method} is one of the public or protected methods on {@link
-   * Object}, or an overridden version thereof.
-   *
-   * <p>This method ignores the return type of the given method, but this is generally fine since
-   * two methods which only differ by their return type will cause a compiler error. (e.g. a
-   * non-static method with the signature {@code int equals(Object)})
-   */
-  public static boolean isObjectMethod(ExecutableElement method) {
-    // First check if this method is directly defined on Object
-    Element enclosingElement = method.getEnclosingElement();
-    if (enclosingElement.getKind() == ElementKind.CLASS
-        && TypeName.get(enclosingElement.asType()).equals(TypeName.OBJECT)) {
-      return true;
-    }
-
-    if (method.getModifiers().contains(Modifier.STATIC)) {
-      return false;
-    }
-    switch (method.getSimpleName().toString()) {
-      case "equals":
-        return (method.getParameters().size() == 1)
-            && (method.getParameters().get(0).asType().toString().equals("java.lang.Object"));
-      case "hashCode":
-      case "toString":
-      case "clone":
-      case "getClass":
-      case "notify":
-      case "notifyAll":
-      case "finalize":
-        return method.getParameters().isEmpty();
-      case "wait":
-        if (method.getParameters().isEmpty()) {
-          return true;
-        } else if ((method.getParameters().size() == 1)
-            && (method.getParameters().get(0).asType().toString().equals("long"))) {
-          return true;
-        } else if ((method.getParameters().size() == 2)
-            && (method.getParameters().get(0).asType().toString().equals("long"))
-            && (method.getParameters().get(1).asType().toString().equals("int"))) {
-          return true;
-        }
-        return false;
-      default:
-        return false;
-    }
-  }
-
-  public static ParameterSpec parameterSpecFromVariableElement(VariableElement element) {
-    return ParameterSpec.builder(
-        ClassName.get(element.asType()),
-        upperToLowerCamel(element.getSimpleName().toString()))
-        .build();
-  }
-
-  /**
-   * Shortcut for converting from upper camel to lower camel case
-   *
-   * <p>Example: "SomeString" => "someString"
-   */
-  public static String upperToLowerCamel(String upperCamel) {
-    return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, upperCamel);
-  }
-
-  /** @return copy of the given MethodSpec as {@link MethodSpec.Builder} with method body removed */
-  public static MethodSpec.Builder copyMethodSpecWithoutBody(MethodSpec methodSpec) {
-    MethodSpec.Builder builder;
-
-    if (methodSpec.isConstructor()) {
-      // Constructors cannot have return types
-      builder = MethodSpec.constructorBuilder();
-    } else {
-      builder = MethodSpec.methodBuilder(methodSpec.name)
-          .returns(methodSpec.returnType);
-    }
-
-    return builder
-        .addAnnotations(methodSpec.annotations)
-        .addModifiers(methodSpec.modifiers)
-        .addParameters(methodSpec.parameters)
-        .addExceptions(methodSpec.exceptions)
-        .addJavadoc(methodSpec.javadoc.toString())
-        .addTypeVariables(methodSpec.typeVariables);
-  }
-
-  /** @return A method spec for an empty constructor (useful for abstract Dagger modules). */
-  public static MethodSpec privateEmptyConstructor() {
-    return MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build();
-  }
-
-  /**
-   * Returns true if the given method is annotated with one of the annotations Dagger recognizes
-   * for abstract methods (e.g. @Binds).
-   */
-  public static boolean hasDaggerAbstractMethodAnnotation(ExecutableElement method) {
-    return hasAnnotation(method, ClassNames.BINDS)
-        || hasAnnotation(method, ClassNames.BINDS_OPTIONAL_OF)
-        || hasAnnotation(method, ClassNames.MULTIBINDS)
-        || hasAnnotation(method, ClassNames.CONTRIBUTES_ANDROID_INJECTOR);
-  }
-
-  public static ImmutableSet<TypeElement> toTypeElements(Elements elements, String[] classes) {
-    return FluentIterable.from(classes).transform(elements::getTypeElement).toSet();
-  }
-
-  public static ImmutableSet<ClassName> toClassNames(Iterable<TypeElement> elements) {
-    return FluentIterable.from(elements).transform(ClassName::get).toSet();
-  }
-
-  public static boolean requiresModuleInstance(Elements elements, TypeElement module) {
-    // Binding methods that lack ABSTRACT or STATIC require module instantiation.
-    // Required by Dagger.  See b/31489617.
-    return ElementFilter.methodsIn(elements.getAllMembers(module)).stream()
-        .filter(Processors::isBindingMethod)
-        .map(ExecutableElement::getModifiers)
-        .anyMatch(modifiers -> !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC));
-  }
-
-  private static boolean isBindingMethod(ExecutableElement method) {
-    return hasAnnotation(method, ClassNames.PROVIDES)
-        || hasAnnotation(method, ClassNames.BINDS)
-        || hasAnnotation(method, ClassNames.BINDS_OPTIONAL_OF)
-        || hasAnnotation(method, ClassNames.MULTIBINDS);
-  }
-
-  public static void addGeneratedAnnotation(
-      TypeSpec.Builder typeSpecBuilder, ProcessingEnvironment env, Class<?> generatorClass) {
-    addGeneratedAnnotation(typeSpecBuilder, env, generatorClass.getName());
-  }
-
-  public static void addGeneratedAnnotation(
-      TypeSpec.Builder typeSpecBuilder, ProcessingEnvironment env, String generatorClass) {
-    GeneratedAnnotations.generatedAnnotation(env.getElementUtils(), env.getSourceVersion())
-        .ifPresent(
-            annotation ->
-                typeSpecBuilder.addAnnotation(
-                    AnnotationSpec.builder(ClassName.get(annotation))
-                        .addMember("value", "$S", generatorClass)
-                        .build()));
-  }
-
-  public static AnnotationSpec getOriginatingElementAnnotation(TypeElement element) {
-    TypeName rawType = rawTypeName(ClassName.get(getTopLevelType(element)));
-    return AnnotationSpec.builder(ClassNames.ORIGINATING_ELEMENT)
-        .addMember("topLevelClass", "$T.class", rawType)
-        .build();
-  }
-
-  /**
-   * Returns the {@link TypeName} for the raw type of the given type name. If the argument isn't a
-   * parameterized type, it returns the argument unchanged.
-   */
-  public static TypeName rawTypeName(TypeName typeName) {
-    return (typeName instanceof ParameterizedTypeName)
-        ? ((ParameterizedTypeName) typeName).rawType
-        : typeName;
-  }
-
-  private Processors() {}
-}
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDeps.java b/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDeps.java
deleted file mode 100644
index cc955ef..0000000
--- a/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDeps.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.aggregateddeps;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-
-// TODO(bcorso): Change this API to clearly represent that each AggeregatedDeps should only contain
-// a single module, entry point, or component entry point.
-/** Annotation for propagating dependency information through javac runs. */
-@Retention(CLASS)
-public @interface AggregatedDeps {
-  /** Returns the components that this dependency will be installed in. */
-  String[] components();
-
-  /** Returns the test this dependency is associated with, otherwise an empty string. */
-  String test() default "";
-
-  /** Returns the deps that this dep replaces. */
-  String[] replaces() default {};
-
-  String[] modules() default {};
-
-  String[] entryPoints() default {};
-
-  String[] componentEntryPoints() default {};
-}
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsGenerator.java b/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsGenerator.java
deleted file mode 100644
index bcc2dfe..0000000
--- a/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsGenerator.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.aggregateddeps;
-
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import java.util.Optional;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.TypeElement;
-
-/**
- * Generates the @AggregatedDeps annotated class used to pass information
- * about modules and entry points through multiple javac runs.
- */
-final class AggregatedDepsGenerator {
-  static final String AGGREGATING_PACKAGE = "hilt_aggregated_deps";
-  private static final ClassName AGGREGATED_DEPS =
-      ClassName.get("dagger.hilt.processor.internal.aggregateddeps", "AggregatedDeps");
-
-  private final String dependencyType;
-  private final TypeElement dependency;
-  private final Optional<ClassName> testName;
-  private final ImmutableSet<ClassName> components;
-  private final ImmutableSet<ClassName> replacedDependencies;
-  private final ProcessingEnvironment processingEnv;
-
-  AggregatedDepsGenerator(
-      String dependencyType,
-      TypeElement dependency,
-      Optional<ClassName> testName,
-      ImmutableSet<ClassName> components,
-      ImmutableSet<ClassName> replacedDependencies,
-      ProcessingEnvironment processingEnv) {
-    this.dependencyType = dependencyType;
-    this.dependency = dependency;
-    this.testName = testName;
-    this.components = components;
-    this.replacedDependencies = replacedDependencies;
-    this.processingEnv = processingEnv;
-  }
-
-  void generate() throws IOException {
-    ClassName name =
-        ClassName.get(
-            AGGREGATING_PACKAGE, Processors.getFullEnclosedName(dependency) + "ModuleDeps");
-    TypeSpec.Builder generator =
-        TypeSpec.classBuilder(name.simpleName())
-            .addOriginatingElement(dependency)
-            .addAnnotation(aggregatedDepsAnnotation())
-            .addJavadoc("Generated class to pass information through multiple javac runs.\n");
-
-    Processors.addGeneratedAnnotation(generator, processingEnv, getClass());
-
-    JavaFile.builder(name.packageName(), generator.build())
-        .build()
-        .writeTo(processingEnv.getFiler());
-  }
-
-  private AnnotationSpec aggregatedDepsAnnotation() {
-    AnnotationSpec.Builder annotationBuilder = AnnotationSpec.builder(AGGREGATED_DEPS);
-    components.forEach(component -> annotationBuilder.addMember("components", "$S", component));
-    replacedDependencies.forEach(dep -> annotationBuilder.addMember("replaces", "$S", dep));
-    testName.ifPresent(test -> annotationBuilder.addMember("test", "$S", test));
-    annotationBuilder.addMember(dependencyType, "$S", dependency.getQualifiedName());
-    return annotationBuilder.build();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessor.java b/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessor.java
deleted file mode 100644
index 58c938f..0000000
--- a/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessor.java
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.aggregateddeps;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreElements.getPackage;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.hilt.android.processor.internal.androidentrypoint.HiltCompilerOptions.BooleanOption.DISABLE_MODULES_HAVE_INSTALL_IN_CHECK;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static javax.lang.model.element.ElementKind.CLASS;
-import static javax.lang.model.element.ElementKind.INTERFACE;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Components;
-import dagger.hilt.processor.internal.KotlinMetadataUtils;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.SimpleAnnotationValueVisitor8;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/** Processor that outputs dummy files to propagate information through multiple javac runs. */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class AggregatedDepsProcessor extends BaseProcessor {
-
-  private static final ImmutableSet<ClassName> ENTRY_POINT_ANNOTATIONS =
-      ImmutableSet.of(
-          ClassNames.ENTRY_POINT,
-          ClassNames.GENERATED_ENTRY_POINT,
-          ClassNames.COMPONENT_ENTRY_POINT);
-
-  private static final ImmutableSet<ClassName> MODULE_ANNOTATIONS =
-      ImmutableSet.of(
-          ClassNames.MODULE);
-
-  private static final ImmutableSet<ClassName> INSTALL_IN_ANNOTATIONS =
-      ImmutableSet.of(ClassNames.INSTALL_IN, ClassNames.TEST_INSTALL_IN);
-
-  private final Set<Element> seen = new HashSet<>();
-
-  @Override
-  public Set<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.builder()
-        .addAll(INSTALL_IN_ANNOTATIONS)
-        .addAll(MODULE_ANNOTATIONS)
-        .addAll(ENTRY_POINT_ANNOTATIONS)
-        .build()
-        .stream()
-        .map(Object::toString)
-        .collect(toImmutableSet());
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    if (!seen.add(element)) {
-      return;
-    }
-
-    Optional<ClassName> installInAnnotation = getAnnotation(element, INSTALL_IN_ANNOTATIONS);
-    Optional<ClassName> entryPointAnnotation = getAnnotation(element, ENTRY_POINT_ANNOTATIONS);
-    Optional<ClassName> moduleAnnotation = getAnnotation(element, MODULE_ANNOTATIONS);
-
-    boolean hasInstallIn = installInAnnotation.isPresent();
-    boolean isEntryPoint = entryPointAnnotation.isPresent();
-    boolean isModule = moduleAnnotation.isPresent();
-
-    ProcessorErrors.checkState(
-        !hasInstallIn || isEntryPoint || isModule,
-        element,
-        "@%s-annotated classes must also be annotated with @Module or @EntryPoint: %s",
-        installInAnnotation.map(ClassName::simpleName).orElse("@InstallIn"),
-        element);
-
-    ProcessorErrors.checkState(
-        !(isEntryPoint && isModule),
-        element,
-        "@%s and @%s cannot be used on the same interface: %s",
-        moduleAnnotation.map(ClassName::simpleName).orElse("@Module"),
-        entryPointAnnotation.map(ClassName::simpleName).orElse("@EntryPoint"),
-        element);
-
-    if (isModule) {
-      processModule(element, installInAnnotation, moduleAnnotation.get());
-    } else if (isEntryPoint) {
-      processEntryPoint(element, installInAnnotation, entryPointAnnotation.get());
-    } else {
-      throw new AssertionError();
-    }
-  }
-
-  private void processModule(
-      Element element, Optional<ClassName> installInAnnotation, ClassName moduleAnnotation)
-      throws Exception {
-    ProcessorErrors.checkState(
-        installInAnnotation.isPresent()
-            || isDaggerGeneratedModule(element)
-            || installInCheckDisabled(element),
-        element,
-        "%s is missing an @InstallIn annotation. If this was intentional, see"
-            + " https://dagger.dev/hilt/compiler-options#disable-install-in-check for how to disable this"
-            + " check.",
-        element);
-
-    if (!installInAnnotation.isPresent()) {
-      // Modules without @InstallIn or @TestInstallIn annotations don't need to be processed further
-      return;
-    }
-
-    ProcessorErrors.checkState(
-        element.getKind() == CLASS || element.getKind() == INTERFACE,
-        element,
-        "Only classes and interfaces can be annotated with @Module: %s",
-        element);
-    TypeElement module = asType(element);
-
-    ProcessorErrors.checkState(
-        Processors.isTopLevel(module)
-            || module.getModifiers().contains(STATIC)
-            || module.getModifiers().contains(ABSTRACT)
-            || Processors.hasAnnotation(module.getEnclosingElement(), ClassNames.HILT_ANDROID_TEST),
-        module,
-        "Nested @%s modules must be static unless they are directly nested within a test. "
-            + "Found: %s",
-        installInAnnotation.get().simpleName(),
-        module);
-
-    // Check that if Dagger needs an instance of the module, Hilt can provide it automatically by
-    // calling a visible empty constructor.
-    ProcessorErrors.checkState(
-        !daggerRequiresModuleInstance(module) || hasVisibleEmptyConstructor(module),
-        module,
-        "Modules that need to be instantiated by Hilt must have a visible, empty constructor.");
-
-    // TODO(b/28989613): This should really be fixed in Dagger. Remove once Dagger bug is fixed.
-    ImmutableList<ExecutableElement> abstractMethodsWithMissingBinds =
-        ElementFilter.methodsIn(module.getEnclosedElements()).stream()
-            .filter(method -> method.getModifiers().contains(ABSTRACT))
-            .filter(method -> !Processors.hasDaggerAbstractMethodAnnotation(method))
-            .collect(toImmutableList());
-    ProcessorErrors.checkState(
-        abstractMethodsWithMissingBinds.isEmpty(),
-        module,
-        "Found unimplemented abstract methods, %s, in an abstract module, %s. "
-            + "Did you forget to add a Dagger binding annotation (e.g. @Binds)?",
-        abstractMethodsWithMissingBinds,
-        module);
-
-    ImmutableList<TypeElement> replacedModules = ImmutableList.of();
-    if (Processors.hasAnnotation(module, ClassNames.TEST_INSTALL_IN)) {
-      Optional<TypeElement> originatingTestElement = getOriginatingTestElement(module);
-      ProcessorErrors.checkState(
-          !originatingTestElement.isPresent(),
-          // TODO(b/152801981): this should really error on the annotation value
-          module,
-          "@TestInstallIn modules cannot be nested in (or originate from) a "
-                + "@HiltAndroidTest-annotated class:  %s",
-          originatingTestElement
-              .map(testElement -> testElement.getQualifiedName().toString())
-              .orElse(""));
-
-      AnnotationMirror testInstallIn =
-          Processors.getAnnotationMirror(module, ClassNames.TEST_INSTALL_IN);
-      replacedModules =
-          Processors.getAnnotationClassValues(getElementUtils(), testInstallIn, "replaces");
-
-      ProcessorErrors.checkState(
-          !replacedModules.isEmpty(),
-          // TODO(b/152801981): this should really error on the annotation value
-          module,
-          "@TestInstallIn#replaces() cannot be empty. Use @InstallIn instead.");
-
-      ImmutableList<TypeElement> nonInstallInModules =
-          replacedModules.stream()
-              .filter(
-                  replacedModule ->
-                      !Processors.hasAnnotation(replacedModule, ClassNames.INSTALL_IN))
-              .collect(toImmutableList());
-
-      ProcessorErrors.checkState(
-          nonInstallInModules.isEmpty(),
-          // TODO(b/152801981): this should really error on the annotation value
-          module,
-          "@TestInstallIn#replaces() can only contain @InstallIn modules, but found: %s",
-          nonInstallInModules);
-
-      ImmutableList<TypeElement> hiltWrapperModules =
-          replacedModules.stream()
-              .filter(
-                  replacedModule ->
-                      replacedModule.getSimpleName().toString().startsWith("HiltWrapper_"))
-              .collect(toImmutableList());
-
-      ProcessorErrors.checkState(
-          hiltWrapperModules.isEmpty(),
-          // TODO(b/152801981): this should really error on the annotation value
-          module,
-          "@TestInstallIn#replaces() cannot contain Hilt generated public wrapper modules, "
-              + "but found: %s. ",
-          hiltWrapperModules);
-
-      if (!getPackage(module).getQualifiedName().toString().startsWith("dagger.hilt")) {
-        // Prevent external users from overriding Hilt's internal modules. Techincally, except for
-        // ApplicationContextModule, making all modules pkg-private should be enough but this is an
-        // extra measure of precaution.
-        ImmutableList<TypeElement> hiltInternalModules =
-            replacedModules.stream()
-                .filter(
-                    replacedModule ->
-                        getPackage(replacedModule)
-                            .getQualifiedName()
-                            .toString()
-                            .startsWith("dagger.hilt"))
-                .collect(toImmutableList());
-
-        ProcessorErrors.checkState(
-            hiltInternalModules.isEmpty(),
-            // TODO(b/152801981): this should really error on the annotation value
-            module,
-            "@TestInstallIn#replaces() cannot contain internal Hilt modules, but found: %s. ",
-            hiltInternalModules);
-      }
-
-      // Prevent users from uninstalling test-specific @InstallIn modules.
-      ImmutableList<TypeElement> replacedTestSpecificInstallIn =
-          replacedModules.stream()
-              .filter(replacedModule -> getOriginatingTestElement(replacedModule).isPresent())
-              .collect(toImmutableList());
-
-      ProcessorErrors.checkState(
-          replacedTestSpecificInstallIn.isEmpty(),
-          // TODO(b/152801981): this should really error on the annotation value
-          module,
-          "@TestInstallIn#replaces() cannot replace test specific @InstallIn modules, but found: "
-              + "%s. Please remove the @InstallIn module manually rather than replacing it.",
-          replacedTestSpecificInstallIn);
-    }
-
-    generateAggregatedDeps(
-        "modules",
-        module,
-        moduleAnnotation,
-        replacedModules.stream().map(ClassName::get).collect(toImmutableSet()));
-  }
-
-  private void processEntryPoint(
-      Element element, Optional<ClassName> installInAnnotation, ClassName entryPointAnnotation)
-      throws Exception {
-    ProcessorErrors.checkState(
-        installInAnnotation.isPresent() ,
-        element,
-        "@%s %s must also be annotated with @InstallIn",
-        entryPointAnnotation.simpleName(),
-        element);
-
-    ProcessorErrors.checkState(
-        !Processors.hasAnnotation(element, ClassNames.TEST_INSTALL_IN),
-        element,
-        "@TestInstallIn can only be used with modules");
-
-    ProcessorErrors.checkState(
-        element.getKind() == INTERFACE,
-        element,
-        "Only interfaces can be annotated with @%s: %s",
-        entryPointAnnotation.simpleName(),
-        element);
-    TypeElement entryPoint = asType(element);
-
-    generateAggregatedDeps(
-        entryPointAnnotation.equals(ClassNames.COMPONENT_ENTRY_POINT)
-            ? "componentEntryPoints"
-            : "entryPoints",
-        entryPoint,
-        entryPointAnnotation,
-        ImmutableSet.of());
-  }
-
-  private void generateAggregatedDeps(
-      String key,
-      TypeElement element,
-      ClassName annotation,
-      ImmutableSet<ClassName> replacedModules)
-      throws Exception {
-    // Get @InstallIn components here to catch errors before skipping user's pkg-private element.
-    ImmutableSet<ClassName> components = Components.getComponents(getElementUtils(), element);
-
-    if (isValidKind(element)) {
-      Optional<PkgPrivateMetadata> pkgPrivateMetadata =
-          PkgPrivateMetadata.of(getElementUtils(), element, annotation);
-      if (pkgPrivateMetadata.isPresent()) {
-        if (key.contentEquals("modules")) {
-          new PkgPrivateModuleGenerator(getProcessingEnv(), pkgPrivateMetadata.get()).generate();
-        } else {
-          new PkgPrivateEntryPointGenerator(getProcessingEnv(), pkgPrivateMetadata.get())
-              .generate();
-        }
-      } else {
-        Optional<ClassName> testName = getOriginatingTestElement(element).map(ClassName::get);
-        new AggregatedDepsGenerator(
-                key, element, testName, components, replacedModules, getProcessingEnv())
-            .generate();
-      }
-    }
-  }
-
-  private static Optional<ClassName> getAnnotation(
-      Element element, ImmutableSet<ClassName> annotations) {
-    ImmutableSet<ClassName> usedAnnotations =
-        annotations.stream()
-            .filter(annotation -> Processors.hasAnnotation(element, annotation))
-            .collect(toImmutableSet());
-
-    if (usedAnnotations.isEmpty()) {
-      return Optional.empty();
-    }
-
-    ProcessorErrors.checkState(
-        usedAnnotations.size() == 1,
-        element,
-        "Only one of the following annotations can be used on %s: %s",
-        element,
-        usedAnnotations);
-
-    return Optional.of(getOnlyElement(usedAnnotations));
-  }
-
-  private Optional<TypeElement> getOriginatingTestElement(Element element) {
-    TypeElement topLevelType = getOriginatingTopLevelType(element);
-    return Processors.hasAnnotation(topLevelType, ClassNames.HILT_ANDROID_TEST)
-        ? Optional.of(asType(topLevelType))
-        : Optional.empty();
-  }
-
-  private TypeElement getOriginatingTopLevelType(Element element) {
-    TypeElement topLevelType = Processors.getTopLevelType(element);
-    if (Processors.hasAnnotation(topLevelType, ClassNames.ORIGINATING_ELEMENT)) {
-      return getOriginatingTopLevelType(
-          Processors.getAnnotationClassValue(
-              getElementUtils(),
-              Processors.getAnnotationMirror(topLevelType, ClassNames.ORIGINATING_ELEMENT),
-              "topLevelClass"));
-    }
-    return topLevelType;
-  }
-
-  private static boolean isValidKind(Element element) {
-    // don't go down the rabbit hole of analyzing undefined types. N.B. we don't issue
-    // an error here because javac already has and we don't want to spam the user.
-    return element.asType().getKind() != TypeKind.ERROR;
-  }
-
-  private boolean installInCheckDisabled(Element element) {
-    return DISABLE_MODULES_HAVE_INSTALL_IN_CHECK.get(getProcessingEnv())
-        || Processors.hasAnnotation(element, ClassNames.DISABLE_INSTALL_IN_CHECK);
-  }
-
-  /**
-   * When using Dagger Producers, don't process generated modules. They will not have the expected
-   * annotations.
-   */
-  private static boolean isDaggerGeneratedModule(Element element) {
-    if (!Processors.hasAnnotation(element, ClassNames.MODULE)) {
-      return false;
-    }
-    return element.getAnnotationMirrors().stream()
-        .filter(mirror -> isGenerated(mirror))
-        .map(mirror -> asString(getOnlyElement(asList(getAnnotationValue(mirror, "value")))))
-        .anyMatch(value -> value.startsWith("dagger"));
-  }
-
-  private static List<? extends AnnotationValue> asList(AnnotationValue value) {
-    return value.accept(
-        new SimpleAnnotationValueVisitor8<List<? extends AnnotationValue>, Void>() {
-          @Override
-          public List<? extends AnnotationValue> visitArray(
-              List<? extends AnnotationValue> value, Void unused) {
-            return value;
-          }
-        },
-        null);
-  }
-
-  private static String asString(AnnotationValue value) {
-    return value.accept(
-        new SimpleAnnotationValueVisitor8<String, Void>() {
-          @Override
-          public String visitString(String value, Void unused) {
-            return value;
-          }
-        },
-        null);
-  }
-
-  private static boolean isGenerated(AnnotationMirror annotationMirror) {
-    Name name = asType(annotationMirror.getAnnotationType().asElement()).getQualifiedName();
-    return name.contentEquals("javax.annotation.Generated")
-        || name.contentEquals("javax.annotation.processing.Generated");
-  }
-
-  private static boolean daggerRequiresModuleInstance(TypeElement module) {
-    return !module.getModifiers().contains(ABSTRACT)
-        && !hasOnlyStaticProvides(module)
-        // Skip ApplicationContextModule, since Hilt manages this module internally.
-        && !ClassNames.APPLICATION_CONTEXT_MODULE.equals(ClassName.get(module))
-        // Skip Kotlin object modules since all their provision methods are static
-        && !isKotlinObject(module);
-  }
-
-  private static boolean isKotlinObject(TypeElement type) {
-    KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
-    return metadataUtil.isObjectClass(type) || metadataUtil.isCompanionObjectClass(type);
-  }
-
-  private static boolean hasOnlyStaticProvides(TypeElement module) {
-    // TODO(erichang): Check for @Produces too when we have a producers story
-    return ElementFilter.methodsIn(module.getEnclosedElements()).stream()
-        .filter(method -> Processors.hasAnnotation(method, ClassNames.PROVIDES))
-        .allMatch(method -> method.getModifiers().contains(STATIC));
-  }
-
-  private static boolean hasVisibleEmptyConstructor(TypeElement type) {
-    List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());
-    return constructors.isEmpty()
-        || constructors.stream()
-            .filter(constructor -> constructor.getParameters().isEmpty())
-            .anyMatch(
-                constructor ->
-                    !constructor.getModifiers().contains(PRIVATE)
-                        );
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/BUILD b/java/dagger/hilt/processor/internal/aggregateddeps/BUILD
deleted file mode 100644
index ebbc941..0000000
--- a/java/dagger/hilt/processor/internal/aggregateddeps/BUILD
+++ /dev/null
@@ -1,88 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   A processor that aggregates metadata about Hilt @InstallIn annotations
-
-package(default_visibility = ["//:src"])
-
-# TODO(bcorso): Remove all AggregatedDeps usage from the processor class path.
-java_library(
-    name = "annotation",
-    srcs = ["AggregatedDeps.java"],
-    exports = [
-        "//java/dagger/hilt/codegen:originating_element",
-    ],
-)
-
-java_plugin(
-    name = "plugin",
-    generates_api = 1,
-    processor_class = "dagger.hilt.processor.internal.aggregateddeps.AggregatedDepsProcessor",
-    deps = [":processor_lib"],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "AggregatedDepsGenerator.java",
-        "AggregatedDepsProcessor.java",
-        "PkgPrivateEntryPointGenerator.java",
-        "PkgPrivateMetadata.java",
-        "PkgPrivateModuleGenerator.java",
-    ],
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:compiler_options",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:components",
-        "//java/dagger/hilt/processor/internal:kotlin",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/jsr250_annotations",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_library(
-    name = "component_dependencies",
-    srcs = [
-        "ComponentDependencies.java",
-    ],
-    deps = [
-        ":processor_lib",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:component_descriptor",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/ComponentDependencies.java b/java/dagger/hilt/processor/internal/aggregateddeps/ComponentDependencies.java
deleted file mode 100644
index 23ed148..0000000
--- a/java/dagger/hilt/processor/internal/aggregateddeps/ComponentDependencies.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.aggregateddeps;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.hilt.processor.internal.aggregateddeps.AggregatedDepsGenerator.AGGREGATING_PACKAGE;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.SetMultimap;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.AnnotationValues;
-import dagger.hilt.processor.internal.BadInputException;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ComponentDescriptor;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import dagger.hilt.processor.internal.aggregateddeps.ComponentDependencies.AggregatedDepMetadata.DependencyType;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.Elements;
-
-/** Represents information needed to create a component (i.e. modules, entry points, etc) */
-@AutoValue
-public abstract class ComponentDependencies {
-  private static Builder builder() {
-    return new AutoValue_ComponentDependencies.Builder();
-  }
-
-  /** Returns the modules for a component, without any filtering. */
-  public abstract Dependencies modules();
-
-  /** Returns the entry points associated with the given a component. */
-  public abstract Dependencies entryPoints();
-
-  /** Returns the component entry point associated with the given a component. */
-  public abstract Dependencies componentEntryPoints();
-
-  @AutoValue.Builder
-  abstract static class Builder {
-    abstract Dependencies.Builder modulesBuilder();
-
-    abstract Dependencies.Builder entryPointsBuilder();
-
-    abstract Dependencies.Builder componentEntryPointsBuilder();
-
-    abstract ComponentDependencies autoBuild();
-
-    ComponentDependencies build(Elements elements) {
-      validateModules(modulesBuilder().build(), elements);
-      return autoBuild();
-    }
-  }
-
-  /** A key used for grouping a test dependency by both its component and test name. */
-  @AutoValue
-  abstract static class TestDepKey {
-    static TestDepKey of(ClassName component, ClassName test) {
-      return new AutoValue_ComponentDependencies_TestDepKey(component, test);
-    }
-
-    /** Returns the name of the component this dependency should be installed in. */
-    abstract ClassName component();
-
-    /** Returns the name of the test that this dependency should be installed in. */
-    abstract ClassName test();
-  }
-
-  /**
-   * Holds a set of component dependencies, e.g. modules or entry points.
-   *
-   * <p>This class handles separating dependencies into global and test dependencies. Global
-   * dependencies are installed with every test, where test dependencies are only installed with the
-   * specified test. The total set of dependencies includes all global + test dependencies.
-   */
-  @AutoValue
-  public abstract static class Dependencies {
-    static Builder builder() {
-      return new AutoValue_ComponentDependencies_Dependencies.Builder();
-    }
-
-    /** Returns the global deps keyed by component. */
-    abstract ImmutableSetMultimap<ClassName, TypeElement> globalDeps();
-
-    /** Returns the global test deps keyed by component. */
-    abstract ImmutableSetMultimap<ClassName, TypeElement> globalTestDeps();
-
-    /** Returns the test deps keyed by component and test. */
-    abstract ImmutableSetMultimap<TestDepKey, TypeElement> testDeps();
-
-    /** Returns the uninstalled test deps keyed by test. */
-    abstract ImmutableSetMultimap<ClassName, TypeElement> uninstalledTestDeps();
-
-    /** Returns the global uninstalled test deps. */
-    abstract ImmutableSet<TypeElement> globalUninstalledTestDeps();
-
-    /** Returns the dependencies to be installed in the given component for the given root. */
-    public ImmutableSet<TypeElement> get(ClassName component, ClassName root, boolean isTestRoot) {
-      if (!isTestRoot) {
-        return globalDeps().get(component);
-      }
-
-      ImmutableSet<TypeElement> uninstalledTestDepsForRoot = uninstalledTestDeps().get(root);
-      return ImmutableSet.<TypeElement>builder()
-          .addAll(
-              globalDeps().get(component).stream()
-                  .filter(dep -> !uninstalledTestDepsForRoot.contains(dep))
-                  .filter(dep -> !globalUninstalledTestDeps().contains(dep))
-                  .collect(toImmutableSet()))
-          .addAll(globalTestDeps().get(component))
-          .addAll(testDeps().get(TestDepKey.of(component, root)))
-          .build();
-    }
-
-    @AutoValue.Builder
-    abstract static class Builder {
-      abstract ImmutableSetMultimap.Builder<ClassName, TypeElement> globalDepsBuilder();
-
-      abstract ImmutableSetMultimap.Builder<ClassName, TypeElement> globalTestDepsBuilder();
-
-      abstract ImmutableSetMultimap.Builder<TestDepKey, TypeElement> testDepsBuilder();
-
-      abstract ImmutableSetMultimap.Builder<ClassName, TypeElement> uninstalledTestDepsBuilder();
-
-      abstract ImmutableSet.Builder<TypeElement> globalUninstalledTestDepsBuilder();
-
-      abstract Dependencies build();
-    }
-  }
-
-  /**
-   * Pulls the component dependencies from the {@code packageName}.
-   *
-   * <p>Dependency files are generated by the {@link AggregatedDepsProcessor}, and have the form:
-   *
-   * <pre>{@code
-   * {@literal @}AggregatedDeps(
-   *   components = {
-   *       "foo.FooComponent",
-   *       "bar.BarComponent"
-   *   },
-   *   modules = "baz.BazModule"
-   * )
-   *
-   * }</pre>
-   */
-  public static ComponentDependencies from(
-      ImmutableSet<ComponentDescriptor> descriptors, Elements elements) {
-    Map<String, ComponentDescriptor> descriptorLookup = descriptorLookupMap(descriptors);
-    ImmutableList<AggregatedDepMetadata> metadatas =
-        getAggregatedDeps(elements).stream()
-            .map(deps -> AggregatedDepMetadata.create(deps, descriptorLookup, elements))
-            .collect(toImmutableList());
-
-    ComponentDependencies.Builder componentDependencies = ComponentDependencies.builder();
-    for (AggregatedDepMetadata metadata : metadatas) {
-      Dependencies.Builder builder = null;
-      switch (metadata.dependencyType()) {
-        case MODULE:
-          builder = componentDependencies.modulesBuilder();
-          break;
-        case ENTRY_POINT:
-          builder = componentDependencies.entryPointsBuilder();
-          break;
-        case COMPONENT_ENTRY_POINT:
-          builder = componentDependencies.componentEntryPointsBuilder();
-          break;
-      }
-
-      for (ComponentDescriptor componentDescriptor : metadata.componentDescriptors()) {
-        ClassName component = componentDescriptor.component();
-        if (metadata.testElement().isPresent()) {
-          // In this case the @InstallIn or @TestInstallIn applies to only the given test root.
-          ClassName test = ClassName.get(metadata.testElement().get());
-          builder.testDepsBuilder().put(TestDepKey.of(component, test), metadata.dependency());
-          builder.uninstalledTestDepsBuilder().putAll(test, metadata.replacedDependencies());
-        } else {
-          // In this case the @InstallIn or @TestInstallIn applies to all roots
-          if (!metadata.replacedDependencies().isEmpty()) {
-            // If there are replacedDependencies() it means this is a @TestInstallIn
-            builder.globalTestDepsBuilder().put(component, metadata.dependency());
-            builder.globalUninstalledTestDepsBuilder().addAll(metadata.replacedDependencies());
-          } else {
-            builder.globalDepsBuilder().put(component, metadata.dependency());
-          }
-        }
-      }
-    }
-
-    // Collect all @UninstallModules.
-    // TODO(b/176438516): Filter @UninstallModules at the root.
-    metadatas.stream()
-        .filter(metadata -> metadata.testElement().isPresent())
-        .map(metadata -> metadata.testElement().get())
-        .distinct()
-        .filter(testElement -> Processors.hasAnnotation(testElement, ClassNames.IGNORE_MODULES))
-        .forEach(
-            testElement ->
-                componentDependencies
-                    .modulesBuilder()
-                    .uninstalledTestDepsBuilder()
-                    .putAll(
-                        ClassName.get(testElement), getUninstalledModules(testElement, elements)));
-
-    return componentDependencies.build(elements);
-  }
-
-  private static ImmutableMap<String, ComponentDescriptor> descriptorLookupMap(
-      ImmutableSet<ComponentDescriptor> descriptors) {
-    ImmutableMap.Builder<String, ComponentDescriptor> builder = ImmutableMap.builder();
-    for (ComponentDescriptor descriptor : descriptors) {
-      // This is a temporary hack to map the old ApplicationComponent to the new SingletonComponent.
-      // Technically, this is only needed for backwards compatibility with libraries using the old
-      // processor since new processors should convert to the new SingletonComponent when generating
-      // the metadata class.
-      if (descriptor.component().equals(ClassNames.SINGLETON_COMPONENT)) {
-        builder.put("dagger.hilt.android.components.ApplicationComponent", descriptor);
-      }
-      builder.put(descriptor.component().toString(), descriptor);
-    }
-    return builder.build();
-  }
-
-  // Validate that the @UninstallModules doesn't contain any test modules.
-  private static Dependencies validateModules(Dependencies moduleDeps, Elements elements) {
-    SetMultimap<ClassName, TypeElement> invalidTestModules = HashMultimap.create();
-    moduleDeps.testDeps().entries().stream()
-        .filter(
-            e -> moduleDeps.uninstalledTestDeps().containsEntry(e.getKey().test(), e.getValue()))
-        .forEach(e -> invalidTestModules.put(e.getKey().test(), e.getValue()));
-
-    // Currently we don't have a good way to throw an error for all tests, so we sort (to keep the
-    // error reporting order stable) and then choose the first test.
-    // TODO(bcorso): Consider using ProcessorErrorHandler directly to report all errors at once?
-    Optional<ClassName> invalidTest =
-        invalidTestModules.keySet().stream()
-            .min((test1, test2) -> test1.toString().compareTo(test2.toString()));
-    if (invalidTest.isPresent()) {
-      throw new BadInputException(
-          String.format(
-              "@UninstallModules on test, %s, should not containing test modules, "
-                  + "but found: %s",
-              invalidTest.get(),
-              invalidTestModules.get(invalidTest.get()).stream()
-                  // Sort modules to keep stable error messages.
-                  .sorted((test1, test2) -> test1.toString().compareTo(test2.toString()))
-                  .collect(toImmutableList())),
-          elements.getTypeElement(invalidTest.get().toString()));
-    }
-    return moduleDeps;
-  }
-
-  private static ImmutableSet<TypeElement> getUninstalledModules(
-      TypeElement testElement, Elements elements) {
-    ImmutableList<TypeElement> userUninstallModules =
-        Processors.getAnnotationClassValues(
-            elements,
-            Processors.getAnnotationMirror(testElement, ClassNames.IGNORE_MODULES),
-            "value");
-
-    // For pkg-private modules, find the generated wrapper class and uninstall that instead.
-    return userUninstallModules.stream()
-        .map(uninstallModule -> getPublicDependency(uninstallModule, elements))
-        .collect(toImmutableSet());
-  }
-
-  /** Returns the public Hilt wrapper module, or the module itself if its already public. */
-  private static TypeElement getPublicDependency(TypeElement dependency, Elements elements) {
-    return PkgPrivateMetadata.of(elements, dependency, ClassNames.MODULE)
-        .map(metadata -> elements.getTypeElement(metadata.generatedClassName().toString()))
-        .orElse(dependency);
-  }
-
-  /** Returns the top-level elements of the aggregated deps package. */
-  private static ImmutableList<AnnotationMirror> getAggregatedDeps(Elements elements) {
-    PackageElement packageElement = elements.getPackageElement(AGGREGATING_PACKAGE);
-    checkState(
-        packageElement != null,
-        "Couldn't find package %s. Did you mark your @Module classes with @InstallIn annotations?",
-        AGGREGATING_PACKAGE);
-
-    List<? extends Element> aggregatedDepsElements = packageElement.getEnclosedElements();
-    checkState(
-        !aggregatedDepsElements.isEmpty(),
-        "No dependencies found. Did you mark your @Module classes with @InstallIn annotations?");
-
-    ImmutableList.Builder<AnnotationMirror> builder = ImmutableList.builder();
-    for (Element element : aggregatedDepsElements) {
-      ProcessorErrors.checkState(
-          element.getKind() == ElementKind.CLASS,
-          element,
-          "Only classes may be in package %s. Did you add custom code in the package?",
-          AGGREGATING_PACKAGE);
-
-      AnnotationMirror aggregatedDeps =
-          Processors.getAnnotationMirror(element, ClassNames.AGGREGATED_DEPS);
-      ProcessorErrors.checkState(
-          aggregatedDeps != null,
-          element,
-          "Classes in package %s must be annotated with @AggregatedDeps: %s. Found: %s.",
-          AGGREGATING_PACKAGE,
-          element.getSimpleName(),
-          element.getAnnotationMirrors());
-
-      builder.add(aggregatedDeps);
-    }
-    return builder.build();
-  }
-
-  @AutoValue
-  abstract static class AggregatedDepMetadata {
-    static AggregatedDepMetadata create(
-        AnnotationMirror aggregatedDeps,
-        Map<String, ComponentDescriptor> descriptorLookup,
-        Elements elements) {
-      ImmutableMap<String, AnnotationValue> aggregatedDepsValues =
-          Processors.getAnnotationValues(elements, aggregatedDeps);
-
-      return new AutoValue_ComponentDependencies_AggregatedDepMetadata(
-          getTestElement(aggregatedDepsValues.get("test"), elements),
-          getComponents(aggregatedDepsValues.get("components"), descriptorLookup),
-          getDependencyType(
-              aggregatedDepsValues.get("modules"),
-              aggregatedDepsValues.get("entryPoints"),
-              aggregatedDepsValues.get("componentEntryPoints")),
-          getDependency(
-              aggregatedDepsValues.get("modules"),
-              aggregatedDepsValues.get("entryPoints"),
-              aggregatedDepsValues.get("componentEntryPoints"),
-              elements),
-          getReplacedDependencies(aggregatedDepsValues.get("replaces"), elements));
-    }
-
-    enum DependencyType {
-      MODULE,
-      ENTRY_POINT,
-      COMPONENT_ENTRY_POINT
-    }
-
-    abstract Optional<TypeElement> testElement();
-
-    abstract ImmutableList<ComponentDescriptor> componentDescriptors();
-
-    abstract DependencyType dependencyType();
-
-    abstract TypeElement dependency();
-
-    abstract ImmutableSet<TypeElement> replacedDependencies();
-
-    private static Optional<TypeElement> getTestElement(
-        AnnotationValue testValue, Elements elements) {
-      checkNotNull(testValue);
-      String test = AnnotationValues.getString(testValue);
-      return test.isEmpty() ? Optional.empty() : Optional.of(elements.getTypeElement(test));
-    }
-
-    private static ImmutableList<ComponentDescriptor> getComponents(
-        AnnotationValue componentsValue, Map<String, ComponentDescriptor> descriptorLookup) {
-      checkNotNull(componentsValue);
-      ImmutableList<String> componentNames =
-          AnnotationValues.getAnnotationValues(componentsValue).stream()
-              .map(AnnotationValues::getString)
-              .collect(toImmutableList());
-
-      checkState(!componentNames.isEmpty());
-      ImmutableList.Builder<ComponentDescriptor> components = ImmutableList.builder();
-      for (String componentName : componentNames) {
-        checkState(
-            descriptorLookup.containsKey(componentName),
-            "%s is not a valid Component. Did you add or remove code in package %s?",
-            componentName,
-            AGGREGATING_PACKAGE);
-        components.add(descriptorLookup.get(componentName));
-      }
-      return components.build();
-    }
-
-    private static DependencyType getDependencyType(
-        AnnotationValue modulesValue,
-        AnnotationValue entryPointsValue,
-        AnnotationValue componentEntryPointsValue) {
-      checkNotNull(modulesValue);
-      checkNotNull(entryPointsValue);
-      checkNotNull(componentEntryPointsValue);
-
-      ImmutableSet.Builder<DependencyType> dependencyTypes = ImmutableSet.builder();
-      if (!AnnotationValues.getAnnotationValues(modulesValue).isEmpty()) {
-        dependencyTypes.add(DependencyType.MODULE);
-      }
-      if (!AnnotationValues.getAnnotationValues(entryPointsValue).isEmpty()) {
-        dependencyTypes.add(DependencyType.ENTRY_POINT);
-      }
-      if (!AnnotationValues.getAnnotationValues(componentEntryPointsValue).isEmpty()) {
-        dependencyTypes.add(DependencyType.COMPONENT_ENTRY_POINT);
-      }
-      return getOnlyElement(dependencyTypes.build());
-    }
-
-    private static TypeElement getDependency(
-        AnnotationValue modulesValue,
-        AnnotationValue entryPointsValue,
-        AnnotationValue componentEntryPointsValue,
-        Elements elements) {
-      checkNotNull(modulesValue);
-      checkNotNull(entryPointsValue);
-      checkNotNull(componentEntryPointsValue);
-
-      return elements.getTypeElement(
-          AnnotationValues.getString(
-              getOnlyElement(
-                  ImmutableList.<AnnotationValue>builder()
-                      .addAll(AnnotationValues.getAnnotationValues(modulesValue))
-                      .addAll(AnnotationValues.getAnnotationValues(entryPointsValue))
-                      .addAll(AnnotationValues.getAnnotationValues(componentEntryPointsValue))
-                      .build())));
-    }
-
-    private static ImmutableSet<TypeElement> getReplacedDependencies(
-        AnnotationValue replacedDependenciesValue, Elements elements) {
-      // Allow null values to support libraries using a Hilt version before @TestInstallIn was added
-      return replacedDependenciesValue == null
-          ? ImmutableSet.of()
-          : AnnotationValues.getAnnotationValues(replacedDependenciesValue).stream()
-              .map(AnnotationValues::getString)
-              .map(elements::getTypeElement)
-              .map(replacedDep -> getPublicDependency(replacedDep, elements))
-              .collect(toImmutableSet());
-    }
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateEntryPointGenerator.java b/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateEntryPointGenerator.java
deleted file mode 100644
index 6dac59f..0000000
--- a/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateEntryPointGenerator.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.aggregateddeps;
-
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/**
- * Generates a public Dagger entrypoint that includes a user's pkg-private entrypoint. This allows a
- * user's entrypoint to use pkg-private visibility to hide from external packages.
- */
-final class PkgPrivateEntryPointGenerator {
-  private final ProcessingEnvironment env;
-  private final PkgPrivateMetadata metadata;
-
-  PkgPrivateEntryPointGenerator(ProcessingEnvironment env, PkgPrivateMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-  }
-
-  // This method creates the following generated code for an EntryPoint in pkg.MyEntryPoint that is
-  // package
-  // private
-  //
-  // package pkg; //same package
-  //
-  // import dagger.hilt.InstallIn;
-  // import dagger.hilt.EntryPoint;;
-  // import javax.annotation.Generated;
-  //
-  // @Generated("dagger.hilt.processor.internal.aggregateddeps.PkgPrivateEntryPointGenerator")
-  // @InstallIn(InstallIn.Component.ACTIVITY)
-  // @EntryPoint
-  // public final class HiltWrapper_MyEntryPoint extends MyEntryPoint  {
-  // }
-  void generate() throws IOException {
-
-    TypeSpec.Builder entryPointInterfaceBuilder =
-        TypeSpec.interfaceBuilder(metadata.generatedClassName().simpleName())
-            .addOriginatingElement(metadata.getTypeElement())
-            .addAnnotation(Processors.getOriginatingElementAnnotation(metadata.getTypeElement()))
-            .addModifiers(Modifier.PUBLIC)
-            .addSuperinterface(metadata.baseClassName())
-            .addAnnotation(metadata.getAnnotation());
-
-    Processors.addGeneratedAnnotation(entryPointInterfaceBuilder, env, getClass());
-
-    if (metadata.getOptionalInstallInAnnotationMirror().isPresent()) {
-      entryPointInterfaceBuilder.addAnnotation(
-          AnnotationSpec.get(metadata.getOptionalInstallInAnnotationMirror().get()));
-    }
-
-    JavaFile.builder(
-            metadata.generatedClassName().packageName(), entryPointInterfaceBuilder.build())
-        .build()
-        .writeTo(env.getFiler());
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateMetadata.java b/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateMetadata.java
deleted file mode 100644
index 66f1751..0000000
--- a/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateMetadata.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.aggregateddeps;
-
-import static com.google.auto.common.Visibility.effectiveVisibilityOfElement;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.Visibility;
-import com.google.auto.value.AutoValue;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.TypeName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.Elements;
-
-/** PkgPrivateModuleMetadata contains a set of utilities for processing package private modules. */
-@AutoValue
-abstract class PkgPrivateMetadata {
-  private static final String PREFIX = "HiltWrapper_";
-
-  /** Returns the base class name of the elemenet. */
-  TypeName baseClassName() {
-    return TypeName.get(getTypeElement().asType());
-  }
-
-  /** Returns TypeElement for the module element the metadata object represents */
-  abstract TypeElement getTypeElement();
-
-  /**
-   * Returns an optional @InstallIn AnnotationMirror for the module element the metadata object
-   * represents
-   */
-  abstract Optional<AnnotationMirror> getOptionalInstallInAnnotationMirror();
-
-  /** Return the Type of this package private element. */
-  abstract ClassName getAnnotation();
-
-  /** Returns the expected genenerated classname for the element the metadata object represents */
-  final ClassName generatedClassName() {
-    return Processors.prepend(
-        Processors.getEnclosedClassName(ClassName.get(getTypeElement())), PREFIX);
-  }
-
-  /**
-   * Returns an Optional PkgPrivateMetadata requiring Hilt processing, otherwise returns an empty
-   * Optional.
-   */
-  static Optional<PkgPrivateMetadata> of(Elements elements, Element element, ClassName annotation) {
-    // If this is a public element no wrapping is needed
-    if (effectiveVisibilityOfElement(element) == Visibility.PUBLIC) {
-      return Optional.empty();
-    }
-
-    Optional<AnnotationMirror> installIn;
-    if (Processors.hasAnnotation(element, ClassNames.INSTALL_IN)) {
-      installIn = Optional.of(Processors.getAnnotationMirror(element, ClassNames.INSTALL_IN));
-    } else if (Processors.hasAnnotation(element, ClassNames.TEST_INSTALL_IN)) {
-      installIn = Optional.of(Processors.getAnnotationMirror(element, ClassNames.TEST_INSTALL_IN));
-    } else {
-      throw new IllegalStateException(
-          "Expected element to be annotated with @InstallIn: " + element);
-    }
-
-    if (annotation.equals(ClassNames.MODULE)
-        ) {
-      // Skip modules that require a module instance. Required by
-      // dagger (b/31489617)
-      if (Processors.requiresModuleInstance(elements, MoreElements.asType(element))) {
-        return Optional.empty();
-      }
-    }
-    return Optional.of(
-        new AutoValue_PkgPrivateMetadata(MoreElements.asType(element), installIn, annotation));
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateModuleGenerator.java b/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateModuleGenerator.java
deleted file mode 100644
index 18ff0bd..0000000
--- a/java/dagger/hilt/processor/internal/aggregateddeps/PkgPrivateModuleGenerator.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.aggregateddeps;
-
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/**
- * Generates a public Dagger module that includes a user's pkg-private module. This allows a user's
- * module to use pkg-private visibility to hide from external packages, but still allows Hilt to
- * install the module when the component is created in another package.
- */
-final class PkgPrivateModuleGenerator {
-  private final ProcessingEnvironment env;
-  private final PkgPrivateMetadata metadata;
-
-  PkgPrivateModuleGenerator(ProcessingEnvironment env, PkgPrivateMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-  }
-
-  // This method creates the following generated code for a pkg-private module, pkg.MyModule:
-  //
-  // package pkg; //same as module
-  //
-  // import dagger.Module;
-  // import dagger.hilt.InstallIn;
-  // import javax.annotation.Generated;
-  //
-  // @Generated("dagger.hilt.processor.internal.aggregateddeps.PkgPrivateModuleGenerator")
-  // @InstallIn(ActivityComponent.class)
-  // @Module(includes = MyModule.class)
-  // public final class HiltModuleWrapper_MyModule {}
-  void generate() throws IOException {
-    TypeSpec.Builder builder =
-        TypeSpec.classBuilder(metadata.generatedClassName().simpleName())
-            .addOriginatingElement(metadata.getTypeElement())
-            .addAnnotation(Processors.getOriginatingElementAnnotation(metadata.getTypeElement()))
-            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-            // generated @InstallIn is exactly the same as the module being processed
-            .addAnnotation(
-                AnnotationSpec.get(metadata.getOptionalInstallInAnnotationMirror().get()))
-            .addAnnotation(
-                AnnotationSpec.builder(metadata.getAnnotation())
-                    .addMember("includes", "$T.class", metadata.getTypeElement())
-                    .build());
-
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-
-    JavaFile.builder(metadata.generatedClassName().packageName(), builder.build())
-        .build()
-        .writeTo(env.getFiler());
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aliasof/AliasOfProcessor.java b/java/dagger/hilt/processor/internal/aliasof/AliasOfProcessor.java
deleted file mode 100644
index 6efd643..0000000
--- a/java/dagger/hilt/processor/internal/aliasof/AliasOfProcessor.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.aliasof;
-
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableSet;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import java.util.Set;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/** Processes the annotations annotated with {@link dagger.hilt.migration.AliasOf} */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class AliasOfProcessor extends BaseProcessor {
-  @Override
-  public Set<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.of(ClassNames.ALIAS_OF.toString());
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    ProcessorErrors.checkState(
-        Processors.hasAnnotation(element, ClassNames.SCOPE),
-        element,
-        "%s should only be used on scopes." + " However, it was found annotating %s",
-        annotation,
-        element);
-    AnnotationMirror annotationMirror =
-        Processors.getAnnotationMirror(element, ClassNames.ALIAS_OF);
-
-    Element defineComponentScope =
-        Processors.getAnnotationClassValue(getElementUtils(), annotationMirror, "value");
-
-    new AliasOfPropagatedDataGenerator(getProcessingEnv(), element, defineComponentScope)
-        .generate();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aliasof/AliasOfPropagatedDataGenerator.java b/java/dagger/hilt/processor/internal/aliasof/AliasOfPropagatedDataGenerator.java
deleted file mode 100644
index 75c4c15..0000000
--- a/java/dagger/hilt/processor/internal/aliasof/AliasOfPropagatedDataGenerator.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.aliasof;
-
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-
-/** Generates resource files for {@link dagger.hilt.migration.AliasOf}. */
-final class AliasOfPropagatedDataGenerator {
-
-  private final ProcessingEnvironment processingEnv;
-  private final Element aliasScope;
-  private final Element defineComponentScope;
-
-  AliasOfPropagatedDataGenerator(
-      ProcessingEnvironment processingEnv, Element aliasScope, Element defineComponentScope) {
-    this.processingEnv = processingEnv;
-    this.aliasScope = aliasScope;
-    this.defineComponentScope = defineComponentScope;
-  }
-
-  void generate() throws IOException {
-    TypeSpec.Builder generator =
-        TypeSpec.classBuilder(Processors.getFullEnclosedName(aliasScope))
-            .addOriginatingElement(aliasScope)
-            .addAnnotation(
-                AnnotationSpec.builder(ClassNames.ALIAS_OF_PROPAGATED_DATA)
-                    .addMember("defineComponentScope", "$T.class", defineComponentScope)
-                    .addMember("alias", "$T.class", aliasScope)
-                    .build())
-            .addJavadoc("Generated class for aggregating scope aliases. \n");
-
-    Processors.addGeneratedAnnotation(generator, processingEnv, getClass());
-
-    JavaFile.builder(AliasOfs.AGGREGATING_PACKAGE, generator.build())
-        .build()
-        .writeTo(processingEnv.getFiler());
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aliasof/AliasOfs.java b/java/dagger/hilt/processor/internal/aliasof/AliasOfs.java
deleted file mode 100644
index 930a72e..0000000
--- a/java/dagger/hilt/processor/internal/aliasof/AliasOfs.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.aliasof;
-
-import static com.google.common.base.Suppliers.memoize;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import java.util.List;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.Elements;
-
-/**
- * Extracts a multimap of aliases annotated with {@link dagger.hilt.migration.AliasOf} mapping them
- * to scopes they are alias of.
- */
-public final class AliasOfs {
-  static final String AGGREGATING_PACKAGE = AliasOfs.class.getPackage().getName() + ".codegen";
-
-  private final ProcessingEnvironment processingEnvironment;
-  private final ImmutableSet<ClassName> defineComponentScopes;
-  private final Supplier<ImmutableMultimap<ClassName, ClassName>> aliases =
-      memoize(() -> getAliases());
-
-  public AliasOfs(
-      ProcessingEnvironment processingEnvironment, ImmutableSet<ClassName> defineComponentScopes) {
-    this.defineComponentScopes = defineComponentScopes;
-    this.processingEnvironment = processingEnvironment;
-  }
-
-  public ImmutableSet<ClassName> getAliasesFor(ClassName defineComponentScope) {
-    return ImmutableSet.copyOf(aliases.get().get(defineComponentScope));
-  }
-
-  private ImmutableMultimap<ClassName, ClassName> getAliases() {
-    Elements elements = processingEnvironment.getElementUtils();
-    PackageElement packageElement = elements.getPackageElement(AGGREGATING_PACKAGE);
-    if (packageElement == null) {
-      return ImmutableMultimap.of();
-    }
-    List<? extends Element> scopeAliasElements = packageElement.getEnclosedElements();
-    Preconditions.checkState(
-        !scopeAliasElements.isEmpty(), "No scope aliases Found in package %s.", packageElement);
-
-    ImmutableMultimap.Builder<ClassName, ClassName> builder = ImmutableMultimap.builder();
-    for (Element element : scopeAliasElements) {
-      ProcessorErrors.checkState(
-          element.getKind() == ElementKind.CLASS,
-          element,
-          "Only classes may be in package %s. Did you add custom code in the package?",
-          packageElement);
-
-      AnnotationMirror annotationMirror =
-          Processors.getAnnotationMirror(element, ClassNames.ALIAS_OF_PROPAGATED_DATA);
-
-      ProcessorErrors.checkState(
-          annotationMirror != null,
-          element,
-          "Classes in package %s must be annotated with @%s: %s."
-              + " Found: %s. Files in this package are generated, did you add custom code in the"
-              + " package? ",
-          packageElement,
-          ClassNames.ALIAS_OF_PROPAGATED_DATA,
-          element.getSimpleName(),
-          element.getAnnotationMirrors());
-
-      TypeElement defineComponentScope =
-          Processors.getAnnotationClassValue(elements, annotationMirror, "defineComponentScope");
-      TypeElement alias = Processors.getAnnotationClassValue(elements, annotationMirror, "alias");
-
-      Preconditions.checkState(
-          defineComponentScopes.contains(ClassName.get(defineComponentScope)),
-          "The scope %s cannot be an alias for %s. You can only have aliases of a scope defined"
-              + " directly on a @DefineComponent type.",
-          ClassName.get(alias),
-          ClassName.get(defineComponentScope));
-
-      builder.put(ClassName.get(defineComponentScope), ClassName.get(alias));
-    }
-
-    return builder.build();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/aliasof/BUILD b/java/dagger/hilt/processor/internal/aliasof/BUILD
deleted file mode 100644
index d3f90f2..0000000
--- a/java/dagger/hilt/processor/internal/aliasof/BUILD
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   A processor for @dagger.hilt.AliasOfProcessor.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.processor.internal.aliasof.AliasOfProcessor",
-    deps = [":processor_lib"],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "AliasOfProcessor.java",
-        "AliasOfPropagatedDataGenerator.java",
-    ],
-    deps = [
-        ":alias_ofs",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-java_library(
-    name = "alias_ofs",
-    srcs = [
-        "AliasOfs.java",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/definecomponent/BUILD b/java/dagger/hilt/processor/internal/definecomponent/BUILD
deleted file mode 100644
index 7edec1c..0000000
--- a/java/dagger/hilt/processor/internal/definecomponent/BUILD
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   A processor for @dagger.hilt.DefineComponent.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.processor.internal.definecomponent.DefineComponentProcessor",
-    deps = [":processor_lib"],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "DefineComponentProcessor.java",
-    ],
-    deps = [
-        ":define_components",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-java_library(
-    name = "define_components",
-    srcs = [
-        "DefineComponentBuilderMetadatas.java",
-        "DefineComponentMetadatas.java",
-        "DefineComponents.java",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:component_descriptor",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:graph",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/definecomponent/DefineComponentBuilderMetadatas.java b/java/dagger/hilt/processor/internal/definecomponent/DefineComponentBuilderMetadatas.java
deleted file mode 100644
index 0f10f39..0000000
--- a/java/dagger/hilt/processor/internal/definecomponent/DefineComponentBuilderMetadatas.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.definecomponent;
-
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.TypeName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import dagger.hilt.processor.internal.definecomponent.DefineComponentMetadatas.DefineComponentMetadata;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-
-/** Metadata for types annotated with {@link dagger.hilt.DefineComponent.Builder}. */
-final class DefineComponentBuilderMetadatas {
-  static DefineComponentBuilderMetadatas create(DefineComponentMetadatas componentMetadatas) {
-    return new DefineComponentBuilderMetadatas(componentMetadatas);
-  }
-
-  private final Map<Element, DefineComponentBuilderMetadata> builderMetadatas = new HashMap<>();
-  private final DefineComponentMetadatas componentMetadatas;
-
-  private DefineComponentBuilderMetadatas(DefineComponentMetadatas componentMetadatas) {
-    this.componentMetadatas = componentMetadatas;
-  }
-
-  DefineComponentBuilderMetadata get(Element element) {
-    if (!builderMetadatas.containsKey(element)) {
-      builderMetadatas.put(element, getUncached(element));
-    }
-    return builderMetadatas.get(element);
-  }
-
-  private DefineComponentBuilderMetadata getUncached(Element element) {
-    ProcessorErrors.checkState(
-        Processors.hasAnnotation(element, ClassNames.DEFINE_COMPONENT_BUILDER),
-        element,
-        "%s, expected to be annotated with @DefineComponent.Builder. Found: %s",
-        element,
-        element.getAnnotationMirrors());
-
-    // TODO(bcorso): Allow abstract classes?
-    ProcessorErrors.checkState(
-        element.getKind().equals(ElementKind.INTERFACE),
-        element,
-        "@DefineComponent.Builder is only allowed on interfaces. Found: %s",
-        element);
-    TypeElement builder = MoreElements.asType(element);
-
-    // TODO(bcorso): Allow extending interfaces?
-    ProcessorErrors.checkState(
-        builder.getInterfaces().isEmpty(),
-        builder,
-        "@DefineComponent.Builder %s, cannot extend a super class or interface. Found: %s",
-        builder,
-        builder.getInterfaces());
-
-    // TODO(bcorso): Allow type parameters?
-    ProcessorErrors.checkState(
-        builder.getTypeParameters().isEmpty(),
-        builder,
-        "@DefineComponent.Builder %s, cannot have type parameters.",
-        builder.asType());
-
-    List<VariableElement> nonStaticFields =
-        ElementFilter.fieldsIn(builder.getEnclosedElements()).stream()
-            .filter(method -> !method.getModifiers().contains(STATIC))
-            .collect(Collectors.toList());
-    ProcessorErrors.checkState(
-        nonStaticFields.isEmpty(),
-        builder,
-        "@DefineComponent.Builder %s, cannot have non-static fields. Found: %s",
-        builder,
-        nonStaticFields);
-
-    List<ExecutableElement> buildMethods =
-        ElementFilter.methodsIn(builder.getEnclosedElements()).stream()
-            .filter(method -> !method.getModifiers().contains(STATIC))
-            .filter(method -> method.getParameters().isEmpty())
-            .collect(Collectors.toList());
-
-    ProcessorErrors.checkState(
-        buildMethods.size() == 1,
-        builder,
-        "@DefineComponent.Builder %s, must have exactly 1 build method that takes no parameters. "
-            + "Found: %s",
-        builder,
-        buildMethods);
-
-    ExecutableElement buildMethod = buildMethods.get(0);
-    TypeMirror component = buildMethod.getReturnType();
-    ProcessorErrors.checkState(
-        buildMethod.getReturnType().getKind().equals(TypeKind.DECLARED)
-            && Processors.hasAnnotation(
-                MoreTypes.asTypeElement(component), ClassNames.DEFINE_COMPONENT),
-        builder,
-        "@DefineComponent.Builder method, %s#%s, must return a @DefineComponent type. Found: %s",
-        builder,
-        buildMethod,
-        component);
-
-    List<ExecutableElement> nonStaticNonBuilderMethods =
-        ElementFilter.methodsIn(builder.getEnclosedElements()).stream()
-            .filter(method -> !method.getModifiers().contains(STATIC))
-            .filter(method -> !method.equals(buildMethod))
-            .filter(method -> !TypeName.get(method.getReturnType()).equals(ClassName.get(builder)))
-            .collect(Collectors.toList());
-
-    ProcessorErrors.checkState(
-        nonStaticNonBuilderMethods.isEmpty(),
-        nonStaticNonBuilderMethods,
-        "@DefineComponent.Builder %s, all non-static methods must return %s or %s. Found: %s",
-        builder,
-        builder,
-        component,
-        nonStaticNonBuilderMethods);
-
-    return new AutoValue_DefineComponentBuilderMetadatas_DefineComponentBuilderMetadata(
-        builder,
-        buildMethod,
-        componentMetadatas.get(MoreTypes.asTypeElement(component)));
-  }
-
-  @AutoValue
-  abstract static class DefineComponentBuilderMetadata {
-    abstract TypeElement builder();
-
-    abstract ExecutableElement buildMethod();
-
-    abstract DefineComponentMetadata componentMetadata();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/definecomponent/DefineComponentMetadatas.java b/java/dagger/hilt/processor/internal/definecomponent/DefineComponentMetadatas.java
deleted file mode 100644
index aa69e40..0000000
--- a/java/dagger/hilt/processor/internal/definecomponent/DefineComponentMetadatas.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.definecomponent;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationElementAndValue;
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static java.util.stream.Collectors.joining;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.AnnotationValues;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.ElementFilter;
-
-/** Metadata for types annotated with {@link dagger.hilt.DefineComponent}. */
-final class DefineComponentMetadatas {
-  static DefineComponentMetadatas create() {
-    return new DefineComponentMetadatas();
-  }
-
-  private final Map<Element, DefineComponentMetadata> metadatas = new HashMap<>();
-
-  private DefineComponentMetadatas() {}
-
-  /** Returns the metadata for an element annotated with {@link dagger.hilt.DefineComponent}. */
-  DefineComponentMetadata get(Element element) {
-    return get(element, new LinkedHashSet<>());
-  }
-
-  private DefineComponentMetadata get(Element element, LinkedHashSet<Element> childPath) {
-    if (!metadatas.containsKey(element)) {
-      metadatas.put(element, getUncached(element, childPath));
-    }
-    return metadatas.get(element);
-  }
-
-  private DefineComponentMetadata getUncached(
-      Element element, LinkedHashSet<Element> childPath) {
-    ProcessorErrors.checkState(
-        childPath.add(element),
-        element,
-        "@DefineComponent cycle: %s -> %s",
-        childPath.stream().map(Object::toString).collect(joining(" -> ")),
-        element);
-
-    ProcessorErrors.checkState(
-        Processors.hasAnnotation(element, ClassNames.DEFINE_COMPONENT),
-        element,
-        "%s, expected to be annotated with @DefineComponent. Found: %s",
-        element,
-        element.getAnnotationMirrors());
-
-    // TODO(bcorso): Allow abstract classes?
-    ProcessorErrors.checkState(
-        element.getKind().equals(ElementKind.INTERFACE),
-        element,
-        "@DefineComponent is only allowed on interfaces. Found: %s",
-        element);
-    TypeElement component = asType(element);
-
-    // TODO(bcorso): Allow extending interfaces?
-    ProcessorErrors.checkState(
-        component.getInterfaces().isEmpty(),
-        component,
-        "@DefineComponent %s, cannot extend a super class or interface. Found: %s",
-        component,
-        component.getInterfaces());
-
-    // TODO(bcorso): Allow type parameters?
-    ProcessorErrors.checkState(
-        component.getTypeParameters().isEmpty(),
-        component,
-        "@DefineComponent %s, cannot have type parameters.",
-        component.asType());
-
-    // TODO(bcorso): Allow non-static abstract methods (aka EntryPoints)?
-    List<ExecutableElement> nonStaticMethods =
-        ElementFilter.methodsIn(component.getEnclosedElements()).stream()
-            .filter(method -> !method.getModifiers().contains(STATIC))
-            .collect(Collectors.toList());
-    ProcessorErrors.checkState(
-        nonStaticMethods.isEmpty(),
-        component,
-        "@DefineComponent %s, cannot have non-static methods. Found: %s",
-        component,
-        nonStaticMethods);
-
-    // No need to check non-static fields since interfaces can't have them.
-
-    ImmutableList<TypeElement> scopes =
-        Processors.getScopeAnnotations(component).stream()
-            .map(AnnotationMirror::getAnnotationType)
-            .map(MoreTypes::asTypeElement)
-            .collect(toImmutableList());
-
-    ImmutableList<AnnotationMirror> aliasScopes =
-        Processors.getAnnotationsAnnotatedWith(component, ClassNames.ALIAS_OF);
-    ProcessorErrors.checkState(
-        aliasScopes.isEmpty(),
-        component,
-        "@DefineComponent %s, references invalid scope(s) annotated with @AliasOf. "
-            + "@DefineComponent scopes cannot be aliases of other scopes: %s",
-        component,
-        aliasScopes);
-
-    AnnotationMirror mirror =
-        Processors.getAnnotationMirror(component, ClassNames.DEFINE_COMPONENT);
-    AnnotationValue parentValue = getAnnotationElementAndValue(mirror, "parent").getValue();
-
-    ProcessorErrors.checkState(
-        // TODO(bcorso): Contribute a check to auto/common AnnotationValues.
-        !"<error>".contentEquals(parentValue.getValue().toString()),
-        component,
-        "@DefineComponent %s, references an invalid parent type: %s",
-        component,
-        mirror);
-
-    TypeElement parent = asTypeElement(AnnotationValues.getTypeMirror(parentValue));
-
-    ProcessorErrors.checkState(
-        ClassName.get(parent).equals(ClassNames.DEFINE_COMPONENT_NO_PARENT)
-            || Processors.hasAnnotation(parent, ClassNames.DEFINE_COMPONENT),
-        component,
-        "@DefineComponent %s, references a type not annotated with @DefineComponent: %s",
-        component,
-        parent);
-
-    Optional<DefineComponentMetadata> parentComponent =
-        ClassName.get(parent).equals(ClassNames.DEFINE_COMPONENT_NO_PARENT)
-            ? Optional.empty()
-            : Optional.of(get(parent, childPath));
-
-    ProcessorErrors.checkState(
-        parentComponent.isPresent()
-            || ClassName.get(component).equals(ClassNames.SINGLETON_COMPONENT),
-        component,
-        "@DefineComponent %s is missing a parent declaration.\n"
-            + "Please declare the parent, for example: @DefineComponent(parent ="
-            + " SingletonComponent.class)",
-        component);
-
-    return new AutoValue_DefineComponentMetadatas_DefineComponentMetadata(
-        component, scopes, parentComponent);
-  }
-
-  @AutoValue
-  abstract static class DefineComponentMetadata {
-
-    /** Returns the component annotated with {@link dagger.hilt.DefineComponent}. */
-    abstract TypeElement component();
-
-    /** Returns the scopes of the component. */
-    abstract ImmutableList<TypeElement> scopes();
-
-    /** Returns the parent component, if one exists. */
-    abstract Optional<DefineComponentMetadata> parentMetadata();
-
-    boolean isRoot() {
-      return !parentMetadata().isPresent();
-    }
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/definecomponent/DefineComponentProcessor.java b/java/dagger/hilt/processor/internal/definecomponent/DefineComponentProcessor.java
deleted file mode 100644
index e0bfca9..0000000
--- a/java/dagger/hilt/processor/internal/definecomponent/DefineComponentProcessor.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.definecomponent;
-
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import dagger.hilt.processor.internal.definecomponent.DefineComponentBuilderMetadatas.DefineComponentBuilderMetadata;
-import dagger.hilt.processor.internal.definecomponent.DefineComponentMetadatas.DefineComponentMetadata;
-import java.io.IOException;
-import java.util.Set;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/**
- * A processor for {@link dagger.hilt.DefineComponent} and {@link
- * dagger.hilt.DefineComponent.Builder}.
- */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class DefineComponentProcessor extends BaseProcessor {
-  private final DefineComponentMetadatas componentMetadatas = DefineComponentMetadatas.create();
-  private final DefineComponentBuilderMetadatas componentBuilderMetadatas =
-      DefineComponentBuilderMetadatas.create(componentMetadatas);
-
-  @Override
-  public Set<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.of(
-        ClassNames.DEFINE_COMPONENT.toString(), ClassNames.DEFINE_COMPONENT_BUILDER.toString());
-  }
-
-  @Override
-  protected void processEach(TypeElement annotation, Element element) throws Exception {
-    if (ClassName.get(annotation).equals(ClassNames.DEFINE_COMPONENT)) {
-      // TODO(bcorso): For cycles we currently process each element in the cycle. We should skip
-      // processing of subsequent elements in a cycle, but this requires ensuring that the first
-      // element processed is always the same so that our failure tests are stable.
-      DefineComponentMetadata metadata = componentMetadatas.get(element);
-      generateFile("component", metadata.component());
-    } else if (ClassName.get(annotation).equals(ClassNames.DEFINE_COMPONENT_BUILDER)) {
-      DefineComponentBuilderMetadata metadata = componentBuilderMetadatas.get(element);
-      generateFile("builder", metadata.builder());
-    } else {
-      throw new AssertionError("Unhandled annotation type: " + annotation);
-    }
-  }
-
-  private void generateFile(String member, TypeElement typeElement) throws IOException {
-    TypeSpec.Builder builder =
-        TypeSpec.interfaceBuilder(Processors.getFullEnclosedName(typeElement))
-            .addOriginatingElement(typeElement)
-            .addAnnotation(
-                AnnotationSpec.builder(ClassNames.DEFINE_COMPONENT_CLASSES)
-                    .addMember(member, "$S", typeElement.getQualifiedName())
-                    .build());
-
-    Processors.addGeneratedAnnotation(builder, processingEnv, getClass());
-
-    JavaFile.builder(DefineComponents.AGGREGATING_PACKAGE, builder.build())
-        .build()
-        .writeTo(processingEnv.getFiler());
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/definecomponent/DefineComponents.java b/java/dagger/hilt/processor/internal/definecomponent/DefineComponents.java
deleted file mode 100644
index 0b33011..0000000
--- a/java/dagger/hilt/processor/internal/definecomponent/DefineComponents.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.definecomponent;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationElementAndValue;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ListMultimap;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.AnnotationValues;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ComponentDescriptor;
-import dagger.hilt.processor.internal.ComponentTree;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import dagger.hilt.processor.internal.definecomponent.DefineComponentBuilderMetadatas.DefineComponentBuilderMetadata;
-import dagger.hilt.processor.internal.definecomponent.DefineComponentMetadatas.DefineComponentMetadata;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.Elements;
-
-/**
- * A utility class for getting {@link DefineComponentMetadata} and {@link
- * DefineComponentBuilderMetadata}.
- */
-public final class DefineComponents {
-  static final String AGGREGATING_PACKAGE =
-      DefineComponents.class.getPackage().getName() + ".codegen";
-
-  public static DefineComponents create() {
-    return new DefineComponents();
-  }
-
-  private final Map<Element, ComponentDescriptor> componentDescriptors = new HashMap<>();
-  private final DefineComponentMetadatas componentMetadatas = DefineComponentMetadatas.create();
-  private final DefineComponentBuilderMetadatas componentBuilderMetadatas =
-      DefineComponentBuilderMetadatas.create(componentMetadatas);
-
-  private DefineComponents() {}
-
-  /** Returns the {@link ComponentDescriptor} for the given component element. */
-  // TODO(b/144940889): This descriptor doesn't contain the "creator" or the "installInName".
-  public ComponentDescriptor componentDescriptor(Element element) {
-    if (!componentDescriptors.containsKey(element)) {
-      componentDescriptors.put(element, uncachedComponentDescriptor(element));
-    }
-    return componentDescriptors.get(element);
-  }
-
-  private ComponentDescriptor uncachedComponentDescriptor(Element element) {
-    DefineComponentMetadata metadata = componentMetadatas.get(element);
-    ComponentDescriptor.Builder builder =
-        ComponentDescriptor.builder()
-            .component(ClassName.get(metadata.component()))
-            .scopes(metadata.scopes().stream().map(ClassName::get).collect(toImmutableSet()));
-
-
-    metadata.parentMetadata()
-        .map(DefineComponentMetadata::component)
-        .map(this::componentDescriptor)
-        .ifPresent(builder::parent);
-
-    return builder.build();
-  }
-
-  /** Returns the {@link ComponentTree} from the aggregated {@link ComponentDescriptor}s. */
-  public ComponentTree getComponentTree(Elements elements) {
-    AggregatedMetadata aggregatedMetadata =
-        AggregatedMetadata.from(elements, componentMetadatas, componentBuilderMetadatas);
-    ListMultimap<DefineComponentMetadata, DefineComponentBuilderMetadata> builderMultimap =
-        ArrayListMultimap.create();
-    aggregatedMetadata.builders()
-        .forEach(builder -> builderMultimap.put(builder.componentMetadata(), builder));
-
-    // Check that there are not multiple builders per component
-    for (DefineComponentMetadata componentMetadata : builderMultimap.keySet()) {
-      TypeElement component = componentMetadata.component();
-      ProcessorErrors.checkState(
-          builderMultimap.get(componentMetadata).size() <= 1,
-          component,
-          "Multiple @%s declarations are not allowed for @%s type, %s. Found: %s",
-          ClassNames.DEFINE_COMPONENT_BUILDER,
-          ClassNames.DEFINE_COMPONENT,
-          component,
-          builderMultimap.get(componentMetadata).stream()
-              .map(DefineComponentBuilderMetadata::builder)
-              .map(TypeElement::toString)
-              .sorted()
-              .collect(toImmutableList()));
-    }
-
-    // Now that we know there is at most 1 builder per component, convert the Multimap to Map.
-    Map<DefineComponentMetadata, DefineComponentBuilderMetadata> builderMap = new LinkedHashMap<>();
-    builderMultimap.entries().forEach(e -> builderMap.put(e.getKey(), e.getValue()));
-
-
-    return ComponentTree.from(aggregatedMetadata.components().stream()
-        .map(componentMetadata -> toComponentDescriptor(componentMetadata, builderMap))
-        .collect(toImmutableSet()));
-  }
-
-  private static ComponentDescriptor toComponentDescriptor(
-      DefineComponentMetadata componentMetadata,
-      Map<DefineComponentMetadata, DefineComponentBuilderMetadata> builderMap) {
-    ComponentDescriptor.Builder builder =
-        ComponentDescriptor.builder()
-            .component(ClassName.get(componentMetadata.component()))
-            .scopes(
-                componentMetadata.scopes().stream().map(ClassName::get).collect(toImmutableSet()));
-
-
-    if (builderMap.containsKey(componentMetadata)) {
-      builder.creator(ClassName.get(builderMap.get(componentMetadata).builder()));
-    }
-
-    componentMetadata
-        .parentMetadata()
-        .map(parent -> toComponentDescriptor(parent, builderMap))
-        .ifPresent(builder::parent);
-
-    return builder.build();
-  }
-
-  @AutoValue
-  abstract static class AggregatedMetadata {
-    /** Returns the aggregated metadata for {@link DefineComponentClasses#component()}. */
-    abstract ImmutableList<DefineComponentMetadata> components();
-
-    /** Returns the aggregated metadata for {@link DefineComponentClasses#builder()}. */
-    abstract ImmutableList<DefineComponentBuilderMetadata> builders();
-
-    static AggregatedMetadata from(
-        Elements elements,
-        DefineComponentMetadatas componentMetadatas,
-        DefineComponentBuilderMetadatas componentBuilderMetadatas) {
-      PackageElement packageElement = elements.getPackageElement(AGGREGATING_PACKAGE);
-
-      if (packageElement == null) {
-        return new AutoValue_DefineComponents_AggregatedMetadata(
-            ImmutableList.of(), ImmutableList.of());
-      }
-
-      ImmutableList.Builder<DefineComponentMetadata> components = ImmutableList.builder();
-      ImmutableList.Builder<DefineComponentBuilderMetadata> builders = ImmutableList.builder();
-      for (Element element : packageElement.getEnclosedElements()) {
-        ProcessorErrors.checkState(
-            MoreElements.isType(element),
-            element,
-            "Only types may be in package %s. Did you add custom code in the package?",
-            packageElement);
-
-        TypeElement typeElement = MoreElements.asType(element);
-        ProcessorErrors.checkState(
-            Processors.hasAnnotation(typeElement, ClassNames.DEFINE_COMPONENT_CLASSES),
-            typeElement,
-            "Class, %s, must be annotated with @%s. Found: %s.",
-            typeElement,
-            ClassNames.DEFINE_COMPONENT_CLASSES.simpleName(),
-            typeElement.getAnnotationMirrors());
-
-        Optional<TypeElement> component = defineComponentClass(elements, typeElement, "component");
-        Optional<TypeElement> builder = defineComponentClass(elements, typeElement, "builder");
-        ProcessorErrors.checkState(
-            component.isPresent() || builder.isPresent(),
-            typeElement,
-            "@DefineComponentClasses missing both `component` and `builder` members.");
-
-        component.map(componentMetadatas::get).ifPresent(components::add);
-        builder.map(componentBuilderMetadatas::get).ifPresent(builders::add);
-      }
-
-      return new AutoValue_DefineComponents_AggregatedMetadata(
-          components.build(), builders.build());
-    }
-
-    private static Optional<TypeElement> defineComponentClass(
-        Elements elements, Element element, String annotationMember) {
-      AnnotationMirror mirror =
-          Processors.getAnnotationMirror(element, ClassNames.DEFINE_COMPONENT_CLASSES);
-      AnnotationValue value = getAnnotationElementAndValue(mirror, annotationMember).getValue();
-      String className = AnnotationValues.getString(value);
-
-      if (className.isEmpty()) { // The default value.
-        return Optional.empty();
-      }
-
-      TypeElement type = elements.getTypeElement(className);
-      ProcessorErrors.checkState(
-          type != null,
-          element,
-          "%s.%s(), has invalid value: `%s`.",
-          ClassNames.DEFINE_COMPONENT_CLASSES.simpleName(),
-          annotationMember,
-          className);
-
-      return Optional.of(type);
-    }
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/disableinstallincheck/BUILD b/java/dagger/hilt/processor/internal/disableinstallincheck/BUILD
deleted file mode 100644
index e3865a6..0000000
--- a/java/dagger/hilt/processor/internal/disableinstallincheck/BUILD
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   A processor for @dagger.hilt.AliasOfProcessor.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.processor.internal.disableinstallincheck.DisableInstallInCheckProcessor",
-    visibility = [
-        "//java/dagger/hilt/migration:__pkg__",
-    ],
-    deps = [":processor_lib"],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "DisableInstallInCheckProcessor.java",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/disableinstallincheck/DisableInstallInCheckProcessor.java b/java/dagger/hilt/processor/internal/disableinstallincheck/DisableInstallInCheckProcessor.java
deleted file mode 100644
index c51f350..0000000
--- a/java/dagger/hilt/processor/internal/disableinstallincheck/DisableInstallInCheckProcessor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.disableinstallincheck;
-
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableSet;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/** Processes the annotations annotated with {@link dagger.hilt.migration.DisableInstallInCheck} */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class DisableInstallInCheckProcessor extends BaseProcessor {
-  @Override
-  public ImmutableSet<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.of(ClassNames.DISABLE_INSTALL_IN_CHECK.toString());
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) {
-    ProcessorErrors.checkState(
-        Processors.hasAnnotation(element, ClassNames.MODULE),
-        element,
-        "@DisableInstallInCheck should only be used on modules. However, it was found annotating"
-            + " %s",
-        element);
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/generatesrootinput/BUILD b/java/dagger/hilt/processor/internal/generatesrootinput/BUILD
deleted file mode 100644
index f24ffb7..0000000
--- a/java/dagger/hilt/processor/internal/generatesrootinput/BUILD
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   A processor for @dagger.hilt.GeneratesRootInput.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.processor.internal.generatesrootinput.GeneratesRootInputProcessor",
-    deps = [":processor_lib"],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "GeneratesRootInputProcessor.java",
-        "GeneratesRootInputPropagatedDataGenerator.java",
-    ],
-    deps = [
-        ":generates_root_inputs",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-java_library(
-    name = "generates_root_inputs",
-    srcs = [
-        "GeneratesRootInputs.java",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputProcessor.java b/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputProcessor.java
deleted file mode 100644
index 6588e09..0000000
--- a/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputProcessor.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.generatesrootinput;
-
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableSet;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import java.util.Set;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/**
- * Processes the annotations annotated with {@link dagger.hilt.GeneratesRootInput} which generate
- * input for components and should be processed before component creation.
- */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class GeneratesRootInputProcessor extends BaseProcessor {
-
-  @Override
-  public Set<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.of(ClassNames.GENERATES_ROOT_INPUT.toString());
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    ProcessorErrors.checkState(
-        element.getKind().equals(ElementKind.ANNOTATION_TYPE),
-        element,
-        "%s should only annotate other annotations. However, it was found annotating %s",
-        annotation,
-        element);
-
-    new GeneratesRootInputPropagatedDataGenerator(this.getProcessingEnv(), element).generate();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputPropagatedDataGenerator.java b/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputPropagatedDataGenerator.java
deleted file mode 100644
index 5c53894..0000000
--- a/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputPropagatedDataGenerator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.generatesrootinput;
-
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-
-/** Generates resource files for {@link GeneratesRootInputs}. */
-final class GeneratesRootInputPropagatedDataGenerator {
-  private final ProcessingEnvironment processingEnv;
-  private final Element element;
-
-  GeneratesRootInputPropagatedDataGenerator(ProcessingEnvironment processingEnv, Element element) {
-    this.processingEnv = processingEnv;
-    this.element = element;
-  }
-
-  void generate() throws IOException {
-    TypeSpec.Builder generator =
-        TypeSpec.classBuilder(Processors.getFullEnclosedName(element))
-            .addOriginatingElement(element)
-            .addAnnotation(
-                AnnotationSpec.builder(ClassNames.GENERATES_ROOT_INPUT_PROPAGATED_DATA)
-                    .addMember("value", "$T.class", element)
-                    .build())
-            .addJavadoc(
-                "Generated class to"
-                    + "get the list of annotations that generate input for root.\n");
-
-    Processors.addGeneratedAnnotation(generator, processingEnv, getClass());
-
-    JavaFile.builder(GeneratesRootInputs.AGGREGATING_PACKAGE, generator.build())
-        .build()
-        .writeTo(processingEnv.getFiler());
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputs.java b/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputs.java
deleted file mode 100644
index 139592e..0000000
--- a/java/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputs.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.generatesrootinput;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Suppliers.memoize;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import java.util.List;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.annotation.processing.RoundEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.Elements;
-
-/** Extracts the list of annotations annotated with {@link dagger.hilt.GeneratesRootInput}. */
-public final class GeneratesRootInputs {
-  static final String AGGREGATING_PACKAGE =
-      GeneratesRootInputs.class.getPackage().getName() + ".codegen";
-
-  private final Elements elements;
-  private final Supplier<ImmutableList<ClassName>> generatesRootInputAnnotations =
-      memoize(() -> getAnnotationList());
-
-  public GeneratesRootInputs(ProcessingEnvironment processingEnvironment) {
-    this.elements = processingEnvironment.getElementUtils();
-  }
-
-  public ImmutableSet<Element> getElementsToWaitFor(RoundEnvironment roundEnv) {
-    // Processing can only take place after all dependent annotations have been processed
-    // Note: We start with ClassName rather than TypeElement because jdk8 does not treat type
-    // elements as equal across rounds. Thus, in order for RoundEnvironment#getElementsAnnotatedWith
-    // to work properly, we get new elements to ensure it works across rounds (See b/148693284).
-    return generatesRootInputAnnotations.get().stream()
-        .map(className -> elements.getTypeElement(className.toString()))
-        .filter(element -> element != null)
-        .flatMap(annotation -> roundEnv.getElementsAnnotatedWith(annotation).stream())
-        .collect(toImmutableSet());
-  }
-
-  private ImmutableList<ClassName> getAnnotationList() {
-    PackageElement packageElement = elements.getPackageElement(AGGREGATING_PACKAGE);
-
-    if (packageElement == null) {
-      return ImmutableList.of();
-    }
-
-    List<? extends Element> annotationElements = packageElement.getEnclosedElements();
-    checkState(!annotationElements.isEmpty(), "No elements Found in package %s.", packageElement);
-
-    ImmutableList.Builder<ClassName> builder = ImmutableList.builder();
-    for (Element element : annotationElements) {
-      ProcessorErrors.checkState(
-          element.getKind() == ElementKind.CLASS,
-          element,
-          "Only classes may be in package %s. Did you add custom code in the package?",
-          packageElement);
-
-      AnnotationMirror annotationMirror =
-          Processors.getAnnotationMirror(element, ClassNames.GENERATES_ROOT_INPUT_PROPAGATED_DATA);
-      ProcessorErrors.checkState(
-          annotationMirror != null,
-          element,
-          "Classes in package %s must be annotated with @%s: %s."
-              + " Found: %s. Files in this package are generated, did you add custom code in the"
-              + " package? ",
-          packageElement,
-          ClassNames.GENERATES_ROOT_INPUT_PROPAGATED_DATA,
-          element.getSimpleName(),
-          element.getAnnotationMirrors());
-
-      TypeElement annotation =
-          Processors.getAnnotationClassValue(elements, annotationMirror, "value");
-
-      builder.add(ClassName.get(annotation));
-    }
-    // This annotation was on Dagger so it couldn't be annotated with @GeneratesRootInput to be
-    // cultivated later. We have to manually add it to the list.
-    builder.add(ClassNames.PRODUCTION_COMPONENT);
-    return builder.build();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/originatingelement/BUILD b/java/dagger/hilt/processor/internal/originatingelement/BUILD
deleted file mode 100644
index 50dbcf6..0000000
--- a/java/dagger/hilt/processor/internal/originatingelement/BUILD
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   A processor for @dagger.hilt.codegen.OriginatingElement.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "processor",
-    generates_api = 1,
-    processor_class = "dagger.hilt.processor.internal.originatingelement.OriginatingElementProcessor",
-    deps = [":processor_lib"],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "OriginatingElementProcessor.java",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/originatingelement/OriginatingElementProcessor.java b/java/dagger/hilt/processor/internal/originatingelement/OriginatingElementProcessor.java
deleted file mode 100644
index 723cf04..0000000
--- a/java/dagger/hilt/processor/internal/originatingelement/OriginatingElementProcessor.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.originatingelement;
-
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableSet;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import javax.annotation.processing.Processor;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/**
- * Processes the annotations annotated with {@link dagger.hilt.codegen.OriginatingElement} to check
- * that they're only used on top-level classes and the value passed is also a top-level class.
- */
-@IncrementalAnnotationProcessor(ISOLATING)
-@AutoService(Processor.class)
-public final class OriginatingElementProcessor extends BaseProcessor {
-
-  @Override
-  public ImmutableSet<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.of(ClassNames.ORIGINATING_ELEMENT.toString());
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    ProcessorErrors.checkState(
-        MoreElements.isType(element) && Processors.isTopLevel(element),
-        element,
-        "@%s should only be used to annotate top-level types, but found: %s",
-        annotation.getSimpleName(),
-        element);
-
-    TypeElement originatingElementValue =
-        Processors.getAnnotationClassValue(
-            getElementUtils(),
-            Processors.getAnnotationMirror(element, ClassNames.ORIGINATING_ELEMENT),
-            "topLevelClass");
-
-    // TODO(bcorso): ProcessorErrors should allow us to point to the annotation too.
-    ProcessorErrors.checkState(
-        Processors.isTopLevel(originatingElementValue),
-        element,
-        "@%s.topLevelClass value should be a top-level class, but found: %s",
-        annotation.getSimpleName(),
-        originatingElementValue);
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/BUILD b/java/dagger/hilt/processor/internal/root/BUILD
deleted file mode 100644
index 709eb7f..0000000
--- a/java/dagger/hilt/processor/internal/root/BUILD
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Annotation processor for Hilt.
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "plugin",
-    generates_api = 1,
-    processor_class = "dagger.hilt.processor.internal.root.RootProcessor",
-    deps = [
-        ":processor_lib",
-    ],
-)
-
-java_library(
-    name = "processor_lib",
-    srcs = [
-        "RootFileFormatter.java",
-        "RootGenerator.java",
-        "RootProcessor.java",
-        "TestComponentDataGenerator.java",
-        "TestComponentDataSupplierGenerator.java",
-        "TestInjectorGenerator.java",
-    ],
-    deps = [
-        ":root_metadata",
-        ":root_type",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:component_descriptor",
-        "//java/dagger/hilt/processor/internal:component_names",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:component_dependencies",
-        "//java/dagger/hilt/processor/internal/definecomponent:define_components",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:generates_root_inputs",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:graph",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_library(
-    name = "root_metadata",
-    srcs = [
-        "Root.java",
-        "RootMetadata.java",
-        "TestRootMetadata.java",
-    ],
-    deps = [
-        ":root_type",
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:component_descriptor",
-        "//java/dagger/hilt/processor/internal:kotlin",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:component_dependencies",
-        "//java/dagger/hilt/processor/internal/aliasof:alias_ofs",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-java_library(
-    name = "root_type",
-    srcs = ["RootType.java"],
-    deps = [
-        "//java/dagger/hilt/processor/internal:classnames",
-        "//java/dagger/hilt/processor/internal:processor_errors",
-        "//java/dagger/hilt/processor/internal:processors",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/processor/internal/root/Root.java b/java/dagger/hilt/processor/internal/root/Root.java
deleted file mode 100644
index 981636d..0000000
--- a/java/dagger/hilt/processor/internal/root/Root.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.root;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.value.AutoValue;
-import com.squareup.javapoet.ClassName;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-/** Metadata for a root element that can trigger the {@link RootProcessor}. */
-@AutoValue
-abstract class Root {
-  /** Creates a {@plainlink Root root} for the given {@plainlink Element element}. */
-  static Root create(Element element, ProcessingEnvironment env) {
-    TypeElement rootElement = MoreElements.asType(element);
-    return new AutoValue_Root(RootType.of(env, rootElement), rootElement);
-  }
-
-  /** Returns the type of the root {@code element}. */
-  abstract RootType type();
-
-  /** Returns the root element that should be used with processing. */
-  abstract TypeElement element();
-
-  /** Returns the class name of the root element. */
-  ClassName classname() {
-    return ClassName.get(element());
-  }
-
-  @Override
-  public final String toString() {
-    return element().toString();
-  }
-
-  boolean isTestRoot() {
-    return type().isTestRoot();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/RootFileFormatter.java b/java/dagger/hilt/processor/internal/root/RootFileFormatter.java
deleted file mode 100644
index 45cdd22..0000000
--- a/java/dagger/hilt/processor/internal/root/RootFileFormatter.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.root;
-
-import com.squareup.javapoet.JavaFile;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.regex.MatchResult;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.annotation.processing.Filer;
-import javax.lang.model.element.Element;
-import javax.tools.JavaFileObject;
-
-/**
- * Typically we would just use {@code JavaFile#writeTo()} to write files. However, this formatter
- * exists to add new lines inbetween interfaces. This can be important for classes with many
- * interfaces (e.g. Dagger components) to avoid spamming the entire list of interfaces when
- * reporting errors to the user.
- *
- * <p>See b/33108646.
- */
-final class RootFileFormatter {
-  private static final Pattern CLASS_PATERN = Pattern.compile("(\\h*)(.*class.*implements)(.*\\{)");
-
-  /** Formats the {@link JavaFile} java source file. */
-  static void write(JavaFile javaFile, Filer filer) throws IOException {
-    String fileName =
-        javaFile.packageName.isEmpty()
-            ? javaFile.typeSpec.name
-            : javaFile.packageName + "." + javaFile.typeSpec.name;
-
-    Element[] originatingElements = javaFile.typeSpec.originatingElements.toArray(new Element[0]);
-
-    StringBuilder sb = new StringBuilder("");
-    javaFile.writeTo(sb);
-    String fileContent = formatInterfaces(sb.toString(), CLASS_PATERN);
-
-    JavaFileObject filerSourceFile = filer.createSourceFile(fileName, originatingElements);
-    try (Writer writer = filerSourceFile.openWriter()) {
-      writer.write(fileContent);
-    } catch (Exception e) {
-      try {
-        filerSourceFile.delete();
-      } catch (Exception ignored) {
-        // Nothing to do.
-      }
-      throw e;
-    }
-  }
-
-  private static String formatInterfaces(String content, Pattern pattern) {
-    Matcher matcher = pattern.matcher(content);
-    StringBuffer sb = new StringBuffer(content.length());
-    while (matcher.find()) {
-      MatchResult result = matcher.toMatchResult();
-      String spaces = result.group(1);
-      String prefix = result.group(2);
-      String interfaces = result.group(3);
-      String formattedInterfaces = formatInterfaces(spaces, interfaces);
-      matcher.appendReplacement(
-          sb, Matcher.quoteReplacement(spaces + prefix + formattedInterfaces));
-    }
-    matcher.appendTail(sb);
-    return sb.toString();
-  }
-
-  private static String formatInterfaces(String prefixSpaces, String interfaces) {
-    StringBuilder sb = new StringBuilder(interfaces);
-    String newLine = String.format("\n%s   ", prefixSpaces);
-
-    // Add a line break after each interface so that there's only 1 interface per line.
-    int i = 0;
-    int bracketCount = 0;
-    while (i >= 0 && i < sb.length()) {
-      char c = sb.charAt(i++);
-      if (c == '<') {
-        bracketCount++;
-      } else if (c == '>') {
-        bracketCount--;
-      } else if (c == ',' && bracketCount == 0) {
-        sb.insert(i++, newLine);
-      }
-    }
-    return sb.toString();
-  }
-
-  private RootFileFormatter() {}
-}
diff --git a/java/dagger/hilt/processor/internal/root/RootGenerator.java b/java/dagger/hilt/processor/internal/root/RootGenerator.java
deleted file mode 100644
index c2c55e6..0000000
--- a/java/dagger/hilt/processor/internal/root/RootGenerator.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.root;
-
-import static dagger.hilt.processor.internal.Processors.toClassNames;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.graph.GraphBuilder;
-import com.google.common.graph.Graphs;
-import com.google.common.graph.MutableGraph;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ComponentDescriptor;
-import dagger.hilt.processor.internal.ComponentGenerator;
-import dagger.hilt.processor.internal.ComponentNames;
-import dagger.hilt.processor.internal.ComponentTree;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import java.util.Optional;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-
-/** Generates components and any other classes needed for a root. */
-final class RootGenerator {
-
-  static void generate(RootMetadata metadata, ProcessingEnvironment env) throws IOException {
-    new RootGenerator(
-        RootMetadata.copyWithNewTree(
-            metadata,
-            filterDescriptors(metadata.componentTree())),
-        env).generateComponents();
-  }
-
-  private final RootMetadata metadata;
-  private final ProcessingEnvironment env;
-  private final Root root;
-
-  private RootGenerator(RootMetadata metadata, ProcessingEnvironment env) {
-    this.metadata = metadata;
-    this.env = env;
-    this.root = metadata.root();
-  }
-
-  private void generateComponents() throws IOException {
-
-    // TODO(bcorso): Consider moving all of this logic into ComponentGenerator?
-    TypeSpec.Builder componentsWrapper =
-        TypeSpec.classBuilder(getComponentsWrapperClassName())
-            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-            .addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build());
-
-    Processors.addGeneratedAnnotation(componentsWrapper, env, ClassNames.ROOT_PROCESSOR.toString());
-
-    ImmutableMap<ComponentDescriptor, ClassName> subcomponentBuilderModules =
-        subcomponentBuilderModules(componentsWrapper);
-
-    ComponentTree componentTree = metadata.componentTree();
-    for (ComponentDescriptor componentDescriptor : componentTree.getComponentDescriptors()) {
-      ImmutableSet<ClassName> modules =
-          ImmutableSet.<ClassName>builder()
-              .addAll(toClassNames(metadata.modules(componentDescriptor.component())))
-              .addAll(
-                  componentTree.childrenOf(componentDescriptor).stream()
-                      .map(subcomponentBuilderModules::get)
-                      .collect(toImmutableSet()))
-              .build();
-
-      componentsWrapper.addType(
-          new ComponentGenerator(
-                  env,
-                  getComponentClassName(componentDescriptor),
-                  root.element(),
-                  Optional.empty(),
-                  modules,
-                  metadata.entryPoints(componentDescriptor.component()),
-                  metadata.scopes(componentDescriptor.component()),
-                  ImmutableList.of(),
-                  componentAnnotation(componentDescriptor),
-                  componentBuilder(componentDescriptor))
-              .generate().toBuilder().addModifiers(Modifier.STATIC).build());
-    }
-
-    RootFileFormatter.write(
-        JavaFile.builder(root.classname().packageName(), componentsWrapper.build()).build(),
-        env.getFiler());
-  }
-
-  private static ComponentTree filterDescriptors(ComponentTree componentTree) {
-    MutableGraph<ComponentDescriptor> graph =
-        GraphBuilder.from(componentTree.graph()).build();
-
-    componentTree.graph().nodes().forEach(graph::addNode);
-    componentTree.graph().edges().forEach(graph::putEdge);
-
-    // Remove components that do not have builders (besides the root component) since if
-    // we didn't find any builder class, then we don't need to generate the component
-    // since it would be inaccessible.
-    componentTree.getComponentDescriptors().stream()
-        .filter(descriptor -> !descriptor.isRoot() && !descriptor.creator().isPresent())
-        .forEach(graph::removeNode);
-
-    // The graph may still have nodes that are children of components that don't have builders,
-    // so we need to find reachable nodes from the root and create a new graph to remove those.
-    // We reuse the root from the original tree since it should not have been removed.
-    return ComponentTree.from(Graphs.reachableNodes(graph, componentTree.root()));
-  }
-
-  private ImmutableMap<ComponentDescriptor, ClassName> subcomponentBuilderModules(
-      TypeSpec.Builder componentsWrapper) throws IOException {
-    ImmutableMap.Builder<ComponentDescriptor, ClassName> modules = ImmutableMap.builder();
-    for (ComponentDescriptor descriptor : metadata.componentTree().getComponentDescriptors()) {
-      // Root component builders don't have subcomponent builder modules
-      if (!descriptor.isRoot() && descriptor.creator().isPresent()) {
-        ClassName component = getComponentClassName(descriptor);
-        ClassName builder = descriptor.creator().get();
-        ClassName module = component.peerClass(component.simpleName() + "BuilderModule");
-        componentsWrapper.addType(subcomponentBuilderModule(component, builder, module));
-        modules.put(descriptor, module);
-      }
-    }
-    return modules.build();
-  }
-
-  // Generates:
-  // @Module(subcomponents = FooSubcomponent.class)
-  // interface FooSubcomponentBuilderModule {
-  //   @Binds FooSubcomponentInterfaceBuilder bind(FooSubcomponent.Builder builder);
-  // }
-  private TypeSpec subcomponentBuilderModule(
-      ClassName componentName, ClassName builderName, ClassName moduleName) throws IOException {
-    TypeSpec.Builder subcomponentBuilderModule =
-        TypeSpec.interfaceBuilder(moduleName)
-            .addOriginatingElement(root.element())
-            .addModifiers(ABSTRACT)
-            .addAnnotation(
-                AnnotationSpec.builder(ClassNames.MODULE)
-                    .addMember("subcomponents", "$T.class", componentName)
-                    .build())
-            .addAnnotation(ClassNames.DISABLE_INSTALL_IN_CHECK)
-            .addMethod(
-                MethodSpec.methodBuilder("bind")
-                    .addModifiers(ABSTRACT, PUBLIC)
-                    .addAnnotation(ClassNames.BINDS)
-                    .returns(builderName)
-                    .addParameter(componentName.nestedClass("Builder"), "builder")
-                    .build());
-
-    Processors.addGeneratedAnnotation(
-        subcomponentBuilderModule, env, ClassNames.ROOT_PROCESSOR.toString());
-
-    return subcomponentBuilderModule.build();
-  }
-
-  private Optional<TypeSpec> componentBuilder(ComponentDescriptor descriptor) {
-    return descriptor
-        .creator()
-        .map(
-            creator ->
-                TypeSpec.interfaceBuilder("Builder")
-                    .addOriginatingElement(root.element())
-                    .addModifiers(STATIC, ABSTRACT)
-                    .addSuperinterface(creator)
-                    .addAnnotation(componentBuilderAnnotation(descriptor))
-                    .build());
-  }
-
-  private ClassName componentAnnotation(ComponentDescriptor componentDescriptor) {
-    if (!componentDescriptor.isRoot()
-        ) {
-      return ClassNames.SUBCOMPONENT;
-    } else {
-      return ClassNames.COMPONENT;
-    }
-  }
-
-  private ClassName componentBuilderAnnotation(ComponentDescriptor componentDescriptor) {
-    if (componentDescriptor.isRoot()) {
-      return ClassNames.COMPONENT_BUILDER;
-    } else {
-      return ClassNames.SUBCOMPONENT_BUILDER;
-    }
-  }
-
-  private ClassName getPartialRootModuleClassName() {
-    return getComponentsWrapperClassName().nestedClass("PartialRootModule");
-  }
-
-  private ClassName getComponentsWrapperClassName() {
-    return ComponentNames.generatedComponentsWrapper(root.classname());
-  }
-
-  private ClassName getComponentClassName(ComponentDescriptor componentDescriptor) {
-    return ComponentNames.generatedComponent(root.classname(), componentDescriptor.component());
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/RootMetadata.java b/java/dagger/hilt/processor/internal/root/RootMetadata.java
deleted file mode 100644
index 4c43f1d..0000000
--- a/java/dagger/hilt/processor/internal/root/RootMetadata.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.root;
-
-import static com.google.common.base.Suppliers.memoize;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.TypeName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ComponentDescriptor;
-import dagger.hilt.processor.internal.ComponentTree;
-import dagger.hilt.processor.internal.KotlinMetadataUtils;
-import dagger.hilt.processor.internal.Processors;
-import dagger.hilt.processor.internal.aggregateddeps.ComponentDependencies;
-import dagger.hilt.processor.internal.aliasof.AliasOfs;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import java.util.List;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.Elements;
-import javax.tools.Diagnostic;
-
-/** Contains metadata about the given hilt root. */
-public final class RootMetadata {
-  private static final ClassName APPLICATION_CONTEXT_MODULE =
-      ClassName.get("dagger.hilt.android.internal.modules", "ApplicationContextModule");
-
-  static RootMetadata create(
-      Root root,
-      ComponentTree componentTree,
-      ComponentDependencies deps,
-      ProcessingEnvironment env) {
-    RootMetadata metadata = new RootMetadata(root, componentTree, deps, env);
-    metadata.validate();
-    return metadata;
-  }
-
-  static RootMetadata copyWithNewTree(
-      RootMetadata other,
-      ComponentTree componentTree) {
-    return create(other.root, componentTree, other.deps, other.env);
-  }
-
-  private final Root root;
-  private final ProcessingEnvironment env;
-  private final Elements elements;
-  private final ComponentTree componentTree;
-  private final ComponentDependencies deps;
-  private final Supplier<ImmutableSetMultimap<ClassName, ClassName>> scopesByComponent =
-      memoize(this::getScopesByComponentUncached);
-  private final Supplier<TestRootMetadata> testRootMetadata =
-      memoize(this::testRootMetadataUncached);
-
-  private RootMetadata(
-      Root root,
-      ComponentTree componentTree,
-      ComponentDependencies deps,
-      ProcessingEnvironment env) {
-    this.root = root;
-    this.env = env;
-    this.elements = env.getElementUtils();
-    this.componentTree = componentTree;
-    this.deps = deps;
-  }
-
-  public Root root() {
-    return root;
-  }
-
-  public ComponentTree componentTree() {
-    return componentTree;
-  }
-
-  public ComponentDependencies deps() {
-    return deps;
-  }
-
-  public ImmutableSet<TypeElement> modules(ClassName componentName) {
-    return deps.modules().get(componentName, root.classname(), root.isTestRoot());
-  }
-
-  public ImmutableSet<TypeName> entryPoints(ClassName componentName) {
-    return ImmutableSet.<TypeName>builder()
-        .addAll(getUserDefinedEntryPoints(componentName))
-        .add(componentName)
-        .build();
-  }
-
-  public ImmutableSet<ClassName> scopes(ClassName componentName) {
-    return scopesByComponent.get().get(componentName);
-  }
-
-  /**
-   * Returns all modules in the given component that do not have accessible default constructors.
-   * Note that a non-static module nested in an outer class is considered to have no default
-   * constructors, since an instance of the outer class is needed to construct the module. This also
-   * filters out framework modules directly referenced by the codegen, since those are already known
-   * about and are specifically handled in the codegen.
-   */
-  public ImmutableSet<TypeElement> modulesThatDaggerCannotConstruct(ClassName componentName) {
-    return modules(componentName).stream()
-        .filter(module -> !daggerCanConstruct(module))
-        .filter(module -> !APPLICATION_CONTEXT_MODULE.equals(ClassName.get(module)))
-        .collect(toImmutableSet());
-  }
-
-  public TestRootMetadata testRootMetadata() {
-    return testRootMetadata.get();
-  }
-
-  public boolean waitForBindValue() {
-    return false;
-  }
-
-  private TestRootMetadata testRootMetadataUncached() {
-    return TestRootMetadata.of(env, root().element());
-  }
-
-  /**
-   * Validates that the {@link RootType} annotation is compatible with its {@link TypeElement} and
-   * {@link ComponentDependencies}.
-   */
-  private void validate() {
-
-    // Only test modules in the application component can be missing default constructor
-    for (ComponentDescriptor componentDescriptor : componentTree.getComponentDescriptors()) {
-      ClassName componentName = componentDescriptor.component();
-      for (TypeElement extraModule : modulesThatDaggerCannotConstruct(componentName)) {
-        if (root.type().isTestRoot() && !componentName.equals(ClassNames.SINGLETON_COMPONENT)) {
-          env.getMessager()
-              .printMessage(
-                  Diagnostic.Kind.ERROR,
-                  "[Hilt] All test modules (unless installed in ApplicationComponent) must use "
-                      + "static provision methods or have a visible, no-arg constructor. Found: "
-                      + extraModule.getQualifiedName(),
-                  root.element());
-        } else if (!root.type().isTestRoot()) {
-          env.getMessager()
-              .printMessage(
-                  Diagnostic.Kind.ERROR,
-                  "[Hilt] All modules must be static and use static provision methods or have a "
-                      + "visible, no-arg constructor. Found: "
-                      + extraModule.getQualifiedName(),
-                  root.element());
-        }
-      }
-    }
-  }
-
-  private ImmutableSet<TypeName> getUserDefinedEntryPoints(ClassName componentName) {
-    ImmutableSet.Builder<TypeName> entryPointSet = ImmutableSet.builder();
-    entryPointSet.add(ClassNames.GENERATED_COMPONENT);
-    for (TypeElement element :
-        deps.entryPoints().get(componentName, root.classname(), root.isTestRoot())) {
-      entryPointSet.add(ClassName.get(element));
-    }
-    return entryPointSet.build();
-  }
-
-  private ImmutableSetMultimap<ClassName, ClassName> getScopesByComponentUncached() {
-    ImmutableSetMultimap.Builder<ClassName, ClassName> builder = ImmutableSetMultimap.builder();
-
-    ImmutableSet<ClassName> defineComponentScopes =
-        componentTree.getComponentDescriptors().stream()
-            .flatMap(descriptor -> descriptor.scopes().stream())
-            .collect(toImmutableSet());
-
-    AliasOfs aliasOfs = new AliasOfs(env, defineComponentScopes);
-
-    for (ComponentDescriptor componentDescriptor : componentTree.getComponentDescriptors()) {
-      for (ClassName scope : componentDescriptor.scopes()) {
-        builder.put(componentDescriptor.component(), scope);
-        builder.putAll(componentDescriptor.component(), aliasOfs.getAliasesFor(scope));
-      }
-    }
-
-    return builder.build();
-  }
-
-  private static boolean daggerCanConstruct(TypeElement type) {
-    KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
-    boolean isKotlinObject =
-        metadataUtil.isObjectClass(type) || metadataUtil.isCompanionObjectClass(type);
-    if (isKotlinObject) {
-      // Treat Kotlin object modules as if Dagger can construct them (it technically can't, but it
-      // doesn't need to as it can use them since all their provision methods are static).
-      return true;
-    }
-
-    return !isInnerClass(type)
-        && !hasNonDaggerAbstractMethod(type)
-        && (hasOnlyStaticProvides(type) || hasVisibleEmptyConstructor(type));
-  }
-
-  private static boolean isInnerClass(TypeElement type) {
-    return type.getNestingKind().isNested() && !type.getModifiers().contains(STATIC);
-  }
-
-  private static boolean hasNonDaggerAbstractMethod(TypeElement type) {
-    // TODO(erichang): Actually this isn't really supported b/28989613
-    return ElementFilter.methodsIn(type.getEnclosedElements()).stream()
-        .filter(method -> method.getModifiers().contains(ABSTRACT))
-        .anyMatch(method -> !Processors.hasDaggerAbstractMethodAnnotation(method));
-  }
-
-  private static boolean hasOnlyStaticProvides(TypeElement type) {
-    // TODO(erichang): Check for @Produces too when we have a producers story
-    return ElementFilter.methodsIn(type.getEnclosedElements()).stream()
-        .filter(method -> Processors.hasAnnotation(method, ClassNames.PROVIDES))
-        .allMatch(method -> method.getModifiers().contains(STATIC));
-  }
-
-  private static boolean hasVisibleEmptyConstructor(TypeElement type) {
-    List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());
-    return constructors.isEmpty()
-        || constructors.stream()
-            .filter(constructor -> constructor.getParameters().isEmpty())
-            .anyMatch(constructor -> !constructor.getModifiers().contains(PRIVATE));
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/RootProcessor.java b/java/dagger/hilt/processor/internal/root/RootProcessor.java
deleted file mode 100644
index 8f8c948..0000000
--- a/java/dagger/hilt/processor/internal/root/RootProcessor.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.root;
-
-import static com.google.common.base.Preconditions.checkState;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.AGGREGATING;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.service.AutoService;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.BaseProcessor;
-import dagger.hilt.processor.internal.ComponentTree;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.aggregateddeps.ComponentDependencies;
-import dagger.hilt.processor.internal.definecomponent.DefineComponents;
-import dagger.hilt.processor.internal.generatesrootinput.GeneratesRootInputs;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.annotation.processing.Processor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
-
-/** Processor that outputs dagger components based on transitive build deps. */
-@IncrementalAnnotationProcessor(AGGREGATING)
-@AutoService(Processor.class)
-public final class RootProcessor extends BaseProcessor {
-  private final List<ClassName> rootNames = new ArrayList<>();
-  private final Set<ClassName> processed = new HashSet<>();
-  private boolean isTestEnv;
-  // TODO(bcorso): Consider using a Dagger component to create/scope these objects
-  private final DefineComponents defineComponents = DefineComponents.create();
-  private GeneratesRootInputs generatesRootInputs;
-
-  @Override
-  public synchronized void init(ProcessingEnvironment processingEnvironment) {
-    super.init(processingEnvironment);
-    generatesRootInputs = new GeneratesRootInputs(processingEnvironment);
-  }
-
-  @Override
-  public ImmutableSet<String> getSupportedAnnotationTypes() {
-    return ImmutableSet.<String>builder()
-        .addAll(
-            Arrays.stream(RootType.values())
-                .map(rootType -> rootType.className().toString())
-                .collect(toImmutableSet()))
-        .build();
-  }
-
-  @Override
-  public void processEach(TypeElement annotation, Element element) throws Exception {
-    TypeElement rootElement = MoreElements.asType(element);
-    boolean isTestRoot = RootType.of(getProcessingEnv(), rootElement).isTestRoot();
-    checkState(
-        rootNames.isEmpty() || isTestEnv == isTestRoot,
-        "Cannot mix test roots with non-test roots:"
-            + "\n\tNon-Test Roots: %s"
-            + "\n\tTest Roots: %s",
-        isTestRoot ? rootNames : rootElement,
-        isTestRoot ? rootElement : rootNames);
-    isTestEnv = isTestRoot;
-
-    rootNames.add(ClassName.get(rootElement));
-    if (isTestEnv) {
-      new TestInjectorGenerator(
-          getProcessingEnv(),
-          TestRootMetadata.of(getProcessingEnv(), rootElement)).generate();
-    } else {
-      ProcessorErrors.checkState(
-          rootNames.size() <= 1, element, "More than one root found: %s", rootNames);
-    }
-  }
-
-  @Override
-  public void postRoundProcess(RoundEnvironment roundEnv) throws Exception {
-    Set<Element> newElements = generatesRootInputs.getElementsToWaitFor(roundEnv);
-    if (!processed.isEmpty() ) {
-      checkState(
-          newElements.isEmpty(),
-          "Found extra modules after compilation: %s\n"
-              + "(If you are adding an annotation processor that generates root input for hilt, "
-              + "the annotation must be annotated with @dagger.hilt.GeneratesRootInput.\n)",
-          newElements);
-    }
-
-    if (!newElements.isEmpty()) {
-      // Skip further processing since there's new elements that generate root inputs in this round.
-      return;
-    }
-
-    ImmutableList<Root> rootsToProcess =
-        rootNames.stream()
-            .filter(rootName -> !processed.contains(rootName))
-            // We create a new root element each round to avoid the jdk8 bug where
-            // TypeElement.equals does not work for elements across processing rounds.
-            .map(rootName -> getElementUtils().getTypeElement(rootName.toString()))
-            .map(rootElement -> Root.create(rootElement, getProcessingEnv()))
-            .collect(toImmutableList());
-
-    if (rootsToProcess.isEmpty()) {
-      // Skip further processing since there's no roots that need processing.
-      return;
-    }
-
-    // TODO(bcorso): Currently, if there's an exception in any of the roots we stop processing
-    // all roots. We should consider if it's worth trying to continue processing for other
-    // roots. At the moment, I think it's rare that if one root failed the others would not.
-    try {
-      ComponentTree tree = defineComponents.getComponentTree(getElementUtils());
-      ComponentDependencies deps = ComponentDependencies.from(
-          tree.getComponentDescriptors(), getElementUtils());
-      ImmutableList<RootMetadata> rootMetadatas =
-          rootsToProcess.stream()
-              .map(root -> RootMetadata.create(root, tree, deps, getProcessingEnv()))
-              .collect(toImmutableList());
-
-      for (RootMetadata rootMetadata : rootMetadatas) {
-        setProcessingState(rootMetadata.root());
-        generateComponents(rootMetadata);
-      }
-
-      if (isTestEnv) {
-        generateTestComponentData(rootMetadatas);
-      }
-    } catch (Exception e) {
-      for (Root root : rootsToProcess) {
-        processed.add(root.classname());
-      }
-      throw e;
-    }
-  }
-
-  private void setProcessingState(Root root) {
-    processed.add(root.classname());
-  }
-
-  private void generateComponents(RootMetadata rootMetadata) throws IOException {
-    RootGenerator.generate(rootMetadata, getProcessingEnv());
-  }
-
-  private void generateTestComponentData(ImmutableList<RootMetadata> rootMetadatas)
-      throws IOException {
-    for (RootMetadata rootMetadata : rootMetadatas) {
-      // TODO(bcorso): Consider moving this check earlier into processEach.
-      TypeElement testElement = rootMetadata.testRootMetadata().testElement();
-      ProcessorErrors.checkState(
-          testElement.getModifiers().contains(PUBLIC),
-          testElement,
-          "Hilt tests must be public, but found: %s",
-          testElement);
-      new TestComponentDataGenerator(getProcessingEnv(), rootMetadata).generate();
-    }
-    new TestComponentDataSupplierGenerator(getProcessingEnv(), rootMetadatas).generate();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/RootType.java b/java/dagger/hilt/processor/internal/root/RootType.java
deleted file mode 100644
index 3545231..0000000
--- a/java/dagger/hilt/processor/internal/root/RootType.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.root;
-
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.TypeElement;
-
-/** The valid root types for Hilt applications. */
-// TODO(erichang): Fix this class so we don't have to have placeholders
-  enum RootType {
-    ROOT(ClassNames.HILT_ANDROID_APP),
-
-    // Placeholder to make sure @HiltAndroidTest usages get processed
-    HILT_ANDROID_TEST_ROOT(ClassNames.HILT_ANDROID_TEST),
-
-    TEST_ROOT(ClassNames.INTERNAL_TEST_ROOT);
-
-  @SuppressWarnings("ImmutableEnumChecker")
-  private final ClassName annotation;
-
-  RootType(ClassName annotation) {
-    this.annotation = annotation;
-  }
-
-  public boolean isTestRoot() {
-    return this == TEST_ROOT;
-  }
-
-  public ClassName className() {
-    return annotation;
-  }
-
-  public static RootType of(ProcessingEnvironment env, TypeElement element) {
-    if (Processors.hasAnnotation(element, ClassNames.HILT_ANDROID_APP)) {
-      return ROOT;
-    } else if (Processors.hasAnnotation(element, ClassNames.HILT_ANDROID_TEST)) {
-      return TEST_ROOT;
-    } else if (Processors.hasAnnotation(element, ClassNames.INTERNAL_TEST_ROOT)) {
-      return TEST_ROOT;
-    }
-    throw new IllegalStateException("Unknown root type: " + element);
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/TestComponentDataGenerator.java b/java/dagger/hilt/processor/internal/root/TestComponentDataGenerator.java
deleted file mode 100644
index 284f8cd..0000000
--- a/java/dagger/hilt/processor/internal/root/TestComponentDataGenerator.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.root;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static java.util.stream.Collectors.joining;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.util.ElementFilter.constructorsIn;
-
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ComponentNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import java.util.List;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-
-/** Generates an implementation of {@link dagger.hilt.android.internal.TestComponentData}. */
-public final class TestComponentDataGenerator {
-  private final ProcessingEnvironment processingEnv;
-  private final RootMetadata rootMetadata;
-  private final ClassName name;
-
-  public TestComponentDataGenerator(
-      ProcessingEnvironment processingEnv,
-      RootMetadata rootMetadata) {
-    this.processingEnv = processingEnv;
-    this.rootMetadata = rootMetadata;
-    this.name =
-        Processors.append(
-            Processors.getEnclosedClassName(rootMetadata.testRootMetadata().testName()),
-            "_ComponentDataHolder");
-  }
-
-  /**
-   *
-   *
-   * <pre><code>{@code
-   * public final class FooTest_ComponentDataHolder {
-   *   public static TestComponentData get() {
-   *     return new TestComponentData(
-   *         false, // waitForBindValue
-   *         testInstance -> injectInternal(($1T) testInstance),
-   *         Arrays.asList(FooTest.TestModule.class, ...),
-   *         modules ->
-   *             DaggerFooTest_ApplicationComponent.builder()
-   *                 .applicationContextModule(
-   *                     new ApplicationContextModule(ApplicationProvider.getApplicationContext()))
-   *                 .testModule((FooTest.TestModule) modules.get(FooTest.TestModule.class))
-   *                 .testModule(modules.containsKey(FooTest.TestModule.class)
-   *                   ? (FooTest.TestModule) modules.get(FooTest.TestModule.class)
-   *                   : ((TestInstace) testInstance).new TestModule())
-   *                 .build());
-   *   }
-   * }
-   * }</code></pre>
-   */
-  public void generate() throws IOException {
-    TypeSpec.Builder generator =
-        TypeSpec.classBuilder(name)
-            .addModifiers(PUBLIC, FINAL)
-            .addMethod(MethodSpec.constructorBuilder().addModifiers(PRIVATE).build())
-            .addMethod(getMethod())
-            .addMethod(getTestInjectInternalMethod());
-
-    Processors.addGeneratedAnnotation(
-        generator, processingEnv, ClassNames.ROOT_PROCESSOR.toString());
-
-    JavaFile.builder(rootMetadata.testRootMetadata().testName().packageName(), generator.build())
-        .build()
-        .writeTo(processingEnv.getFiler());
-  }
-
-  private MethodSpec getMethod() {
-    TypeElement testElement = rootMetadata.testRootMetadata().testElement();
-    ClassName component =
-        ComponentNames.generatedComponent(
-            ClassName.get(testElement), ClassNames.SINGLETON_COMPONENT);
-    ImmutableSet<TypeElement> daggerRequiredModules =
-        rootMetadata.modulesThatDaggerCannotConstruct(ClassNames.SINGLETON_COMPONENT);
-    ImmutableSet<TypeElement> hiltRequiredModules =
-        daggerRequiredModules.stream()
-            .filter(module -> !canBeConstructedByHilt(module, testElement))
-            .collect(toImmutableSet());
-
-    return MethodSpec.methodBuilder("get")
-        .addModifiers(PUBLIC, STATIC)
-        .returns(ClassNames.TEST_COMPONENT_DATA)
-        .addStatement(
-            "return new $T($L, $L, $L, $L, $L)",
-            ClassNames.TEST_COMPONENT_DATA,
-            rootMetadata.waitForBindValue(),
-            CodeBlock.of("testInstance -> injectInternal(($1T) testInstance)", testElement),
-            getElementsListed(daggerRequiredModules),
-            getElementsListed(hiltRequiredModules),
-            CodeBlock.of(
-                "(modules, testInstance, autoAddModuleEnabled) -> $T.builder()\n"
-                    + ".applicationContextModule(new $T($T.getApplicationContext()))\n"
-                    + "$L"
-                    + ".build()",
-                Processors.prepend(Processors.getEnclosedClassName(component), "Dagger"),
-                ClassNames.APPLICATION_CONTEXT_MODULE,
-                ClassNames.APPLICATION_PROVIDER,
-                daggerRequiredModules.stream()
-                    .map(module -> getAddModuleStatement(module, testElement))
-                    .collect(joining("\n"))))
-        .build();
-  }
-
-  /**
-   *
-   *
-   * <pre><code>
-   * .testModule(modules.get(FooTest.TestModule.class))
-   * </code></pre>
-   *
-   * <pre><code>
-   * .testModule(autoAddModuleEnabled
-   *     ? ((FooTest) testInstance).new TestModule()
-   *     : (FooTest.TestModule) modules.get(FooTest.TestModule.class))
-   * </code></pre>
-   */
-  private static String getAddModuleStatement(TypeElement module, TypeElement testElement) {
-    ClassName className = ClassName.get(module);
-    return canBeConstructedByHilt(module, testElement)
-        ? CodeBlock.of(
-                ".$1L(autoAddModuleEnabled\n"
-                    // testInstance can never be null if we reach here, because this flag can be
-                    // turned on only when testInstance is not null
-                    + "    ? (($3T) testInstance).new $4L()\n"
-                    + "    : ($2T) modules.get($2T.class))",
-                Processors.upperToLowerCamel(className.simpleName()),
-                className,
-                className.enclosingClassName(),
-                className.simpleName())
-            .toString()
-        : CodeBlock.of(
-                ".$1L(($2T) modules.get($2T.class))",
-                Processors.upperToLowerCamel(className.simpleName()),
-                className)
-            .toString();
-  }
-
-  private static boolean canBeConstructedByHilt(TypeElement module, TypeElement testElement) {
-    return hasOnlyAccessibleNoArgConstructor(module)
-        && module.getEnclosingElement().equals(testElement);
-  }
-
-  private static boolean hasOnlyAccessibleNoArgConstructor(TypeElement module) {
-    List<ExecutableElement> declaredConstructors = constructorsIn(module.getEnclosedElements());
-    return declaredConstructors.isEmpty()
-        || (declaredConstructors.size() == 1
-            && !declaredConstructors.get(0).getModifiers().contains(PRIVATE)
-            && declaredConstructors.get(0).getParameters().isEmpty());
-  }
-
-  /* Arrays.asList(FooTest.TestModule.class, ...) */
-  private static CodeBlock getElementsListed(ImmutableSet<TypeElement> modules) {
-    return modules.isEmpty()
-        ? CodeBlock.of("$T.emptySet()", ClassNames.COLLECTIONS)
-        : CodeBlock.of(
-            "new $T<>($T.asList($L))",
-            ClassNames.HASH_SET,
-            ClassNames.ARRAYS,
-            modules.stream()
-                .map(module -> CodeBlock.of("$T.class", module).toString())
-                .collect(joining(",")));
-  }
-
-  private MethodSpec getTestInjectInternalMethod() {
-    TypeElement testElement = rootMetadata.testRootMetadata().testElement();
-    ClassName testName = ClassName.get(testElement);
-    return MethodSpec.methodBuilder("injectInternal")
-        .addModifiers(PRIVATE, STATIC)
-        .addParameter(testName, "testInstance")
-        .addAnnotation(
-            AnnotationSpec.builder(SuppressWarnings.class)
-                .addMember("value", "$S", "unchecked")
-                .build())
-        .addStatement("$L.injectTest(testInstance)", getInjector(testElement))
-        .build();
-  }
-
-  private static CodeBlock getInjector(TypeElement testElement) {
-    return CodeBlock.of(
-        "(($T) (($T) $T.getApplicationContext()).generatedComponent())",
-        ClassNames.TEST_INJECTOR,
-        ClassNames.GENERATED_COMPONENT_MANAGER,
-        ClassNames.APPLICATION_PROVIDER);
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/TestComponentDataSupplierGenerator.java b/java/dagger/hilt/processor/internal/root/TestComponentDataSupplierGenerator.java
deleted file mode 100644
index e5a83b6..0000000
--- a/java/dagger/hilt/processor/internal/root/TestComponentDataSupplierGenerator.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.root;
-
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PROTECTED;
-import static javax.lang.model.element.Modifier.PUBLIC;
-
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.WildcardTypeName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-
-/** Generates an implementation of {@link dagger.hilt.android.internal.TestComponentDataSupplier} */
-public final class TestComponentDataSupplierGenerator {
-  private static final ClassName TEST_COMPONENT_DATA_SUPPLIER_IMPL =
-      ClassName.get("dagger.hilt.android.internal.testing", "TestComponentDataSupplierImpl");
-  private static final ParameterizedTypeName CLASS_TYPE =
-      ParameterizedTypeName.get(ClassNames.CLASS, WildcardTypeName.subtypeOf(TypeName.OBJECT));
-  private static final ParameterizedTypeName TEST_COMPONENT_DATA_MAP_TYPE =
-      ParameterizedTypeName.get(ClassNames.MAP, CLASS_TYPE, ClassNames.TEST_COMPONENT_DATA);
-
-  private final ProcessingEnvironment processingEnv;
-  private final ImmutableList<RootMetadata> rootMetadatas;
-
-  public TestComponentDataSupplierGenerator(
-      ProcessingEnvironment processingEnv,
-      ImmutableList<RootMetadata> rootMetadatas) {
-    this.processingEnv = processingEnv;
-    this.rootMetadatas = rootMetadatas;
-  }
-
-  /**
-   * <pre><code>{@code
-   * public final class TestComponentDataSupplierImpl extends TestComponentDataSupplier {
-   *   private final Map<Class<?>, TestComponentData> testComponentDataMap = new HashMap<>();
-   *
-   *   protected TestComponentDataSupplierImpl() {
-   *     testComponentDataMap.put(FooTest.class, new FooTest_ComponentData());
-   *     testComponentDataMap.put(BarTest.class, new BarTest_ComponentData());
-   *     ...
-   *   }
-   *
-   *   @Override
-   *   protected Map<Class<?>, TestComponentData> get() {
-   *     return testComponentDataMap;
-   *   }
-   * }
-   * }</code></pre>
-   */
-  public void generate() throws IOException {
-    TypeSpec.Builder generator =
-        TypeSpec.classBuilder(TEST_COMPONENT_DATA_SUPPLIER_IMPL)
-            .addModifiers(PUBLIC, FINAL)
-            .superclass(ClassNames.TEST_COMPONENT_DATA_SUPPLIER)
-            .addField(
-                FieldSpec.builder(
-                        TEST_COMPONENT_DATA_MAP_TYPE, "testComponentDataMap", PRIVATE, FINAL)
-                    .initializer("new $T<>($L)", ClassNames.HASH_MAP, rootMetadatas.size())
-                    .build())
-            .addMethod(constructor())
-            .addMethod(getMethod());
-
-    Processors.addGeneratedAnnotation(
-        generator, processingEnv, ClassNames.ROOT_PROCESSOR.toString());
-
-    JavaFile.builder(TEST_COMPONENT_DATA_SUPPLIER_IMPL.packageName(), generator.build())
-        .build()
-        .writeTo(processingEnv.getFiler());
-  }
-
-
-  private MethodSpec constructor() {
-    MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
-    for (RootMetadata rootMetadata : rootMetadatas) {
-      ClassName testName = rootMetadata.testRootMetadata().testName();
-      ClassName testComponentDataHolderName =
-          Processors.append(Processors.getEnclosedClassName(testName), "_ComponentDataHolder");
-      constructor.addStatement(
-          "testComponentDataMap.put($T.class, $T.get())",
-          testName,
-          testComponentDataHolderName);
-    }
-    return constructor.build();
-  }
-
-  private MethodSpec getMethod() {
-    return MethodSpec.methodBuilder("get")
-        .addAnnotation(Override.class)
-        .addModifiers(PROTECTED)
-        .returns(TEST_COMPONENT_DATA_MAP_TYPE)
-        .addStatement("return testComponentDataMap")
-        .build();
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/TestInjectorGenerator.java b/java/dagger/hilt/processor/internal/root/TestInjectorGenerator.java
deleted file mode 100644
index fc97fed..0000000
--- a/java/dagger/hilt/processor/internal/root/TestInjectorGenerator.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.root;
-
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.Processors;
-import java.io.IOException;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-
-/** Generates an entry point for a test. */
-public final class TestInjectorGenerator {
-  private final ProcessingEnvironment env;
-  private final TestRootMetadata metadata;
-
-  TestInjectorGenerator(ProcessingEnvironment env, TestRootMetadata metadata) {
-    this.env = env;
-    this.metadata = metadata;
-  }
-
-  // @GeneratedEntryPoint
-  // @InstallIn(SingletonComponent.class)
-  // public interface FooTest_GeneratedInjector extends TestInjector<FooTest> {}
-  public void generate() throws IOException {
-    TypeSpec.Builder builder =
-        TypeSpec.interfaceBuilder(metadata.testInjectorName())
-            .addOriginatingElement(metadata.testElement())
-            .addAnnotation(Processors.getOriginatingElementAnnotation(metadata.testElement()))
-            .addAnnotation(ClassNames.GENERATED_ENTRY_POINT)
-            .addAnnotation(
-                AnnotationSpec.builder(ClassNames.INSTALL_IN)
-                    .addMember("value", "$T.class", installInComponent(metadata.testElement()))
-                    .build())
-            .addModifiers(Modifier.PUBLIC)
-            .addSuperinterface(
-                ParameterizedTypeName.get(ClassNames.TEST_INJECTOR, metadata.testName()))
-            .addMethod(
-                MethodSpec.methodBuilder("injectTest")
-                    .addAnnotation(Override.class)
-                    .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
-                    .addParameter(
-                        metadata.testName(),
-                        Processors.upperToLowerCamel(metadata.testName().simpleName()))
-                    .build());
-
-    Processors.addGeneratedAnnotation(builder, env, getClass());
-
-    JavaFile.builder(metadata.testInjectorName().packageName(), builder.build())
-        .build()
-        .writeTo(env.getFiler());
-  }
-
-  private static ClassName installInComponent(TypeElement testElement) {
-    return ClassNames.SINGLETON_COMPONENT;
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/root/TestRootMetadata.java b/java/dagger/hilt/processor/internal/root/TestRootMetadata.java
deleted file mode 100644
index 561beb7..0000000
--- a/java/dagger/hilt/processor/internal/root/TestRootMetadata.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.root;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.value.AutoValue;
-import com.squareup.javapoet.ClassName;
-import dagger.hilt.processor.internal.ClassNames;
-import dagger.hilt.processor.internal.ProcessorErrors;
-import dagger.hilt.processor.internal.Processors;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-/** Metadata class for {@code InternalTestRoot} annotated classes. */
-@AutoValue
-abstract class TestRootMetadata {
-
-  /** Returns the {@link TypeElement} for the test class. */
-  abstract TypeElement testElement();
-
-  /** Returns the {@link TypeElement} for the base application. */
-  abstract TypeElement baseElement();
-
-  /** Returns the {@link ClassName} for the test class. */
-  ClassName testName() {
-    return ClassName.get(testElement());
-  }
-
-  /** Returns the {@link ClassName} for the base application. */
-  ClassName baseAppName() {
-    return ClassName.get(baseElement());
-  }
-
-  /** The name of the generated Hilt test application class for the given test name. */
-  ClassName appName() {
-    return Processors.append(Processors.getEnclosedClassName(testName()), "_Application");
-  }
-
-  /** The name of the generated Hilt test application class for the given test name. */
-  ClassName testInjectorName() {
-    return Processors.append(Processors.getEnclosedClassName(testName()), "_GeneratedInjector");
-  }
-
-  static TestRootMetadata of(ProcessingEnvironment env, Element element) {
-
-    TypeElement testElement = MoreElements.asType(element);
-
-    TypeElement baseElement =
-        env.getElementUtils().getTypeElement(ClassNames.MULTI_DEX_APPLICATION.toString());
-    ProcessorErrors.checkState(
-        !Processors.hasAnnotation(element, ClassNames.ANDROID_ENTRY_POINT),
-        element,
-        "Tests cannot be annotated with @AndroidEntryPoint. Please use @HiltAndroidTest");
-
-    ProcessorErrors.checkState(
-        Processors.hasAnnotation(element, ClassNames.HILT_ANDROID_TEST),
-        element,
-        "Tests must be annotated with @HiltAndroidTest");
-
-    return new AutoValue_TestRootMetadata(testElement, baseElement);
-  }
-}
diff --git a/java/dagger/hilt/testing/BUILD b/java/dagger/hilt/testing/BUILD
deleted file mode 100644
index 3ea1c5f..0000000
--- a/java/dagger/hilt/testing/BUILD
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2020 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.
-#
-# Description:
-#   Testing libraries for Hilt.
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-    deps = [
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-    ],
-)
-
-java_library(
-    name = "test_install_in",
-    testonly = 1,
-    srcs = ["TestInstallIn.java"],
-    exported_plugins = [
-        "//java/dagger/hilt/processor/internal/aggregateddeps:plugin",
-    ],
-    exports = [
-        "//java/dagger/hilt/processor/internal/aggregateddeps:annotation",
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger/hilt:generates_root_input",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/java/dagger/hilt/testing/TestInstallIn.java b/java/dagger/hilt/testing/TestInstallIn.java
deleted file mode 100644
index dfe1389..0000000
--- a/java/dagger/hilt/testing/TestInstallIn.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.testing;
-
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import dagger.hilt.GeneratesRootInput;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * An annotation that replaces one or more {@link dagger.hilt.InstallIn} modules with the annotated
- * module in tests.
- *
- * <p>The annotated class must also be annotated with {@link dagger.Module}.
- *
- * <p>Example:
- *
- * <pre><code>
- *   // Replaces FooModule with FakeFooModule, and installs it into the same component as FooModule.
- *   {@literal @}Module
- *   {@literal @}TestInstallIn(components = SingletonComponent.class, replaces = FooModule.class)
- *   public final class FakeFooModule {
- *     {@literal @}Provides
- *     static Foo provideFoo() {
- *       return new FakeFoo();
- *     }
- *   }
- * </code></pre>
- *
- * @see <a href="https://dagger.dev/hilt/modules">Hilt Modules</a>
- */
-@Retention(CLASS)
-@Target({ElementType.TYPE})
-@GeneratesRootInput
-public @interface TestInstallIn {
-  /** Returns the component(s) into which the annotated module will be installed. */
-  Class<?>[] components();
-
-  /** Returns the {@link InstallIn} module(s) that the annotated class will replace in tests. */
-  Class<?>[] replaces();
-}
diff --git a/java/dagger/hilt/testing/package-info.java b/java/dagger/hilt/testing/package-info.java
deleted file mode 100644
index 5837343..0000000
--- a/java/dagger/hilt/testing/package-info.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-/**
- * This package contains APIs for writing tests with Hilt.
- *
- * @see <a href="https://dagger.dev/hilt/testing">Hilt Testing</a>
- */
-@ParametersAreNonnullByDefault
-package dagger.hilt.testing;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/java/dagger/internal/ConfigureInitializationParameters.java b/java/dagger/internal/ConfigureInitializationParameters.java
new file mode 100644
index 0000000..1ca0fbb
--- /dev/null
+++ b/java/dagger/internal/ConfigureInitializationParameters.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 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;
+
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Target;
+
+/**
+ * Annotates a {@code configureInitialization()} method with {@code ComponentRequirement}s that it
+ * accepts as parameters.
+ */
+@Target(METHOD)
+public @interface ConfigureInitializationParameters {
+  /**
+   * The list of parameters.
+   *
+   * Each value is a {@link dagger.internal.codegen.serialization.ComponentRequirementProto}
+   * serialized in Base64.
+   */
+  String[] value() default {};
+}
diff --git a/java/dagger/internal/GenerationOptions.java b/java/dagger/internal/GenerationOptions.java
new file mode 100644
index 0000000..996cd1d
--- /dev/null
+++ b/java/dagger/internal/GenerationOptions.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Metadata annotation for base subcomponent implementations in ahead-of-time compilations. This
+ * propagates any compiler options related to code generation so that later compilations can
+ * recreate the model of the generated code of superclass implementations.
+ */
+@Target(ElementType.TYPE)
+public @interface GenerationOptions {
+  boolean fastInit();
+}
diff --git a/java/dagger/internal/InjectedFieldSignature.java b/java/dagger/internal/InjectedFieldSignature.java
deleted file mode 100644
index 55d3285..0000000
--- a/java/dagger/internal/InjectedFieldSignature.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2019 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;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks a {@link dagger.MembersInjector} method for injecting a field with the signature of the
- * field intended to inject.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target(ElementType.METHOD)
-public @interface InjectedFieldSignature {
-  String value();
-}
diff --git a/java/dagger/internal/MapBuilder.java b/java/dagger/internal/MapBuilder.java
index 12824d1..25e2b5b 100644
--- a/java/dagger/internal/MapBuilder.java
+++ b/java/dagger/internal/MapBuilder.java
@@ -50,9 +50,11 @@
   }
 
   public Map<K, V> build() {
-    if (contributions.isEmpty()) {
-      return Collections.emptyMap();
+    switch (contributions.size()) {
+      case 0:
+        return Collections.emptyMap();
+      default:
+        return Collections.unmodifiableMap(contributions);
     }
-    return Collections.unmodifiableMap(contributions);
   }
 }
diff --git a/java/dagger/internal/MapFactory.java b/java/dagger/internal/MapFactory.java
index 39748c9..8eb0783 100644
--- a/java/dagger/internal/MapFactory.java
+++ b/java/dagger/internal/MapFactory.java
@@ -66,13 +66,11 @@
       super(size);
     }
 
-    @Override
     public Builder<K, V> put(K key, Provider<V> providerOfValue) {
       super.put(key, providerOfValue);
       return this;
     }
 
-    @Override
     public Builder<K, V> putAll(Provider<Map<K, V>> mapFactory) {
       super.putAll(mapFactory);
       return this;
diff --git a/java/dagger/internal/MissingBindingFactory.java b/java/dagger/internal/MissingBindingFactory.java
new file mode 100644
index 0000000..993d150
--- /dev/null
+++ b/java/dagger/internal/MissingBindingFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+/**
+ * A {@link Factory} that always throws on calls to {@link Factory#get()}. This is necessary in
+ * ahead-of-time subcomponents mode, where modifiable binding methods need to return a {@code
+ * Provider<T>} to a framework instance initialization that is pruned and no longer in the binding
+ * graph, but was present in a superclass implementation. This class fulfills that requirement but
+ * is still practically unusable.
+ */
+public final class MissingBindingFactory<T> implements Factory<T> {
+  private static final MissingBindingFactory<Object> INSTANCE = new MissingBindingFactory<>();
+
+  private MissingBindingFactory() {}
+
+  @SuppressWarnings({"unchecked", "rawtypes"}) // safe covariant cast
+  public static <T> Factory<T> create() {
+    return (Factory) INSTANCE;
+  }
+
+  @Override
+  public T get() {
+    throw new AssertionError(
+        "This binding is not part of the final binding graph. The key was requested by a binding "
+            + "that was believed to possibly be part of the graph, but is no longer requested. "
+            + "If this exception is thrown, it is the result of a Dagger bug.");
+  }
+}
diff --git a/java/dagger/internal/ModifiableBinding.java b/java/dagger/internal/ModifiableBinding.java
new file mode 100644
index 0000000..1e658e4
--- /dev/null
+++ b/java/dagger/internal/ModifiableBinding.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 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;
+
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Target;
+
+/** Annotates methods that implement bindings that may be modified by subclass implementations. */
+@Target(METHOD)
+public @interface ModifiableBinding {
+  /** {@code ModifiableBindingType} of the binding. */
+  // TODO(ronshapiro): should this be a shared enum with dagger.internal.codegen?
+  String modifiableBindingType();
+
+  /** A {@link dagger.internal.codegen.serialization.BindingRequestProto} serialized in Base64. */
+  String bindingRequest();
+
+  /**
+   * For a multibinding, the keys of all contributions it depends on in this implementation.
+   */
+  String[] multibindingContributions() default {};
+}
diff --git a/java/dagger/internal/ModifiableModule.java b/java/dagger/internal/ModifiableModule.java
new file mode 100644
index 0000000..983321e
--- /dev/null
+++ b/java/dagger/internal/ModifiableModule.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 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;
+
+/**
+ * Annotates methods that return {@linkplain dagger.Module modules} that may be modified by subclass
+ * implementations.
+ */
+public @interface ModifiableModule {
+  /** The serialized {@code ComponentRequirement} of this method's module. */
+  String value();
+}
diff --git a/java/dagger/internal/Preconditions.java b/java/dagger/internal/Preconditions.java
index 5c2d740..714a353 100644
--- a/java/dagger/internal/Preconditions.java
+++ b/java/dagger/internal/Preconditions.java
@@ -51,34 +51,6 @@
   }
 
   /**
-   * Ensures that an object reference returned from a provides method is not null.
-   *
-   * @param reference an object reference
-   * @return the non-null reference that was validated
-   * @throws NullPointerException if {@code reference} is null
-   */
-  public static <T> T checkNotNullFromProvides(T reference) {
-    if (reference == null) {
-      throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");
-    }
-    return reference;
-  }
-
-  /**
-   * Ensures that an object reference returned from a component method is not null.
-   *
-   * @param reference an object reference
-   * @return the non-null reference that was validated
-   * @throws NullPointerException if {@code reference} is null
-   */
-  public static <T> T checkNotNullFromComponent(T reference) {
-    if (reference == null) {
-      throw new NullPointerException("Cannot return null from a non-@Nullable component method");
-    }
-    return reference;
-  }
-
-  /**
    * Ensures that an object reference passed as a parameter to the calling method is not null.
    *
    * @param reference an object reference
diff --git a/java/dagger/internal/SetBuilder.java b/java/dagger/internal/SetBuilder.java
index d65e7cb..41a2fc7 100644
--- a/java/dagger/internal/SetBuilder.java
+++ b/java/dagger/internal/SetBuilder.java
@@ -61,12 +61,13 @@
   }
 
   public Set<T> build() {
-    if (contributions.isEmpty()) {
-      return Collections.emptySet();
-    } else if (contributions.size() == 1) {
-      return Collections.singleton(contributions.get(0));
-    } else {
-      return Collections.unmodifiableSet(new HashSet<>(contributions));
+    switch (contributions.size()) {
+      case 0:
+        return Collections.emptySet();
+      case 1:
+        return Collections.singleton(contributions.get(0));
+      default:
+        return Collections.unmodifiableSet(new HashSet<>(contributions));
     }
   }
 }
diff --git a/java/dagger/internal/codegen/AnnotationCreatorGenerator.java b/java/dagger/internal/codegen/AnnotationCreatorGenerator.java
new file mode 100644
index 0000000..273f552
--- /dev/null
+++ b/java/dagger/internal/codegen/AnnotationCreatorGenerator.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2014 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.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.AnnotationExpression.createMethodName;
+import static dagger.internal.codegen.AnnotationExpression.getAnnotationCreatorClassName;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.LinkedHashSet;
+import java.util.Optional;
+import java.util.Set;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.util.SimpleTypeVisitor6;
+
+/**
+ * Generates classes that create annotation instances for an annotation type. The generated class
+ * will have a private empty constructor, a static method that creates the annotation type itself,
+ * and a static method that creates each annotation type that is nested in the top-level annotation
+ * type.
+ *
+ * <p>So for an example annotation:
+ *
+ * <pre>
+ *   {@literal @interface} Foo {
+ *     String s();
+ *     int i();
+ *     Bar bar(); // an annotation defined elsewhere
+ *   }
+ * </pre>
+ *
+ * the generated class will look like:
+ *
+ * <pre>
+ *   public final class FooCreator {
+ *     private FooCreator() {}
+ *
+ *     public static Foo createFoo(String s, int i, Bar bar) { … }
+ *     public static Bar createBar(…) { … }
+ *   }
+ * </pre>
+ */
+class AnnotationCreatorGenerator extends SourceFileGenerator<TypeElement> {
+  private static final ClassName AUTO_ANNOTATION =
+      ClassName.get("com.google.auto.value", "AutoAnnotation");
+
+  @Inject
+  AnnotationCreatorGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
+    super(filer, elements, sourceVersion);
+  }
+
+  @Override
+  ClassName nameGeneratedType(TypeElement annotationType) {
+    return getAnnotationCreatorClassName(annotationType);
+  }
+
+  @Override
+  Element originatingElement(TypeElement annotationType) {
+    return annotationType;
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, TypeElement annotationType) {
+    TypeSpec.Builder annotationCreatorBuilder =
+        classBuilder(generatedTypeName)
+            .addModifiers(PUBLIC, FINAL)
+            .addMethod(constructorBuilder().addModifiers(PRIVATE).build());
+
+    for (TypeElement annotationElement : annotationsToCreate(annotationType)) {
+      annotationCreatorBuilder.addMethod(buildCreateMethod(generatedTypeName, annotationElement));
+    }
+
+    return Optional.of(annotationCreatorBuilder);
+  }
+
+  private MethodSpec buildCreateMethod(ClassName generatedTypeName, TypeElement annotationElement) {
+    String createMethodName = createMethodName(annotationElement);
+    MethodSpec.Builder createMethod =
+        methodBuilder(createMethodName)
+            .addAnnotation(AUTO_ANNOTATION)
+            .addModifiers(PUBLIC, STATIC)
+            .returns(TypeName.get(annotationElement.asType()));
+
+    ImmutableList.Builder<CodeBlock> parameters = ImmutableList.builder();
+    for (ExecutableElement annotationMember : methodsIn(annotationElement.getEnclosedElements())) {
+      String parameterName = annotationMember.getSimpleName().toString();
+      TypeName parameterType = TypeName.get(annotationMember.getReturnType());
+      createMethod.addParameter(parameterType, parameterName);
+      parameters.add(CodeBlock.of("$L", parameterName));
+    }
+
+    ClassName autoAnnotationClass =
+        generatedTypeName.peerClass(
+            "AutoAnnotation_" + generatedTypeName.simpleName() + "_" + createMethodName);
+    createMethod.addStatement(
+        "return new $T($L)", autoAnnotationClass, makeParametersCodeBlock(parameters.build()));
+    return createMethod.build();
+  }
+
+  /**
+   * Returns the annotation types for which {@code @AutoAnnotation static Foo createFoo(…)} methods
+   * should be written.
+   */
+  protected Set<TypeElement> annotationsToCreate(TypeElement annotationElement) {
+    return nestedAnnotationElements(annotationElement, new LinkedHashSet<>());
+  }
+
+  @CanIgnoreReturnValue
+  private static Set<TypeElement> nestedAnnotationElements(
+      TypeElement annotationElement, Set<TypeElement> annotationElements) {
+    if (annotationElements.add(annotationElement)) {
+      for (ExecutableElement method : methodsIn(annotationElement.getEnclosedElements())) {
+        TRAVERSE_NESTED_ANNOTATIONS.visit(method.getReturnType(), annotationElements);
+      }
+    }
+    return annotationElements;
+  }
+
+  private static final SimpleTypeVisitor6<Void, Set<TypeElement>> TRAVERSE_NESTED_ANNOTATIONS =
+      new SimpleTypeVisitor6<Void, Set<TypeElement>>() {
+        @Override
+        public Void visitDeclared(DeclaredType t, Set<TypeElement> p) {
+          TypeElement typeElement = MoreTypes.asTypeElement(t);
+          if (typeElement.getKind() == ElementKind.ANNOTATION_TYPE) {
+            nestedAnnotationElements(typeElement, p);
+          }
+          return null;
+        }
+      };
+}
diff --git a/java/dagger/internal/codegen/AnnotationExpression.java b/java/dagger/internal/codegen/AnnotationExpression.java
new file mode 100644
index 0000000..8d729e2
--- /dev/null
+++ b/java/dagger/internal/codegen/AnnotationExpression.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2016 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.AnnotationMirrors.getAnnotationValuesWithDefaults;
+import static dagger.internal.codegen.SourceFiles.classFileName;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static java.util.stream.Collectors.toList;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import java.util.List;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleAnnotationValueVisitor6;
+import javax.lang.model.util.SimpleTypeVisitor6;
+
+/**
+ * Returns an expression creating an instance of the visited annotation type. Its parameter must be
+ * a class as generated by {@link AnnotationCreatorGenerator}.
+ *
+ * <p>Note that {@link AnnotationValue#toString()} is the source-code representation of the value
+ * <em>when used in an annotation</em>, which is not always the same as the representation needed
+ * when creating the value in a method body.
+ *
+ * <p>For example, inside an annotation, a nested array of {@code int}s is simply {@code {1, 2, 3}},
+ * but in code it would have to be {@code new int[] {1, 2, 3}}.
+ */
+class AnnotationExpression extends SimpleAnnotationValueVisitor6<CodeBlock, AnnotationValue> {
+
+  private final AnnotationMirror annotation;
+  private final ClassName creatorClass;
+
+  AnnotationExpression(AnnotationMirror annotation) {
+    this.annotation = annotation;
+    this.creatorClass =
+        getAnnotationCreatorClassName(
+            MoreTypes.asTypeElement(annotation.getAnnotationType()));
+  }
+
+  /**
+   * Returns an expression that calls static methods on the annotation's creator class to create an
+   * annotation instance equivalent the annotation passed to the constructor.
+   */
+  CodeBlock getAnnotationInstanceExpression() {
+    return getAnnotationInstanceExpression(annotation);
+  }
+
+  private CodeBlock getAnnotationInstanceExpression(AnnotationMirror annotation) {
+    return CodeBlock.of(
+        "$T.$L($L)",
+        creatorClass,
+        createMethodName(
+            MoreElements.asType(annotation.getAnnotationType().asElement())),
+        makeParametersCodeBlock(
+            getAnnotationValuesWithDefaults(annotation)
+                .entrySet()
+                .stream()
+                .map(entry -> getValueExpression(entry.getKey().getReturnType(), entry.getValue()))
+                .collect(toList())));
+  }
+
+  /**
+   * Returns the name of the generated class that contains the static {@code create} methods for an
+   * annotation type.
+   */
+  static ClassName getAnnotationCreatorClassName(TypeElement annotationType) {
+    ClassName annotationTypeName = ClassName.get(annotationType);
+    return annotationTypeName
+        .topLevelClassName()
+        .peerClass(classFileName(annotationTypeName) + "Creator");
+  }
+
+  static String createMethodName(TypeElement annotationType) {
+    return "create" + annotationType.getSimpleName();
+  }
+
+  /**
+   * Returns an expression that evaluates to a {@code value} of a given type on an {@code
+   * annotation}.
+   */
+  CodeBlock getValueExpression(TypeMirror valueType, AnnotationValue value) {
+    return ARRAY_LITERAL_PREFIX.visit(valueType, this.visit(value, value));
+  }
+
+  @Override
+  public CodeBlock visitEnumConstant(VariableElement c, AnnotationValue p) {
+    return CodeBlock.of("$T.$L", c.getEnclosingElement(), c.getSimpleName());
+  }
+
+  @Override
+  public CodeBlock visitAnnotation(AnnotationMirror a, AnnotationValue p) {
+    return getAnnotationInstanceExpression(a);
+  }
+
+  @Override
+  public CodeBlock visitType(TypeMirror t, AnnotationValue p) {
+    return CodeBlock.of("$T.class", t);
+  }
+
+  @Override
+  public CodeBlock visitString(String s, AnnotationValue p) {
+    return CodeBlock.of("$S", s);
+  }
+
+  @Override
+  public CodeBlock visitByte(byte b, AnnotationValue p) {
+    return CodeBlock.of("(byte) $L", b);
+  }
+
+  @Override
+  public CodeBlock visitChar(char c, AnnotationValue p) {
+    return CodeBlock.of("$L", p);
+  }
+
+  @Override
+  public CodeBlock visitDouble(double d, AnnotationValue p) {
+    return CodeBlock.of("$LD", d);
+  }
+
+  @Override
+  public CodeBlock visitFloat(float f, AnnotationValue p) {
+    return CodeBlock.of("$LF", f);
+  }
+
+  @Override
+  public CodeBlock visitLong(long i, AnnotationValue p) {
+    return CodeBlock.of("$LL", i);
+  }
+
+  @Override
+  public CodeBlock visitShort(short s, AnnotationValue p) {
+    return CodeBlock.of("(short) $L", s);
+  }
+
+  @Override
+  protected CodeBlock defaultAction(Object o, AnnotationValue p) {
+    return CodeBlock.of("$L", o);
+  }
+
+  @Override
+  public CodeBlock visitArray(List<? extends AnnotationValue> values, AnnotationValue p) {
+    ImmutableList.Builder<CodeBlock> codeBlocks = ImmutableList.builder();
+    for (AnnotationValue value : values) {
+      codeBlocks.add(this.visit(value, p));
+    }
+    return CodeBlock.of("{$L}", makeParametersCodeBlock(codeBlocks.build()));
+  }
+
+  /**
+   * If the visited type is an array, prefixes the parameter code block with {@code new T[]}, where
+   * {@code T} is the raw array component type.
+   */
+  private static final SimpleTypeVisitor6<CodeBlock, CodeBlock> ARRAY_LITERAL_PREFIX =
+      new SimpleTypeVisitor6<CodeBlock, CodeBlock>() {
+
+        @Override
+        public CodeBlock visitArray(ArrayType t, CodeBlock p) {
+          return CodeBlock.of("new $T[] $L", RAW_TYPE_NAME.visit(t.getComponentType()), p);
+        }
+
+        @Override
+        protected CodeBlock defaultAction(TypeMirror e, CodeBlock p) {
+          return p;
+        }
+      };
+
+  /**
+   * If the visited type is an array, returns the name of its raw component type; otherwise returns
+   * the name of the type itself.
+   */
+  private static final SimpleTypeVisitor6<TypeName, Void> RAW_TYPE_NAME =
+      new SimpleTypeVisitor6<TypeName, Void>() {
+        @Override
+        public TypeName visitDeclared(DeclaredType t, Void p) {
+          return ClassName.get(MoreTypes.asTypeElement(t));
+        }
+
+        @Override
+        protected TypeName defaultAction(TypeMirror e, Void p) {
+          return TypeName.get(e);
+        }
+      };
+}
diff --git a/java/dagger/internal/codegen/AnnotationProtoConverter.java b/java/dagger/internal/codegen/AnnotationProtoConverter.java
new file mode 100644
index 0000000..282d8ca
--- /dev/null
+++ b/java/dagger/internal/codegen/AnnotationProtoConverter.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2019 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.AnnotationMirrors.getAnnotationValuesWithDefaults;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Maps.transformValues;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import dagger.internal.codegen.serialization.AnnotationProto;
+import dagger.internal.codegen.serialization.AnnotationValueProto;
+import java.util.Collections;
+import java.util.List;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.AnnotationValueVisitor;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleAnnotationValueVisitor8;
+
+/** Converts {@link AnnotationMirror}s to {@link AnnotationProto}s and vice-versa. */
+final class AnnotationProtoConverter {
+  private final TypeProtoConverter typeProtoConverter;
+
+  @Inject
+  AnnotationProtoConverter(TypeProtoConverter typeProtoConverter) {
+    this.typeProtoConverter = typeProtoConverter;
+  }
+
+  /** Translates an {@link AnnotationMirror} to a proto representation. */
+  static AnnotationProto toProto(AnnotationMirror annotationMirror) {
+    AnnotationProto.Builder builder = AnnotationProto.newBuilder();
+    builder.setAnnotationType(TypeProtoConverter.toProto(annotationMirror.getAnnotationType()));
+    getAnnotationValuesWithDefaults(annotationMirror)
+        .forEach(
+            (attribute, value) ->
+                builder.putAllValues(
+                    Collections.singletonMap(
+                        attribute.getSimpleName().toString(), annotationValueProto(value))));
+    return builder.build();
+  }
+
+  /** Creates an {@link AnnotationMirror} from its proto representation. */
+  AnnotationMirror fromProto(AnnotationProto annotation) {
+    return SimpleAnnotationMirror.of(
+        MoreTypes.asTypeElement(typeProtoConverter.fromProto(annotation.getAnnotationType())),
+        transformValues(annotation.getValues(), AnnotationValueFromProto::new));
+  }
+
+  private static final AnnotationValueVisitor<
+          AnnotationValueProto.Builder, AnnotationValueProto.Builder>
+      ANNOTATION_VALUE_TO_PROTO =
+          new SimpleAnnotationValueVisitor8<
+              AnnotationValueProto.Builder, AnnotationValueProto.Builder>() {
+            @Override
+            public AnnotationValueProto.Builder visitAnnotation(
+                AnnotationMirror nestedAnnotation, AnnotationValueProto.Builder builder) {
+              return builder
+                  .setNestedAnnotation(toProto(nestedAnnotation))
+                  .setKind(AnnotationValueProto.Kind.ANNOTATION);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitBoolean(
+                boolean b, AnnotationValueProto.Builder builder) {
+              return builder.setBooleanValue(b).setKind(AnnotationValueProto.Kind.BOOLEAN);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitChar(
+                char c, AnnotationValueProto.Builder builder) {
+              return builder
+                  .setStringValue(String.valueOf(c))
+                  .setKind(AnnotationValueProto.Kind.CHAR);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitByte(
+                byte b, AnnotationValueProto.Builder builder) {
+              return builder.setIntValue(b).setKind(AnnotationValueProto.Kind.BYTE);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitShort(
+                short s, AnnotationValueProto.Builder builder) {
+              return builder.setIntValue(s).setKind(AnnotationValueProto.Kind.SHORT);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitInt(
+                int i, AnnotationValueProto.Builder builder) {
+              return builder.setIntValue(i).setKind(AnnotationValueProto.Kind.INT);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitFloat(
+                float f, AnnotationValueProto.Builder builder) {
+              return builder.setFloatValue(f).setKind(AnnotationValueProto.Kind.FLOAT);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitLong(
+                long l, AnnotationValueProto.Builder builder) {
+              return builder.setLongValue(l).setKind(AnnotationValueProto.Kind.LONG);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitDouble(
+                double d, AnnotationValueProto.Builder builder) {
+              return builder.setDoubleValue(d).setKind(AnnotationValueProto.Kind.DOUBLE);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitString(
+                String s, AnnotationValueProto.Builder builder) {
+              return builder.setStringValue(s).setKind(AnnotationValueProto.Kind.STRING);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitType(
+                TypeMirror t, AnnotationValueProto.Builder builder) {
+              return builder
+                  .setClassLiteral(TypeProtoConverter.toProto(t))
+                  .setKind(AnnotationValueProto.Kind.CLASS_LITERAL);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitEnumConstant(
+                VariableElement c, AnnotationValueProto.Builder builder) {
+              return builder
+                  .setEnumType(TypeProtoConverter.toProto(c.asType()))
+                  .setEnumName(c.getSimpleName().toString())
+                  .setKind(AnnotationValueProto.Kind.ENUM);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitArray(
+                List<? extends AnnotationValue> values, AnnotationValueProto.Builder builder) {
+              values.forEach(value -> builder.addArrayValues(annotationValueProto(value)));
+              return builder.setKind(AnnotationValueProto.Kind.ARRAY);
+            }
+
+            @Override
+            public AnnotationValueProto.Builder visitUnknown(
+                AnnotationValue av, AnnotationValueProto.Builder builder) {
+              throw new UnsupportedOperationException(av.toString());
+            }
+          };
+
+  /** Translates an {@link AnnotationValue} to a proto representation. */
+  private static AnnotationValueProto annotationValueProto(AnnotationValue annotationValue) {
+    return annotationValue
+        .accept(ANNOTATION_VALUE_TO_PROTO, AnnotationValueProto.newBuilder())
+        .build();
+  }
+
+  private class AnnotationValueFromProto implements AnnotationValue {
+    private final AnnotationValueProto proto;
+
+    AnnotationValueFromProto(AnnotationValueProto proto) {
+      this.proto = proto;
+    }
+
+    @Override
+    public Object getValue() {
+      switch (proto.getKind()) {
+        case BOOLEAN:
+          return proto.getBooleanValue();
+        case BYTE:
+          return (byte) proto.getIntValue();
+        case SHORT:
+          return (short) proto.getIntValue();
+        case CHAR:
+          return getCharValue();
+        case INT:
+          return proto.getIntValue();
+        case FLOAT:
+          return proto.getFloatValue();
+        case LONG:
+          return proto.getLongValue();
+        case DOUBLE:
+          return proto.getDoubleValue();
+        case STRING:
+          return proto.getStringValue();
+        case CLASS_LITERAL:
+          return typeProtoConverter.fromProto(proto.getClassLiteral());
+        case ENUM:
+          return getEnumConstant();
+        case ANNOTATION:
+          return fromProto(proto.getNestedAnnotation());
+        case ARRAY:
+          return getArrayValues();
+        case UNKNOWN:
+        case UNRECOGNIZED:
+          // fall through
+      }
+      throw new AssertionError(proto);
+    }
+
+    @Override
+    public <R, P> R accept(AnnotationValueVisitor<R, P> visitor, P passedValue) {
+      switch (proto.getKind()) {
+        case BOOLEAN:
+          return visitor.visitBoolean(proto.getBooleanValue(), passedValue);
+        case BYTE:
+          return visitor.visitByte((byte) proto.getIntValue(), passedValue);
+        case SHORT:
+          return visitor.visitShort((short) proto.getIntValue(), passedValue);
+        case CHAR:
+          return visitor.visitChar(getCharValue(), passedValue);
+        case INT:
+          return visitor.visitInt(proto.getIntValue(), passedValue);
+        case FLOAT:
+          return visitor.visitFloat(proto.getFloatValue(), passedValue);
+        case LONG:
+          return visitor.visitLong(proto.getLongValue(), passedValue);
+        case DOUBLE:
+          return visitor.visitDouble(proto.getDoubleValue(), passedValue);
+        case STRING:
+          return visitor.visitString((String) getValue(), passedValue);
+        case CLASS_LITERAL:
+          return visitor.visitType((TypeMirror) getValue(), passedValue);
+        case ENUM:
+          return visitor.visitEnumConstant((VariableElement) getValue(), passedValue);
+        case ANNOTATION:
+          return visitor.visitAnnotation((AnnotationMirror) getValue(), passedValue);
+        case ARRAY:
+          return visitor.visitArray(getArrayValues(), passedValue);
+        case UNKNOWN:
+        case UNRECOGNIZED:
+          // fall through
+      }
+      throw new AssertionError(proto);
+    }
+
+    private char getCharValue() {
+      checkState(proto.getKind().equals(AnnotationValueProto.Kind.CHAR));
+      return proto.getStringValue().charAt(0);
+    }
+
+    private VariableElement getEnumConstant() {
+      checkState(proto.getKind().equals(AnnotationValueProto.Kind.ENUM));
+      TypeMirror enumType = typeProtoConverter.fromProto(proto.getEnumType());
+      return fieldsIn(MoreTypes.asTypeElement(enumType).getEnclosedElements()).stream()
+          .filter(value -> value.getSimpleName().contentEquals(proto.getEnumName()))
+          .findFirst()
+          .get();
+    }
+
+    private ImmutableList<AnnotationValue> getArrayValues() {
+      checkState(proto.getKind().equals(AnnotationValueProto.Kind.ARRAY));
+      return proto.getArrayValuesList().stream()
+          .map(AnnotationValueFromProto::new)
+          .collect(toImmutableList());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/AnonymousProviderCreationExpression.java b/java/dagger/internal/codegen/AnonymousProviderCreationExpression.java
new file mode 100644
index 0000000..fc30eaa
--- /dev/null
+++ b/java/dagger/internal/codegen/AnonymousProviderCreationExpression.java
@@ -0,0 +1,58 @@
+/*
+ * 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 dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.javapoet.CodeBlocks.anonymousProvider;
+import static dagger.model.RequestKind.INSTANCE;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.javapoet.Expression;
+
+/**
+ * A {@link javax.inject.Provider} creation expression for an anonymous inner class whose
+ * {@code get()} method returns the expression for an instance binding request for its key.
+ */
+final class AnonymousProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+  private final ContributionBinding binding;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final ClassName requestingClass;
+
+  AnonymousProviderCreationExpression(
+      ContributionBinding binding,
+      ComponentBindingExpressions componentBindingExpressions,
+      ClassName requestingClass) {
+    this.binding = binding;
+    this.componentBindingExpressions = componentBindingExpressions;
+    this.requestingClass = requestingClass;
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    BindingRequest instanceExpressionRequest = bindingRequest(binding.key(), INSTANCE);
+    Expression instanceExpression =
+        componentBindingExpressions.getDependencyExpression(
+            instanceExpressionRequest,
+            // Not a real class name, but the actual requestingClass is an inner class within the
+            // given class, not that class itself.
+            requestingClass.nestedClass("Anonymous"));
+    return anonymousProvider(instanceExpression);
+  }
+}
diff --git a/java/dagger/internal/codegen/AnyBindingMethodValidator.java b/java/dagger/internal/codegen/AnyBindingMethodValidator.java
new file mode 100644
index 0000000..bad9636
--- /dev/null
+++ b/java/dagger/internal/codegen/AnyBindingMethodValidator.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2016 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.MoreElements.isAnnotationPresent;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
+import static java.util.stream.Collectors.joining;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+
+/** Validates any binding method. */
+final class AnyBindingMethodValidator {
+
+  private final ImmutableMap<Class<? extends Annotation>, BindingMethodValidator> validators;
+  private final Map<ExecutableElement, ValidationReport<ExecutableElement>> reports =
+      new HashMap<>();
+
+  @Inject
+  AnyBindingMethodValidator(
+      ImmutableMap<Class<? extends Annotation>, BindingMethodValidator> validators) {
+    this.validators = validators;
+  }
+
+  /** Returns the binding method annotations considered by this validator. */
+  ImmutableSet<Class<? extends Annotation>> methodAnnotations() {
+    return validators.keySet();
+  }
+
+  /**
+   * Returns {@code true} if {@code method} is annotated with at least one of {@link
+   * #methodAnnotations()}.
+   */
+  boolean isBindingMethod(ExecutableElement method) {
+    return isAnyAnnotationPresent(method, methodAnnotations());
+  }
+
+  /**
+   * Returns a validation report for a method.
+   *
+   * <ul>
+   *   <li>Reports an error if {@code method} is annotated with more than one {@linkplain
+   *       #methodAnnotations() binding method annotation}.
+   *   <li>Validates {@code method} with the {@link BindingMethodValidator} for the single
+   *       {@linkplain #methodAnnotations() binding method annotation}.
+   * </ul>
+   *
+   * @throws IllegalArgumentException if {@code method} is not annotated by any {@linkplain
+   *     #methodAnnotations() binding method annotation}
+   */
+  ValidationReport<ExecutableElement> validate(ExecutableElement method) {
+    return reentrantComputeIfAbsent(reports, method, this::validateUncached);
+  }
+
+  /**
+   * Returns {@code true} if {@code method} was already {@linkplain #validate(ExecutableElement)
+   * validated}.
+   */
+  boolean wasAlreadyValidated(ExecutableElement method) {
+    return reports.containsKey(method);
+  }
+
+  private ValidationReport<ExecutableElement> validateUncached(ExecutableElement method) {
+    ValidationReport.Builder<ExecutableElement> report = ValidationReport.about(method);
+    ImmutableSet<? extends Class<? extends Annotation>> bindingMethodAnnotations =
+        methodAnnotations()
+            .stream()
+            .filter(annotation -> isAnnotationPresent(method, annotation))
+            .collect(toImmutableSet());
+    switch (bindingMethodAnnotations.size()) {
+      case 0:
+        throw new IllegalArgumentException(
+            String.format("%s has no binding method annotation", method));
+
+      case 1:
+        report.addSubreport(
+            validators.get(getOnlyElement(bindingMethodAnnotations)).validate(method));
+        break;
+
+      default:
+        report.addError(
+            String.format(
+                "%s is annotated with more than one of (%s)",
+                method.getSimpleName(),
+                methodAnnotations().stream().map(Class::getCanonicalName).collect(joining(", "))),
+            method);
+        break;
+    }
+    return report.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/AssistedFactoryProcessingStep.java b/java/dagger/internal/codegen/AssistedFactoryProcessingStep.java
deleted file mode 100644
index abc0436..0000000
--- a/java/dagger/internal/codegen/AssistedFactoryProcessingStep.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2020 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.MoreElements.asType;
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedInjectedConstructors;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeNames.INSTANCE_FACTORY;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
-import static java.util.stream.Collectors.joining;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.assisted.AssistedFactory;
-import dagger.internal.codegen.base.SourceFileGenerationException;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.AssistedInjectionAnnotations;
-import dagger.internal.codegen.binding.AssistedInjectionAnnotations.AssistedFactoryMetadata;
-import dagger.internal.codegen.binding.AssistedInjectionAnnotations.AssistedParameter;
-import dagger.internal.codegen.binding.BindingFactory;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
-import dagger.internal.codegen.validation.ValidationReport;
-import java.lang.annotation.Annotation;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.processing.Filer;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-
-/** An annotation processor for {@link dagger.assisted.AssistedFactory}-annotated types. */
-final class AssistedFactoryProcessingStep extends TypeCheckingProcessingStep<TypeElement> {
-  private final Messager messager;
-  private final Filer filer;
-  private final SourceVersion sourceVersion;
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final BindingFactory bindingFactory;
-
-  @Inject
-  AssistedFactoryProcessingStep(
-      Messager messager,
-      Filer filer,
-      SourceVersion sourceVersion,
-      DaggerElements elements,
-      DaggerTypes types,
-      BindingFactory bindingFactory) {
-    super(MoreElements::asType);
-    this.messager = messager;
-    this.filer = filer;
-    this.sourceVersion = sourceVersion;
-    this.elements = elements;
-    this.types = types;
-    this.bindingFactory = bindingFactory;
-  }
-
-  @Override
-  public ImmutableSet<Class<? extends Annotation>> annotations() {
-    return ImmutableSet.of(AssistedFactory.class);
-  }
-
-  @Override
-  protected void process(
-      TypeElement factory, ImmutableSet<Class<? extends Annotation>> annotations) {
-    ValidationReport<TypeElement> report = new AssistedFactoryValidator().validate(factory);
-    report.printMessagesTo(messager);
-    if (report.isClean()) {
-      try {
-        ProvisionBinding binding = bindingFactory.assistedFactoryBinding(factory, Optional.empty());
-        new AssistedFactoryImplGenerator().generate(binding);
-      } catch (SourceFileGenerationException e) {
-        e.printMessageTo(messager);
-      }
-    }
-  }
-
-  private final class AssistedFactoryValidator {
-    ValidationReport<TypeElement> validate(TypeElement factory) {
-      ValidationReport.Builder<TypeElement> report = ValidationReport.about(factory);
-
-      if (!factory.getModifiers().contains(ABSTRACT)) {
-        return report
-            .addError(
-                "The @AssistedFactory-annotated type must be either an abstract class or "
-                    + "interface.",
-                factory)
-            .build();
-      }
-
-      if (factory.getNestingKind().isNested() && !factory.getModifiers().contains(STATIC)) {
-        report.addError("Nested @AssistedFactory-annotated types must be static. ", factory);
-      }
-
-      ImmutableSet<ExecutableElement> abstractFactoryMethods =
-          AssistedInjectionAnnotations.assistedFactoryMethods(factory, elements, types);
-
-      if (abstractFactoryMethods.isEmpty()) {
-        report.addError(
-            "The @AssistedFactory-annotated type is missing an abstract, non-default method "
-                + "whose return type matches the assisted injection type.",
-            factory);
-      }
-
-      for (ExecutableElement method : abstractFactoryMethods) {
-        ExecutableType methodType = types.resolveExecutableType(method, factory.asType());
-        if (!isAssistedInjectionType(methodType.getReturnType())) {
-          report.addError(
-              String.format(
-                  "Invalid return type: %s. An assisted factory's abstract method must return a "
-                      + "type with an @AssistedInject-annotated constructor.",
-                  methodType.getReturnType()),
-              method);
-        }
-        if (!method.getTypeParameters().isEmpty()) {
-          report.addError(
-              "@AssistedFactory does not currently support type parameters in the creator "
-                  + "method. See https://github.com/google/dagger/issues/2279",
-              method);
-        }
-      }
-
-      if (abstractFactoryMethods.size() > 1) {
-        report.addError(
-            "The @AssistedFactory-annotated type should contain a single abstract, non-default"
-                + " method but found multiple: "
-                + abstractFactoryMethods,
-            factory);
-      }
-
-      if (!report.build().isClean()) {
-        return report.build();
-      }
-
-      AssistedFactoryMetadata metadata =
-          AssistedFactoryMetadata.create(factory.asType(), elements, types);
-
-      // Note: We check uniqueness of the @AssistedInject constructor parameters in
-      // AssistedInjectProcessingStep. We need to check uniqueness for here too because we may
-      // have resolved some type parameters that were not resolved in the @AssistedInject type.
-      Set<AssistedParameter> uniqueAssistedParameters = new HashSet<>();
-      for (AssistedParameter assistedParameter : metadata.assistedFactoryAssistedParameters()) {
-        if (!uniqueAssistedParameters.add(assistedParameter)) {
-          report.addError(
-              "@AssistedFactory method has duplicate @Assisted types: " + assistedParameter,
-              assistedParameter.variableElement());
-        }
-      }
-
-      if (!ImmutableSet.copyOf(metadata.assistedInjectAssistedParameters())
-          .equals(ImmutableSet.copyOf(metadata.assistedFactoryAssistedParameters()))) {
-        report.addError(
-            String.format(
-                "The parameters in the factory method must match the @Assisted parameters in %s."
-                    + "\n      Actual: %s#%s"
-                    + "\n    Expected: %s#%s(%s)",
-                metadata.assistedInjectType(),
-                metadata.factory().getQualifiedName(),
-                metadata.factoryMethod(),
-                metadata.factory().getQualifiedName(),
-                metadata.factoryMethod().getSimpleName(),
-                metadata.assistedInjectAssistedParameters().stream()
-                    .map(AssistedParameter::type)
-                    .map(Object::toString)
-                    .collect(joining(", "))),
-            metadata.factoryMethod());
-      }
-
-      return report.build();
-    }
-
-    private boolean isAssistedInjectionType(TypeMirror type) {
-      return type.getKind() == TypeKind.DECLARED
-          && AssistedInjectionAnnotations.isAssistedInjectionType(asTypeElement(type));
-    }
-  }
-
-  /** Generates an implementation of the {@link dagger.assisted.AssistedFactory}-annotated class. */
-  private final class AssistedFactoryImplGenerator extends SourceFileGenerator<ProvisionBinding> {
-    AssistedFactoryImplGenerator() {
-      super(filer, elements, sourceVersion);
-    }
-
-    @Override
-    public ClassName nameGeneratedType(ProvisionBinding binding) {
-      return generatedClassNameForBinding(binding);
-    }
-
-    @Override
-    public Element originatingElement(ProvisionBinding binding) {
-      return binding.bindingElement().get();
-    }
-
-    // For each @AssistedFactory-annotated type, we generates a class named "*_Impl" that implements
-    // that type.
-    //
-    // Note that this class internally delegates to the @AssistedInject generated class, which
-    // contains the actual implementation logic for creating the @AssistedInject type. The reason we
-    // need both of these generated classes is because while the @AssistedInject generated class
-    // knows how to create the @AssistedInject type, it doesn't know about all of the
-    // @AssistedFactory interfaces that it needs to extend when it's generated. Thus, the role of
-    // the @AssistedFactory generated class is purely to implement the @AssistedFactory type.
-    // Furthermore, while we could have put all of the logic into the @AssistedFactory generated
-    // class and not generate the @AssistedInject generated class, having the @AssistedInject
-    // generated class ensures we have proper accessibility to the @AssistedInject type, and reduces
-    // duplicate logic if there are multiple @AssistedFactory types for the same @AssistedInject
-    // type.
-    //
-    // Example:
-    // public class FooFactory_Impl implements FooFactory {
-    //   private final Foo_Factory delegateFactory;
-    //
-    //   FooFactory_Impl(Foo_Factory delegateFactory) {
-    //     this.delegateFactory = delegateFactory;
-    //   }
-    //
-    //   @Override
-    //   public Foo createFoo(AssistedDep assistedDep) {
-    //     return delegateFactory.get(assistedDep);
-    //   }
-    //
-    //   public static Provider<FooFactory> create(Foo_Factory delegateFactory) {
-    //     return InstanceFactory.create(new FooFactory_Impl(delegateFactory));
-    //   }
-    // }
-    @Override
-    public Optional<TypeSpec.Builder> write(ProvisionBinding binding) {
-      TypeElement factory = asType(binding.bindingElement().get());
-
-      ClassName name = nameGeneratedType(binding);
-      TypeSpec.Builder builder =
-          TypeSpec.classBuilder(name)
-              .addModifiers(PUBLIC, FINAL)
-              .addTypeVariables(
-                  factory.getTypeParameters().stream()
-                      .map(TypeVariableName::get)
-                      .collect(toImmutableList()));
-
-      if (factory.getKind() == ElementKind.INTERFACE) {
-        builder.addSuperinterface(factory.asType());
-      } else {
-        builder.superclass(factory.asType());
-      }
-
-      AssistedFactoryMetadata metadata =
-          AssistedFactoryMetadata.create(asDeclared(factory.asType()), elements, types);
-      ParameterSpec delegateFactoryParam =
-          ParameterSpec.builder(
-                  delegateFactoryTypeName(metadata.assistedInjectType()), "delegateFactory")
-              .build();
-      builder
-          .addField(
-              FieldSpec.builder(delegateFactoryParam.type, delegateFactoryParam.name)
-                  .addModifiers(PRIVATE, FINAL)
-                  .build())
-          .addMethod(
-              MethodSpec.constructorBuilder()
-                  .addParameter(delegateFactoryParam)
-                  .addStatement("this.$1N = $1N", delegateFactoryParam)
-                  .build())
-          .addMethod(
-              MethodSpec.overriding(metadata.factoryMethod(), metadata.factoryType(), types)
-                  .addStatement(
-                      "return $N.get($L)",
-                      delegateFactoryParam,
-                      // Use the order of the parameters from the @AssistedInject constructor but
-                      // use the parameter names of the @AssistedFactory method.
-                      metadata.assistedInjectAssistedParameters().stream()
-                          .map(metadata.assistedFactoryAssistedParametersMap()::get)
-                          .map(param -> CodeBlock.of("$L", param.getSimpleName()))
-                          .collect(toParametersCodeBlock()))
-                  .build())
-          .addMethod(
-              MethodSpec.methodBuilder("create")
-                  .addModifiers(PUBLIC, STATIC)
-                  .addParameter(delegateFactoryParam)
-                  .addTypeVariables(
-                      metadata.assistedInjectElement().getTypeParameters().stream()
-                          .map(TypeVariableName::get)
-                          .collect(toImmutableList()))
-                  .returns(providerOf(TypeName.get(factory.asType())))
-                  .addStatement(
-                      "return $T.$Lcreate(new $T($N))",
-                      INSTANCE_FACTORY,
-                      // Java 7 type inference requires the method call provide the exact type here.
-                      sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0
-                          ? CodeBlock.of("<$T>", types.accessibleType(metadata.factoryType(), name))
-                          : CodeBlock.of(""),
-                      name,
-                      delegateFactoryParam)
-                  .build());
-      return Optional.of(builder);
-    }
-
-    /** Returns the generated factory {@link TypeName type} for an @AssistedInject constructor. */
-    private TypeName delegateFactoryTypeName(DeclaredType assistedInjectType) {
-      // The name of the generated factory for the assisted inject type,
-      // e.g. an @AssistedInject Foo(...) {...} constructor will generate a Foo_Factory class.
-      ClassName generatedFactoryClassName =
-          generatedClassNameForBinding(
-              bindingFactory.injectionBinding(
-                  getOnlyElement(assistedInjectedConstructors(asTypeElement(assistedInjectType))),
-                  Optional.empty()));
-
-      // Return the factory type resolved with the same type parameters as the assisted inject type.
-      return assistedInjectType.getTypeArguments().isEmpty()
-          ? generatedFactoryClassName
-          : ParameterizedTypeName.get(
-              generatedFactoryClassName,
-              assistedInjectType.getTypeArguments().stream()
-                  .map(TypeName::get)
-                  .collect(toImmutableList())
-                  .toArray(new TypeName[0]));
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/AssistedInjectProcessingStep.java b/java/dagger/internal/codegen/AssistedInjectProcessingStep.java
deleted file mode 100644
index 4f2f5b7..0000000
--- a/java/dagger/internal/codegen/AssistedInjectProcessingStep.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2021 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.common.base.Preconditions.checkState;
-import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import dagger.assisted.AssistedInject;
-import dagger.internal.codegen.binding.AssistedInjectionAnnotations;
-import dagger.internal.codegen.binding.AssistedInjectionAnnotations.AssistedParameter;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
-import dagger.internal.codegen.validation.ValidationReport;
-import java.lang.annotation.Annotation;
-import java.util.HashSet;
-import java.util.Set;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.DeclaredType;
-
-/** An annotation processor for {@link dagger.assisted.AssistedInject}-annotated elements. */
-final class AssistedInjectProcessingStep extends TypeCheckingProcessingStep<ExecutableElement> {
-  private final DaggerTypes types;
-  private final Messager messager;
-
-  @Inject
-  AssistedInjectProcessingStep(DaggerTypes types, Messager messager) {
-    super(MoreElements::asExecutable);
-    this.types = types;
-    this.messager = messager;
-  }
-
-  @Override
-  public ImmutableSet<Class<? extends Annotation>> annotations() {
-    return ImmutableSet.of(AssistedInject.class);
-  }
-
-  @Override
-  protected void process(
-      ExecutableElement assistedInjectElement,
-      ImmutableSet<Class<? extends Annotation>> annotations) {
-    new AssistedInjectValidator().validate(assistedInjectElement).printMessagesTo(messager);
-  }
-
-  private final class AssistedInjectValidator {
-    ValidationReport<ExecutableElement> validate(ExecutableElement constructor) {
-      checkState(constructor.getKind() == ElementKind.CONSTRUCTOR);
-      ValidationReport.Builder<ExecutableElement> report = ValidationReport.about(constructor);
-
-      DeclaredType assistedInjectType =
-          asDeclared(closestEnclosingTypeElement(constructor).asType());
-      ImmutableList<AssistedParameter> assistedParameters =
-          AssistedInjectionAnnotations.assistedInjectAssistedParameters(assistedInjectType, types);
-
-      Set<AssistedParameter> uniqueAssistedParameters = new HashSet<>();
-      for (AssistedParameter assistedParameter : assistedParameters) {
-        if (!uniqueAssistedParameters.add(assistedParameter)) {
-          report.addError(
-              "@AssistedInject constructor has duplicate @Assisted type: " + assistedParameter,
-              assistedParameter.variableElement());
-        }
-      }
-
-      return report.build();
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/AssistedProcessingStep.java b/java/dagger/internal/codegen/AssistedProcessingStep.java
deleted file mode 100644
index 3173987..0000000
--- a/java/dagger/internal/codegen/AssistedProcessingStep.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2020 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.MoreElements.isAnnotationPresent;
-import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSet;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedInject;
-import dagger.internal.codegen.binding.AssistedInjectionAnnotations;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
-import dagger.internal.codegen.validation.ValidationReport;
-import java.lang.annotation.Annotation;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-
-/**
- * An annotation processor for {@link dagger.assisted.Assisted}-annotated types.
- *
- * <p>This processing step should run after {@link AssistedFactoryProcessingStep}.
- */
-final class AssistedProcessingStep extends TypeCheckingProcessingStep<VariableElement> {
-  private final KotlinMetadataUtil kotlinMetadataUtil;
-  private final InjectionAnnotations injectionAnnotations;
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final Messager messager;
-
-  @Inject
-  AssistedProcessingStep(
-      KotlinMetadataUtil kotlinMetadataUtil,
-      InjectionAnnotations injectionAnnotations,
-      DaggerElements elements,
-      DaggerTypes types,
-      Messager messager) {
-    super(MoreElements::asVariable);
-    this.kotlinMetadataUtil = kotlinMetadataUtil;
-    this.injectionAnnotations = injectionAnnotations;
-    this.elements = elements;
-    this.types = types;
-    this.messager = messager;
-  }
-
-  @Override
-  public ImmutableSet<Class<? extends Annotation>> annotations() {
-    return ImmutableSet.of(Assisted.class);
-  }
-
-  @Override
-  protected void process(
-      VariableElement assisted, ImmutableSet<Class<? extends Annotation>> annotations) {
-    new AssistedValidator().validate(assisted).printMessagesTo(messager);
-  }
-
-  private final class AssistedValidator {
-    ValidationReport<VariableElement> validate(VariableElement assisted) {
-      ValidationReport.Builder<VariableElement> report = ValidationReport.about(assisted);
-
-      Element enclosingElement = assisted.getEnclosingElement();
-      if (!isAssistedInjectConstructor(enclosingElement)
-          && !isAssistedFactoryCreateMethod(enclosingElement)
-          // The generated java stubs for kotlin data classes contain a "copy" method that has
-          // the same parameters (and annotations) as the constructor, so just ignore it.
-          && !isKotlinDataClassCopyMethod(enclosingElement)) {
-        report.addError(
-            "@Assisted parameters can only be used within an @AssistedInject-annotated "
-                + "constructor.",
-            assisted);
-      }
-
-      injectionAnnotations
-          .getQualifiers(assisted)
-          .forEach(
-              qualifier ->
-                  report.addError(
-                      "Qualifiers cannot be used with @Assisted parameters.", assisted, qualifier));
-
-      return report.build();
-    }
-  }
-
-  private boolean isAssistedInjectConstructor(Element element) {
-    return element.getKind() == ElementKind.CONSTRUCTOR
-        && isAnnotationPresent(element, AssistedInject.class);
-  }
-
-  private boolean isAssistedFactoryCreateMethod(Element element) {
-    if (element.getKind() == ElementKind.METHOD) {
-      TypeElement enclosingElement = closestEnclosingTypeElement(element);
-      return AssistedInjectionAnnotations.isAssistedFactoryType(enclosingElement)
-          // This assumes we've already validated AssistedFactory and that a valid method exists.
-          && AssistedInjectionAnnotations.assistedFactoryMethod(enclosingElement, elements, types)
-              .equals(element);
-    }
-    return false;
-  }
-
-  private boolean isKotlinDataClassCopyMethod(Element element) {
-    // Note: This is a best effort. Technically, we could check the return type and parameters of
-    // the copy method to verify it's the one associated with the constructor, but I'd rather keep
-    // this simple to avoid encoding too many details of kapt's stubs. At worst, we'll be allowing
-    // an @Assisted annotation that has no affect, which is already true for many of Dagger's other
-    // annotations.
-    return element.getKind() == ElementKind.METHOD
-        && element.getSimpleName().contentEquals("copy")
-        && kotlinMetadataUtil.isDataClass(closestEnclosingTypeElement(element));
-  }
-}
diff --git a/java/dagger/internal/codegen/BUILD b/java/dagger/internal/codegen/BUILD
index be970be..824a72e 100644
--- a/java/dagger/internal/codegen/BUILD
+++ b/java/dagger/internal/codegen/BUILD
@@ -15,106 +15,485 @@
 # Description:
 #   A JSR-330 compliant dependency injection system for android and java
 
-load("@rules_java//java:defs.bzl", "java_library", "java_plugin")
-load(
-    "//:build_defs.bzl",
-    "POM_VERSION",
-)
-load("//tools:maven.bzl", "gen_maven_artifact")
-
 package(default_visibility = ["//:src"])
 
+load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "DOCLINT_REFERENCES")
+load("//tools:maven.bzl", "POM_VERSION", "pom_file")
+
+EXPERIMENTAL_VISUALIZER_SRCS = ["BindingNetworkVisualizer.java"]
+
+JAVAC_PLUGIN_MODULE_SRCS = ["JavacPluginModule.java"]
+
+KYTHE_SRCS = ["DaggerKythePlugin.java"]
+
+STATISTICS_COLLECTOR_SRCS = ["BindingGraphStatisticsCollector.java"]
+
+CODEGEN_SRCS = glob(
+    ["*.java"],
+    exclude = EXPERIMENTAL_VISUALIZER_SRCS + KYTHE_SRCS + STATISTICS_COLLECTOR_SRCS +
+              JAVAC_PLUGIN_MODULE_SRCS,
+)
+
+CODEGEN_PLUGINS = [":bootstrap_compiler_plugin"]
+
+CODEGEN_SHARED_DEPS = [
+    "@google_bazel_common//third_party/java/auto:service",
+    "@google_bazel_common//third_party/java/auto:value",
+    "@google_bazel_common//third_party/java/auto:common",
+    "@google_bazel_common//third_party/java/checker_framework_annotations",
+    "@google_bazel_common//third_party/java/error_prone:annotations",
+    "@google_bazel_common//third_party/java/google_java_format",
+    "@google_bazel_common//third_party/java/javapoet",
+    "@bazel_tools//tools/jdk:langtools-neverlink",
+    "@google_bazel_common//third_party/java/jsr250_annotations",
+    "@google_bazel_common//third_party/java/jsr330_inject",
+    "//java/dagger:core",
+    "//java/dagger/internal/codegen/serialization",
+    "//java/dagger/producers",
+    "//java/dagger/model",
+    "//java/dagger/spi",
+    "//java/dagger/model:internal-proxies",
+]
+
+CODEGEN_DEPS = CODEGEN_SHARED_DEPS + [
+    ":jdk-and-guava-extras",
+    "@google_bazel_common//third_party/java/guava",
+]
+
+# Extra features for the JDK and Guava. This code is merged into both
+# the dagger-compiler and dagger-spi artifacts that are sent to Maven
+java_library(
+    name = "jdk-and-guava-extras",
+    srcs = [
+        "DaggerGraphs.java",
+        "DaggerStreams.java",
+        "Optionals.java",
+    ],
+    plugins = CODEGEN_PLUGINS,
+    tags = ["maven:merged"],
+    deps = [
+        "@google_bazel_common//third_party/java/guava",
+    ],
+)
+
+# Common types needed across all of the codegen package
+java_library(
+    name = "base",
+    srcs = [
+        "AnnotationProtoConverter.java",
+        "ClearableCache.java",
+        "CompilerOptions.java",
+        "ComponentAnnotation.java",
+        "ContributionType.java",
+        "DaggerStatistics.java",
+        "DaggerStatisticsCollectingProcessingStep.java",
+        "DaggerStatisticsCollector.java",
+        "DaggerStatisticsRecorder.java",
+        "DiagnosticFormatting.java",
+        "ElementFormatter.java",
+        "FeatureStatus.java",
+        "Formatter.java",
+        "ForwardingCompilerOptions.java",
+        "FrameworkTypes.java",
+        "InjectionAnnotations.java",
+        "Keys.java",
+        "MapKeyAccessibility.java",
+        "MapType.java",
+        "ModuleAnnotation.java",
+        "MoreAnnotationMirrors.java",
+        "MoreAnnotationValues.java",
+        "MultibindingAnnotations.java",
+        "OptionalType.java",
+        "ProcessingEnvironmentCompilerOptions.java",
+        "ProcessingOptions.java",
+        "RequestKinds.java",
+        "Scopes.java",
+        "SetType.java",
+        "SimpleAnnotationMirror.java",
+        "SimpleTypeAnnotationValue.java",
+        "SourceFileGenerationException.java",  # Used in :writing and :processor
+        "SourceFileGenerator.java",  # Needed by InjectBindingRegistry in :binding and also :writing
+        "TypeCheckingProcessingStep.java",
+        "TypeProtoConverter.java",
+        "UniqueNameSet.java",
+        "Util.java",
+        "ValidationType.java",
+        "package-info.java",
+    ],
+    plugins = CODEGEN_PLUGINS,
+    tags = ["maven:merged"],
+    deps = CODEGEN_DEPS + [
+        "//java/dagger/internal/codegen/javapoet",
+        "//java/dagger/internal/codegen/langmodel",
+    ],
+)
+
+# Classes that help to build a model of the binding graph
+java_library(
+    name = "binding",
+    srcs = [
+        "AnnotationExpression.java",
+        "Binding.java",
+        "BindingDeclaration.java",
+        "BindingDeclarationFormatter.java",
+        "BindingFactory.java",
+        "BindingGraph.java",
+        "BindingGraphConverter.java",
+        "BindingGraphFactory.java",
+        "BindingNode.java",
+        "BindingRequest.java",
+        "BindingType.java",
+        "BindsTypeChecker.java",
+        "ChildFactoryMethodEdgeImpl.java",
+        "ComponentCreatorAnnotation.java",
+        "ComponentCreatorDescriptor.java",
+        "ComponentCreatorKind.java",
+        "ComponentDescriptor.java",
+        "ComponentDescriptorFactory.java",
+        "ComponentKind.java",
+        "ComponentNodeImpl.java",
+        "ComponentRequirement.java",
+        "ComponentTreeTraverser.java",
+        "ConfigurationAnnotations.java",  # Uses ModuleDescriptors
+        "ContributionBinding.java",
+        "DelegateDeclaration.java",
+        "DependencyEdgeImpl.java",
+        "DependencyRequestFactory.java",
+        "DependencyRequestFormatter.java",
+        "DependencyVariableNamer.java",  # Used by SourceFiles
+        "ErrorMessages.java",  # Consider splitting this up as it pulls in too much
+        "FrameworkDependency.java",
+        "FrameworkField.java",  # Used by SourceFiles
+        "FrameworkType.java",
+        "FrameworkTypeMapper.java",
+        "InjectBindingRegistry.java",
+        "InjectionSiteFactory.java",
+        "KeyFactory.java",
+        "KeyVariableNamer.java",  # needs ConfigurationAnnotations, SourceFiles
+        "MapKeys.java",
+        "MembersInjectionBinding.java",
+        "MethodSignature.java",
+        "MethodSignatureFormatter.java",
+        "ModuleDescriptor.java",
+        "ModuleKind.java",
+        "MultibindingDeclaration.java",
+        "OptionalBindingDeclaration.java",
+        "ProductionBinding.java",
+        "ProvisionBinding.java",
+        "ResolvedBindings.java",
+        "SourceFiles.java",  # Consider splitting this up?
+        "SubcomponentCreatorBindingEdgeImpl.java",
+        "SubcomponentDeclaration.java",
+    ],
+    plugins = CODEGEN_PLUGINS,
+    tags = ["maven:merged"],
+    deps = CODEGEN_DEPS + [
+        ":base",
+        "//java/dagger/internal/codegen/langmodel",
+        "//java/dagger/internal/codegen/javapoet",
+    ],
+)
+
+# Code related to validating the user-written Dagger code
+java_library(
+    name = "validation",
+    srcs = [
+        "AnyBindingMethodValidator.java",
+        "BindingElementValidator.java",
+        "BindingGraphPlugins.java",
+        "BindingGraphValidator.java",
+        "BindingMethodProcessingStep.java",
+        "BindingMethodValidator.java",
+        "BindsInstanceElementValidator.java",
+        "BindsInstanceMethodValidator.java",
+        "BindsInstanceParameterValidator.java",
+        "BindsInstanceProcessingStep.java",
+        "BindsMethodValidator.java",
+        "BindsOptionalOfMethodValidator.java",
+        "ComponentCreatorValidator.java",
+        "ComponentDescriptorValidator.java",
+        "ComponentHierarchyValidator.java",
+        "ComponentValidator.java",
+        "DependencyRequestValidator.java",
+        "DiagnosticReporterFactory.java",
+        "InjectValidator.java",
+        "MapKeyValidator.java",
+        "MembersInjectionValidator.java",
+        "ModuleValidator.java",
+        "MultibindingAnnotationsProcessingStep.java",
+        "MultibindsMethodValidator.java",
+        "ProducesMethodValidator.java",
+        "ProvidesMethodValidator.java",
+        "Validation.java",
+        "ValidationReport.java",
+    ],
+    plugins = CODEGEN_PLUGINS,
+    tags = ["maven:merged"],
+    deps = CODEGEN_DEPS + [
+        ":base",
+        ":binding",
+        "//java/dagger/internal/codegen/langmodel",
+    ],
+)
+
+java_library(
+    name = "binding_graph_validation",
+    srcs = [
+        "DependencyCycleValidator.java",
+        "DependsOnProductionExecutorValidator.java",
+        "DuplicateBindingsValidator.java",
+        "IncompatiblyScopedBindingsValidator.java",
+        "InjectBindingValidator.java",
+        "MapMultibindingValidator.java",
+        "MissingBindingValidator.java",
+        "NullableBindingValidator.java",
+        "ProvisionDependencyOnProducerBindingValidator.java",
+        "SubcomponentFactoryMethodValidator.java",
+    ],
+    plugins = CODEGEN_PLUGINS,
+    tags = ["maven:merged"],
+    deps = CODEGEN_DEPS + [
+        ":base",
+        ":binding",
+        ":validation",
+        "//java/dagger/internal/codegen/langmodel",
+    ],
+)
+
+# Classes that assemble the model of the generated code and write to the Filer
+java_library(
+    name = "writing",
+    srcs = [
+        "AnnotationCreatorGenerator.java",
+        "AnonymousProviderCreationExpression.java",
+        "BindingExpression.java",
+        "ComponentBindingExpressions.java",
+        "ComponentCreatorImplementation.java",
+        "ComponentImplementation.java",
+        "ComponentInstanceBindingExpression.java",
+        "ComponentMethodBindingExpression.java",
+        "ComponentProvisionBindingExpression.java",
+        "ComponentRequirementBindingExpression.java",
+        "ComponentRequirementExpression.java",
+        "ComponentRequirementExpressions.java",
+        "DeferredModifiableBindingExpression.java",
+        "DelegateBindingExpression.java",
+        "DelegatingFrameworkInstanceCreationExpression.java",
+        "DependencyMethodProducerCreationExpression.java",
+        "DependencyMethodProviderCreationExpression.java",
+        "DerivedFromFrameworkInstanceBindingExpression.java",
+        "FactoryGenerator.java",
+        "FrameworkFieldInitializer.java",
+        "FrameworkInstanceBindingExpression.java",
+        "FrameworkInstanceSupplier.java",
+        "GenerationCompilerOptions.java",
+        "GwtCompatibility.java",
+        "HjarSourceFileGenerator.java",
+        "ImmediateFutureBindingExpression.java",
+        "InaccessibleMapKeyProxyGenerator.java",
+        "InjectionMethod.java",
+        "InjectionMethods.java",
+        "InjectionOrProvisionProviderCreationExpression.java",
+        "InnerSwitchingProviders.java",
+        "InstanceFactoryCreationExpression.java",
+        "MapBindingExpression.java",
+        "MapFactoryCreationExpression.java",
+        "MemberSelect.java",
+        "MembersInjectionBindingExpression.java",
+        "MembersInjectionMethods.java",
+        "MembersInjectorGenerator.java",
+        "MembersInjectorProviderCreationExpression.java",
+        "MethodBindingExpression.java",
+        "MissingBindingExpression.java",
+        "ModifiableAbstractMethodBindingExpression.java",
+        "ModifiableBindingExpressions.java",
+        "ModifiableBindingMethods.java",
+        "ModifiableBindingType.java",
+        "ModifiableConcreteMethodBindingExpression.java",
+        "ModuleConstructorProxyGenerator.java",
+        "ModuleGenerator.java",
+        "ModuleProxies.java",
+        "MonitoringModuleGenerator.java",
+        "MonitoringModuleProcessingStep.java",
+        "MultibindingExpression.java",
+        "MultibindingFactoryCreationExpression.java",
+        "OptionalBindingExpression.java",
+        "OptionalFactories.java",
+        "OptionalFactoryInstanceCreationExpression.java",
+        "ParentComponent.java",
+        "PerComponentImplementation.java",
+        "PerGeneratedFile.java",
+        "PrivateMethodBindingExpression.java",
+        "ProducerCreationExpression.java",
+        "ProducerEntryPointView.java",
+        "ProducerFactoryGenerator.java",
+        "ProducerFromProviderCreationExpression.java",
+        "ProducerNodeInstanceBindingExpression.java",
+        "ProviderInstanceBindingExpression.java",
+        "PrunedConcreteMethodBindingExpression.java",
+        "SetBindingExpression.java",
+        "SetFactoryCreationExpression.java",
+        "SimpleInvocationBindingExpression.java",
+        "SimpleMethodBindingExpression.java",
+        "SubcomponentCreatorBindingExpression.java",
+        "SubcomponentNames.java",
+        "SwitchingProviders.java",
+        "TopLevel.java",
+        "UnwrappedMapKeyGenerator.java",
+    ],
+    plugins = CODEGEN_PLUGINS,
+    tags = ["maven:merged"],
+    deps = CODEGEN_DEPS + [
+        ":base",
+        ":binding",
+        "//java/dagger/internal/codegen/javapoet",
+        "//java/dagger/internal/codegen/langmodel",
+    ],
+)
+
+# The processor's "main", if you will
 java_library(
     name = "processor",
-    srcs = glob(
-        ["*.java"],
-        exclude = ["package-info.java"],
-    ),
-    plugins = [
-        "//java/dagger/internal/codegen/bootstrap",
+    srcs = [
+        "BindingGraphValidationModule.java",
+        "BindingMethodValidatorsModule.java",
+        "ComponentCreatorImplementationFactory.java",
+        "ComponentGenerator.java",
+        "ComponentHjarProcessingStep.java",
+        "ComponentImplementationBuilder.java",
+        "ComponentImplementationFactory.java",
+        "ComponentProcessingStep.java",
+        "ComponentProcessor.java",
+        "CurrentImplementationSubcomponent.java",
+        "DeserializedComponentImplementationBuilder.java",
+        "GenerationOptionsModule.java",
+        "InjectBindingRegistryImpl.java",
+        "InjectBindingRegistryModule.java",
+        "InjectProcessingStep.java",
+        "MapKeyProcessingStep.java",
+        "ModuleProcessingStep.java",
+        "ProcessingEnvironmentModule.java",
+        "ProcessingRoundCacheModule.java",
+        "SourceFileGeneratorsModule.java",
+        "SpiModule.java",
+        "SystemComponentsModule.java",
+        "TopLevelImplementationComponent.java",
     ],
+    plugins = CODEGEN_PLUGINS,
     tags = ["maven_coordinates=com.google.dagger:dagger-compiler:" + POM_VERSION],
-    exports = [
-        "@google_bazel_common//third_party/java/jsr250_annotations",  # Export for @Generated
-    ],
-    deps = [
-        ":package_info",
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/bindinggraphvalidation",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/componentgenerator",
-        "//java/dagger/internal/codegen/extension",
+    deps = CODEGEN_DEPS + [
+        ":base",
+        ":binding",
+        ":binding_graph_validation",
+        ":writing",
+        ":validation",
         "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
         "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/codegen/validation",
-        "//java/dagger/internal/codegen/writing",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@google_bazel_common//third_party/java/google_java_format",
         "@google_bazel_common//third_party/java/incap",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
+    ],
+)
+
+pom_file(
+    name = "pom",
+    artifact_id = "dagger-compiler",
+    artifact_name = "Dagger Compiler",
+    targets = [
+        ":processor",
+        ":base",
+        ":binding",
+        ":binding_graph_validation",
+        ":writing",
+        ":validation",
+        "//java/dagger/internal/codegen/serialization",
+        "//java/dagger/internal/codegen/javapoet",
     ],
 )
 
 java_library(
-    name = "package_info",
-    srcs = ["package-info.java"],
-    tags = ["maven:merged"],
-    deps = ["@google_bazel_common//third_party/java/error_prone:annotations"],
+    name = "javac-plugin-module",
+    srcs = JAVAC_PLUGIN_MODULE_SRCS,
+    plugins = [":component-codegen"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":base",
+        ":binding",
+        ":javac",
+        ":processor",
+        "//java/dagger:core",
+        "//java/dagger/internal/codegen/langmodel",
+    ],
 )
 
-gen_maven_artifact(
-    name = "artifact",
-    artifact_coordinates = "com.google.dagger:dagger-compiler:" + POM_VERSION,
-    artifact_name = "Dagger Compiler",
-    artifact_target = ":processor",
-    artifact_target_libs = [
-        ":package_info",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/base:shared",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/bindinggraphvalidation",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/componentgenerator",
-        "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
+java_library(
+    name = "kythe",
+    srcs = KYTHE_SRCS,
+    plugins = [":component-codegen"],
+    deps = [
+        ":base",
+        ":binding",
+        ":javac",
+        ":javac-plugin-module",
+        ":kythe_plugin",
+        ":processor",
+        "//java/dagger:core",
         "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/codegen/validation",
-        "//java/dagger/internal/codegen/writing",
-        "//java/dagger/model:internal-proxies",
+        "//java/dagger/model",
+        "//java/dagger/producers",
+        "@google_bazel_common//third_party/java/auto:common",
+        "@google_bazel_common//third_party/java/auto:service",
+        "@google_bazel_common//third_party/java/guava",
     ],
-    artifact_target_maven_deps = [
-        "com.google.auto:auto-common",
-        "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger-producers",
-        "com.google.dagger:dagger-spi",
-        "com.google.dagger:dagger",
-        "com.google.googlejavaformat:google-java-format",
-        "com.google.guava:failureaccess",
-        "com.google.guava:guava",
-        "com.squareup:javapoet",
-        "javax.annotation:jsr250-api",
-        "javax.inject:javax.inject",
-        "net.ltgt.gradle.incap:incap",
-        "org.checkerframework:checker-compat-qual",
-        "org.jetbrains.kotlin:kotlin-stdlib",
-        "org.jetbrains.kotlinx:kotlinx-metadata-jvm",
+)
+
+# Replacement for @bazel_tools//third_party/java/jdk/langtools:javac, which seems to have gone away?
+java_import(
+    name = "javac",
+    jars = ["@bazel_tools//third_party/java/jdk/langtools:javac_jar"],
+)
+
+# A _deploy.jar consisting of the java_librarys in https://github.com/kythe/kythe needed to build a
+# Kythe plugin
+# TODO(ronshapiro): replace this with a http_archive of the next release in
+# https://github.com/kythe/kythe/releases
+java_import(
+    name = "kythe_plugin",
+    jars = ["kythe_plugin_deploy.jar"],
+    neverlink = 1,
+)
+
+java_import(
+    name = "bootstrap_compiler",
+    jars = ["bootstrap_compiler_deploy.jar"],
+    visibility = ["//visibility:private"],
+)
+
+java_plugin(
+    name = "bootstrap_compiler_plugin",
+    generates_api = 1,
+    processor_class = "dagger.internal.codegen.ComponentProcessor",
+    deps = [":bootstrap_compiler"],
+)
+
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+
+javadoc_library(
+    name = "codegen-javadoc",
+    srcs = CODEGEN_SRCS,
+    root_packages = ["dagger.internal.codegen"],
+    deps = [":processor"],
+)
+
+java_library(
+    name = "check-package-javadoc",
+    testonly = 1,
+    srcs = CODEGEN_SRCS,
+    javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
+    plugins = CODEGEN_PLUGINS,
+    deps = CODEGEN_DEPS + [
+        "//java/dagger/internal/codegen/langmodel",
+        "//java/dagger/internal/codegen/javapoet",
+        "@google_bazel_common//third_party/java/incap",
     ],
-    javadoc_root_packages = ["dagger.internal.codegen"],
-    # The javadocs should only include ComponentProcessor.java, since that is the only class used
-    # externally. Specifically, ComponentProcessor.forTesting() is required for testing SPI plugins.
-    javadoc_srcs = ["ComponentProcessor.java"],
-    shaded_deps = ["@maven//:com_google_auto_auto_common"],
-    shaded_rules = ["rule com.google.auto.common.** dagger.shaded.auto.common.@1"],
 )
 
 java_plugin(
@@ -130,3 +509,19 @@
     ],
     deps = [":processor"],
 )
+
+java_library(
+    name = "statistics",
+    srcs = STATISTICS_COLLECTOR_SRCS,
+    plugins = [":component-codegen"],
+    deps = [
+        ":base",
+        ":binding",
+        ":javac",
+        ":javac-plugin-module",
+        ":processor",
+        "//java/dagger:core",
+        "//java/dagger/model",
+        "@google_bazel_common//third_party/java/error_prone:check_api",
+    ],
+)
diff --git a/java/dagger/internal/codegen/Binding.java b/java/dagger/internal/codegen/Binding.java
new file mode 100644
index 0000000..c0f6b71
--- /dev/null
+++ b/java/dagger/internal/codegen/Binding.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2014 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.common.base.Suppliers.memoize;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static java.util.stream.Collectors.toSet;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.Sets;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.BindingKind;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.Scope;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleTypeVisitor6;
+
+/**
+ * An abstract type for classes representing a Dagger binding. Particularly, contains the {@link
+ * Element} that generated the binding and the {@link DependencyRequest} instances that are required
+ * to satisfy the binding, but leaves the specifics of the <i>mechanism</i> of the binding to the
+ * subtypes.
+ */
+abstract class Binding extends BindingDeclaration {
+
+  /**
+   * Returns {@code true} if using this binding requires an instance of the {@link
+   * #contributingModule()}.
+   */
+  boolean requiresModuleInstance() {
+    if (!bindingElement().isPresent() || !contributingModule().isPresent()) {
+      return false;
+    }
+    Set<Modifier> modifiers = bindingElement().get().getModifiers();
+    return !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC);
+  }
+
+  /**
+   * Returns {@code true} if this binding may provide {@code null} instead of an instance of {@link
+   * #key()}. Nullable bindings cannot be requested from {@linkplain DependencyRequest#isNullable()
+   * non-nullable dependency requests}.
+   */
+  abstract boolean isNullable();
+
+  /** The kind of binding this instance represents. */
+  abstract BindingKind kind();
+
+  /** The {@link BindingType} of this binding. */
+  abstract BindingType bindingType();
+
+  /** The {@link FrameworkType} of this binding. */
+  final FrameworkType frameworkType() {
+    return FrameworkType.forBindingType(bindingType());
+  }
+
+  /**
+   * The explicit set of {@link DependencyRequest dependencies} required to satisfy this binding as
+   * defined by the user-defined injection sites.
+   */
+  abstract ImmutableSet<DependencyRequest> explicitDependencies();
+
+  /**
+   * The set of {@link DependencyRequest dependencies} that are added by the framework rather than a
+   * user-defined injection site. This returns an unmodifiable set.
+   */
+  // TODO(gak): this will eventually get changed to return a set of FrameworkDependency
+  ImmutableSet<DependencyRequest> implicitDependencies() {
+    return ImmutableSet.of();
+  }
+
+  private final Supplier<ImmutableSet<DependencyRequest>> dependencies =
+      memoize(
+          () -> {
+            ImmutableSet<DependencyRequest> implicitDependencies = implicitDependencies();
+            return ImmutableSet.copyOf(
+                implicitDependencies.isEmpty()
+                    ? explicitDependencies()
+                    : Sets.union(implicitDependencies, explicitDependencies()));
+          });
+
+  /**
+   * The set of {@link DependencyRequest dependencies} required to satisfy this binding. This is the
+   * union of {@link #explicitDependencies()} and {@link #implicitDependencies()}. This returns an
+   * unmodifiable set.
+   */
+  final ImmutableSet<DependencyRequest> dependencies() {
+    return dependencies.get();
+  }
+
+  private final Supplier<ImmutableList<FrameworkDependency>> frameworkDependencies =
+      memoize(
+          () ->
+              dependencyAssociations()
+                  .stream()
+                  .map(DependencyAssociation::frameworkDependency)
+                  .collect(toImmutableList()));
+
+  /**
+   * The framework dependencies of {@code binding}. There will be one element for each different
+   * binding key in the <em>{@linkplain Binding#unresolved() unresolved}</em> version of {@code
+   * binding}.
+   *
+   * <p>For example, given the following modules:
+   *
+   * <pre><code>
+   *   {@literal @Module} abstract class {@literal BaseModule<T>} {
+   *     {@literal @Provides} Foo provideFoo(T t, String string) {
+   *       return …;
+   *     }
+   *   }
+   *
+   *   {@literal @Module} class StringModule extends {@literal BaseModule<String>} {}
+   * </code></pre>
+   *
+   * Both dependencies of {@code StringModule.provideFoo} have the same binding key: {@code String}.
+   * But there are still two dependencies, because in the unresolved binding they have different
+   * binding keys:
+   *
+   * <dl>
+   *   <dt>{@code T}
+   *   <dd>{@code String t}
+   *   <dt>{@code String}
+   *   <dd>{@code String string}
+   * </dl>
+   *
+   * <p>Note that the sets returned by this method when called on the same binding will be equal,
+   * and their elements will be in the same order.
+   */
+  /* TODO(dpb): The stable-order postcondition is actually hard to verify in code for two equal
+   * instances of Binding, because it really depends on the order of the binding's dependencies,
+   * and two equal instances of Binding may have the same dependencies in a different order. */
+  final ImmutableList<FrameworkDependency> frameworkDependencies() {
+    return frameworkDependencies.get();
+  }
+
+  /**
+   * Associates a {@link FrameworkDependency} with the set of {@link DependencyRequest} instances
+   * that correlate for a binding.
+   */
+  @AutoValue
+  abstract static class DependencyAssociation {
+    abstract FrameworkDependency frameworkDependency();
+
+    abstract ImmutableSet<DependencyRequest> dependencyRequests();
+
+    static DependencyAssociation create(
+        FrameworkDependency frameworkDependency, Iterable<DependencyRequest> dependencyRequests) {
+      return new AutoValue_Binding_DependencyAssociation(
+          frameworkDependency, ImmutableSet.copyOf(dependencyRequests));
+    }
+  }
+
+  private final Supplier<ImmutableList<DependencyAssociation>> dependencyAssociations =
+      memoize(
+          () -> {
+            FrameworkTypeMapper frameworkTypeMapper =
+                FrameworkTypeMapper.forBindingType(bindingType());
+            ImmutableList.Builder<DependencyAssociation> list = ImmutableList.builder();
+            for (Set<DependencyRequest> requests : groupByUnresolvedKey()) {
+              list.add(
+                  DependencyAssociation.create(
+                      FrameworkDependency.create(
+                          getOnlyElement(
+                              requests.stream().map(DependencyRequest::key).collect(toSet())),
+                          frameworkTypeMapper.getFrameworkType(requests)),
+                      requests));
+            }
+            return list.build();
+          });
+
+  /**
+   * Returns the same {@link FrameworkDependency} instances from {@link #frameworkDependencies}, but
+   * with the set of {@link DependencyRequest} instances with which each is associated.
+   *
+   * <p>Ths method returns a list of {@link Map.Entry entries} rather than a {@link Map} or {@link
+   * com.google.common.collect.Multimap} because any given {@link FrameworkDependency} may appear
+   * multiple times if the {@linkplain Binding#unresolved() unresolved} binding requires it. If that
+   * distinction is not important, the entries can be merged into a single mapping.
+   */
+  final ImmutableList<DependencyAssociation> dependencyAssociations() {
+    return dependencyAssociations.get();
+  }
+
+  private final Supplier<ImmutableMap<DependencyRequest, FrameworkDependency>>
+      frameworkDependenciesMap =
+          memoize(
+              () -> {
+                ImmutableMap.Builder<DependencyRequest, FrameworkDependency> frameworkDependencies =
+                    ImmutableMap.builder();
+                for (DependencyAssociation dependencyAssociation : dependencyAssociations()) {
+                  for (DependencyRequest dependencyRequest :
+                      dependencyAssociation.dependencyRequests()) {
+                    frameworkDependencies.put(
+                        dependencyRequest, dependencyAssociation.frameworkDependency());
+                  }
+                }
+                return frameworkDependencies.build();
+              });
+
+  /**
+   * Returns the mapping from each {@linkplain #dependencies dependency} to its associated {@link
+   * FrameworkDependency}.
+   */
+  final ImmutableMap<DependencyRequest, FrameworkDependency>
+      dependenciesToFrameworkDependenciesMap() {
+    return frameworkDependenciesMap.get();
+  }
+
+  /**
+   * Groups {@code binding}'s implicit dependencies by their binding key, using the dependency keys
+   * from the {@link Binding#unresolved()} binding if it exists.
+   */
+  private ImmutableList<Set<DependencyRequest>> groupByUnresolvedKey() {
+    ImmutableSetMultimap.Builder<Key, DependencyRequest> dependenciesByKeyBuilder =
+        ImmutableSetMultimap.builder();
+    Iterator<DependencyRequest> dependencies = dependencies().iterator();
+    Binding unresolved = unresolved().isPresent() ? unresolved().get() : this;
+    Iterator<DependencyRequest> unresolvedDependencies = unresolved.dependencies().iterator();
+    while (dependencies.hasNext()) {
+      dependenciesByKeyBuilder.put(unresolvedDependencies.next().key(), dependencies.next());
+    }
+    return ImmutableList.copyOf(
+        Multimaps.asMap(
+                dependenciesByKeyBuilder.orderValuesBy(SourceFiles.DEPENDENCY_ORDERING).build())
+            .values());
+  }
+
+  /**
+   * If this binding's key's type parameters are different from those of the
+   * {@link #bindingTypeElement()}, this is the binding for the {@link #bindingTypeElement()}'s
+   * unresolved type.
+   */
+  abstract Optional<? extends Binding> unresolved();
+
+  Optional<Scope> scope() {
+    return Optional.empty();
+  }
+
+  // TODO(sameb): Remove the TypeElement parameter and pull it from the TypeMirror.
+  static boolean hasNonDefaultTypeParameters(
+      TypeElement element, TypeMirror type, DaggerTypes types) {
+    // If the element has no type parameters, nothing can be wrong.
+    if (element.getTypeParameters().isEmpty()) {
+      return false;
+    }
+
+    List<TypeMirror> defaultTypes = Lists.newArrayList();
+    for (TypeParameterElement parameter : element.getTypeParameters()) {
+      defaultTypes.add(parameter.asType());
+    }
+
+    List<TypeMirror> actualTypes =
+        type.accept(
+            new SimpleTypeVisitor6<List<TypeMirror>, Void>() {
+              @Override
+              protected List<TypeMirror> defaultAction(TypeMirror e, Void p) {
+                return ImmutableList.of();
+              }
+
+              @Override
+              public List<TypeMirror> visitDeclared(DeclaredType t, Void p) {
+                return ImmutableList.<TypeMirror>copyOf(t.getTypeArguments());
+              }
+            },
+            null);
+
+    // The actual type parameter size can be different if the user is using a raw type.
+    if (defaultTypes.size() != actualTypes.size()) {
+      return true;
+    }
+
+    for (int i = 0; i < defaultTypes.size(); i++) {
+      if (!types.isSameType(defaultTypes.get(i), actualTypes.get(i))) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingDeclaration.java b/java/dagger/internal/codegen/BindingDeclaration.java
new file mode 100644
index 0000000..c9520cd
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingDeclaration.java
@@ -0,0 +1,62 @@
+/*
+ * 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 dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.model.BindingKind;
+import dagger.model.Key;
+import java.util.Optional;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/** An object that declares or specifies a binding. */
+abstract class BindingDeclaration {
+
+  /** The {@link Key} of this declaration. */
+  abstract Key key();
+
+  /**
+   * The {@link Element} that declares this binding. Absent for {@linkplain BindingKind binding
+   * kinds} that are not always declared by exactly one element.
+   *
+   * <p>For example, consider {@link BindingKind#MULTIBOUND_SET}. A component with many
+   * {@code @IntoSet} bindings for the same key will have a synthetic binding that depends on all
+   * contributions, but with no identifiying binding element. A {@code @Multibinds} method will also
+   * contribute a synthetic binding, but since multiple {@code @Multibinds} methods can coexist in
+   * the same component (and contribute to one single binding), it has no binding element.
+   */
+  // TODO(ronshapiro): examine whether this wildcard+bound have any benefit.
+  // We never actually refer to the overridden bindingElement methods directly in a way which needs
+  // anything more than an Element. Removing the wildcard would allow for simpler user-written code
+  // when the binding element is passed to a method.
+  abstract Optional<Element> bindingElement();
+
+  /**
+   * The type enclosing the {@link #bindingElement()}, or {@link Optional#empty()} if {@link
+   * #bindingElement()} is empty.
+   */
+  final Optional<TypeElement> bindingTypeElement() {
+    return bindingElement().map(DaggerElements::closestEnclosingTypeElement);
+  }
+  
+  /**
+   * The installed module class that contributed the {@link #bindingElement()}. May be a subclass of
+   * the class that contains {@link #bindingElement()}. Absent if {@link #bindingElement()} is
+   * empty.
+   */
+  abstract Optional<TypeElement> contributingModule();
+}
diff --git a/java/dagger/internal/codegen/BindingDeclarationFormatter.java b/java/dagger/internal/codegen/BindingDeclarationFormatter.java
new file mode 100644
index 0000000..d850165
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingDeclarationFormatter.java
@@ -0,0 +1,124 @@
+/*
+ * 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.common.collect.Sets.immutableEnumSet;
+import static dagger.internal.codegen.DiagnosticFormatting.stripCommonTypePrefixes;
+import static dagger.internal.codegen.ElementFormatter.elementToString;
+import static javax.lang.model.element.ElementKind.PARAMETER;
+import static javax.lang.model.type.TypeKind.DECLARED;
+import static javax.lang.model.type.TypeKind.EXECUTABLE;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+
+/**
+ * Formats a {@link BindingDeclaration} into a {@link String} suitable for use in error messages.
+ */
+final class BindingDeclarationFormatter extends Formatter<BindingDeclaration> {
+  private static final ImmutableSet<TypeKind> FORMATTABLE_ELEMENT_TYPE_KINDS =
+      immutableEnumSet(EXECUTABLE, DECLARED);
+
+  private final MethodSignatureFormatter methodSignatureFormatter;
+
+  @Inject
+  BindingDeclarationFormatter(MethodSignatureFormatter methodSignatureFormatter) {
+    this.methodSignatureFormatter = methodSignatureFormatter;
+  }
+
+  /**
+   * Returns {@code true} for declarations that this formatter can format. Specifically bindings
+   * from subcomponent declarations or those with {@linkplain BindingDeclaration#bindingElement()
+   * binding elements} that are methods, constructors, or types.
+   */
+  boolean canFormat(BindingDeclaration bindingDeclaration) {
+    if (bindingDeclaration instanceof SubcomponentDeclaration) {
+      return true;
+    }
+    if (bindingDeclaration.bindingElement().isPresent()) {
+      Element bindingElement = bindingDeclaration.bindingElement().get();
+      return bindingElement.getKind().equals(PARAMETER)
+          || FORMATTABLE_ELEMENT_TYPE_KINDS.contains(bindingElement.asType().getKind());
+    }
+    // TODO(dpb): validate whether what this is doing is correct
+    return false;
+  }
+
+  @Override
+  public String format(BindingDeclaration bindingDeclaration) {
+    if (bindingDeclaration instanceof SubcomponentDeclaration) {
+      return formatSubcomponentDeclaration((SubcomponentDeclaration) bindingDeclaration);
+    }
+
+    if (bindingDeclaration.bindingElement().isPresent()) {
+      Element bindingElement = bindingDeclaration.bindingElement().get();
+      if (bindingElement.getKind().equals(PARAMETER)) {
+        return elementToString(bindingElement);
+      }
+
+      switch (bindingElement.asType().getKind()) {
+        case EXECUTABLE:
+          return methodSignatureFormatter.format(
+              MoreElements.asExecutable(bindingElement),
+              bindingDeclaration
+                  .contributingModule()
+                  .map(module -> MoreTypes.asDeclared(module.asType())));
+
+        case DECLARED:
+          return stripCommonTypePrefixes(bindingElement.asType().toString());
+
+        default:
+          throw new IllegalArgumentException(
+              "Formatting unsupported for element: " + bindingElement);
+      }
+    }
+
+    return String.format(
+        "Dagger-generated binding for %s",
+        stripCommonTypePrefixes(bindingDeclaration.key().toString()));
+  }
+
+  private String formatSubcomponentDeclaration(SubcomponentDeclaration subcomponentDeclaration) {
+    ImmutableList<TypeElement> moduleSubcomponents =
+        subcomponentDeclaration.moduleAnnotation().subcomponents();
+    int index = moduleSubcomponents.indexOf(subcomponentDeclaration.subcomponentType());
+    StringBuilder annotationValue = new StringBuilder();
+    if (moduleSubcomponents.size() != 1) {
+      annotationValue.append("{");
+    }
+    annotationValue.append(
+        formatArgumentInList(
+            index,
+            moduleSubcomponents.size(),
+            subcomponentDeclaration.subcomponentType().getQualifiedName() + ".class"));
+    if (moduleSubcomponents.size() != 1) {
+      annotationValue.append("}");
+    }
+
+    return String.format(
+        "@%s(subcomponents = %s) for %s",
+        subcomponentDeclaration.moduleAnnotation().annotationClass().getSimpleName(),
+        annotationValue,
+        subcomponentDeclaration.contributingModule().get());
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingElementValidator.java b/java/dagger/internal/codegen/BindingElementValidator.java
new file mode 100644
index 0000000..0051912
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingElementValidator.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2016 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.common.base.Verify.verifyNotNull;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifiers;
+import static dagger.internal.codegen.MapKeys.getMapKeys;
+import static dagger.internal.codegen.Scopes.scopesOf;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
+import static javax.lang.model.type.TypeKind.ARRAY;
+import static javax.lang.model.type.TypeKind.DECLARED;
+import static javax.lang.model.type.TypeKind.TYPEVAR;
+import static javax.lang.model.type.TypeKind.VOID;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.errorprone.annotations.FormatMethod;
+import dagger.MapKey;
+import dagger.Provides;
+import dagger.model.Key;
+import dagger.model.Scope;
+import dagger.multibindings.ElementsIntoSet;
+import dagger.multibindings.IntoMap;
+import dagger.producers.Produces;
+import java.lang.annotation.Annotation;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.inject.Qualifier;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+/** A validator for elements that represent binding declarations. */
+abstract class BindingElementValidator<E extends Element> {
+  private final Class<? extends Annotation> bindingAnnotation;
+  private final AllowsMultibindings allowsMultibindings;
+  private final AllowsScoping allowsScoping;
+  private final Map<E, ValidationReport<E>> cache = new HashMap<>();
+
+  /**
+   * Creates a validator object.
+   *
+   * @param bindingAnnotation the annotation on an element that identifies it as a binding element
+   */
+  protected BindingElementValidator(
+      Class<? extends Annotation> bindingAnnotation,
+      AllowsMultibindings allowsMultibindings,
+      AllowsScoping allowsScoping) {
+    this.bindingAnnotation = bindingAnnotation;
+    this.allowsMultibindings = allowsMultibindings;
+    this.allowsScoping = allowsScoping;
+  }
+
+  /** Returns a {@link ValidationReport} for {@code element}. */
+  final ValidationReport<E> validate(E element) {
+    return reentrantComputeIfAbsent(cache, element, this::validateUncached);
+  }
+
+  private ValidationReport<E> validateUncached(E element) {
+    return elementValidator(element).validate();
+  }
+
+  /**
+   * Returns an error message of the form "&lt;{@link #bindingElements()}&gt; <i>rule</i>", where
+   * <i>rule</i> comes from calling {@link String#format(String, Object...)} on {@code ruleFormat}
+   * and the other arguments.
+   */
+  @FormatMethod
+  protected final String bindingElements(String ruleFormat, Object... args) {
+    return new Formatter().format("%s ", bindingElements()).format(ruleFormat, args).toString();
+  }
+
+  /**
+   * The kind of elements that this validator validates. Should be plural. Used for error reporting.
+   */
+  protected abstract String bindingElements();
+
+  /** The verb describing the {@link ElementValidator#bindingElementType()} in error messages. */
+  // TODO(ronshapiro,dpb): improve the name of this method and it's documentation.
+  protected abstract String bindingElementTypeVerb();
+
+  /** The error message when a binding element has a bad type. */
+  protected String badTypeMessage() {
+    return bindingElements(
+        "must %s a primitive, an array, a type variable, or a declared type",
+        bindingElementTypeVerb());
+  }
+
+  /**
+   * The error message when a the type for a binding element with {@link
+   * ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} is a not set type.
+   */
+  protected String elementsIntoSetNotASetMessage() {
+    return bindingElements(
+        "annotated with @ElementsIntoSet must %s a Set", bindingElementTypeVerb());
+  }
+
+  /**
+   * The error message when a the type for a binding element with {@link
+   * ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} is a raw set.
+   */
+  protected String elementsIntoSetRawSetMessage() {
+    return bindingElements(
+        "annotated with @ElementsIntoSet cannot %s a raw Set", bindingElementTypeVerb());
+  }
+
+  /*** Returns an {@link ElementValidator} for validating the given {@code element}. */
+  protected abstract ElementValidator elementValidator(E element);
+
+  /** Validator for a single binding element. */
+  protected abstract class ElementValidator {
+    protected final E element;
+    protected final ValidationReport.Builder<E> report;
+
+    protected ElementValidator(E element) {
+      this.element = element;
+      this.report = ValidationReport.about(element);
+    }
+
+    /** Checks the element for validity. */
+    private ValidationReport<E> validate() {
+      checkType();
+      checkQualifiers();
+      checkMapKeys();
+      checkMultibindings();
+      checkScopes();
+      checkAdditionalProperties();
+      return report.build();
+    }
+
+    /** Check any additional properties of the element. Does nothing by default. */
+    protected void checkAdditionalProperties() {}
+
+    /**
+     * The type declared by this binding element. This may differ from a binding's {@link
+     * Key#type()}, for example in multibindings. An {@link Optional#empty()} return value indicates
+     * that the contributed type is ambiguous or missing, i.e. a {@code @BindsInstance} method with
+     * zero or many parameters.
+     */
+    // TODO(dpb): should this be an ImmutableList<TypeMirror>, with this class checking the size?
+    protected abstract Optional<TypeMirror> bindingElementType();
+
+    /**
+     * Adds an error if the {@link #bindingElementType() binding element type} is not appropriate.
+     *
+     * <p>Adds an error if the type is not a primitive, array, declared type, or type variable.
+     *
+     * <p>If the binding is not a multibinding contribution, adds an error if the type is a
+     * framework type.
+     *
+     * <p>If the element has {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES}, adds an
+     * error if the type is not a {@code Set<T>} for some {@code T}
+     */
+    protected void checkType() {
+      switch (ContributionType.fromBindingElement(element)) {
+        case UNIQUE:
+          /* Validate that a unique binding is not attempting to bind a framework type. This
+           * validation is only appropriate for unique bindings because multibindings may collect
+           * framework types.  E.g. Set<Provider<Foo>> is perfectly reasonable. */
+          checkFrameworkType();
+          // fall through
+
+        case SET:
+        case MAP:
+          bindingElementType().ifPresent(type -> checkKeyType(type));
+          break;
+
+        case SET_VALUES:
+          checkSetValuesType();
+      }
+    }
+
+    /**
+     * Adds an error if {@code keyType} is not a primitive, declared type, array, or type variable.
+     */
+    protected void checkKeyType(TypeMirror keyType) {
+      TypeKind kind = keyType.getKind();
+      if (kind.equals(VOID)) {
+        report.addError(bindingElements("must %s a value (not void)", bindingElementTypeVerb()));
+      } else if (!(kind.isPrimitive()
+          || kind.equals(DECLARED)
+          || kind.equals(ARRAY)
+          || kind.equals(TYPEVAR))) {
+        report.addError(badTypeMessage());
+      }
+    }
+
+    /**
+     * Adds an error if the type for an element with {@link ElementsIntoSet @ElementsIntoSet} or
+     * {@code SET_VALUES} is not a a {@code Set<T>} for a reasonable {@code T}.
+     */
+    // TODO(gak): should we allow "covariant return" for set values?
+    protected void checkSetValuesType() {
+      bindingElementType().ifPresent(keyType -> checkSetValuesType(keyType));
+    }
+
+    /** Adds an error if {@code type} is not a {@code Set<T>} for a reasonable {@code T}. */
+    protected final void checkSetValuesType(TypeMirror type) {
+      if (!SetType.isSet(type)) {
+        report.addError(elementsIntoSetNotASetMessage());
+      } else {
+        SetType setType = SetType.from(type);
+        if (setType.isRawType()) {
+          report.addError(elementsIntoSetRawSetMessage());
+        } else {
+          checkKeyType(setType.elementType());
+        }
+      }
+    }
+
+    /**
+     * Adds an error if the element has more than one {@linkplain Qualifier qualifier} annotation.
+     */
+    private void checkQualifiers() {
+      ImmutableSet<? extends AnnotationMirror> qualifiers = getQualifiers(element);
+      if (qualifiers.size() > 1) {
+        for (AnnotationMirror qualifier : qualifiers) {
+          report.addError(
+              bindingElements("may not use more than one @Qualifier"),
+              element,
+              qualifier);
+        }
+      }
+    }
+
+    /**
+     * Adds an error if an {@link IntoMap @IntoMap} element doesn't have exactly one {@link
+     * MapKey @MapKey} annotation, or if an element that is {@link IntoMap @IntoMap} has any.
+     */
+    private void checkMapKeys() {
+      if (!allowsMultibindings.allowsMultibindings()) {
+        return;
+      }
+      ImmutableSet<? extends AnnotationMirror> mapKeys = getMapKeys(element);
+      if (ContributionType.fromBindingElement(element).equals(ContributionType.MAP)) {
+        switch (mapKeys.size()) {
+          case 0:
+            report.addError(bindingElements("of type map must declare a map key"));
+            break;
+          case 1:
+            break;
+          default:
+            report.addError(bindingElements("may not have more than one map key"));
+            break;
+        }
+      } else if (!mapKeys.isEmpty()) {
+        report.addError(bindingElements("of non map type cannot declare a map key"));
+      }
+    }
+
+    /**
+     * Adds errors if:
+     *
+     * <ul>
+     *   <li>the element doesn't allow {@linkplain MultibindingAnnotations multibinding annotations}
+     *       and has any
+     *   <li>the element does allow them but has more than one
+     *   <li>the element has a multibinding annotation and its {@link Provides} or {@link Produces}
+     *       annotation has a {@code type} parameter.
+     * </ul>
+     */
+    private void checkMultibindings() {
+      ImmutableSet<AnnotationMirror> multibindingAnnotations =
+          MultibindingAnnotations.forElement(element);
+
+      switch (allowsMultibindings) {
+        case NO_MULTIBINDINGS:
+          for (AnnotationMirror annotation : multibindingAnnotations) {
+            report.addError(
+                bindingElements("cannot have multibinding annotations"),
+                element,
+                annotation);
+          }
+          break;
+
+        case ALLOWS_MULTIBINDINGS:
+          if (multibindingAnnotations.size() > 1) {
+            for (AnnotationMirror annotation : multibindingAnnotations) {
+              report.addError(
+                  bindingElements("cannot have more than one multibinding annotation"),
+                  element,
+                  annotation);
+            }
+          }
+          break;
+      }
+
+      // TODO(ronshapiro): move this into ProvidesMethodValidator
+      if (bindingAnnotation.equals(Provides.class)) {
+        AnnotationMirror bindingAnnotationMirror =
+            getAnnotationMirror(element, bindingAnnotation).get();
+        boolean usesProvidesType = false;
+        for (ExecutableElement member : bindingAnnotationMirror.getElementValues().keySet()) {
+          usesProvidesType |= member.getSimpleName().contentEquals("type");
+        }
+        if (usesProvidesType && !multibindingAnnotations.isEmpty()) {
+          report.addError(
+              "@Provides.type cannot be used with multibinding annotations", element);
+        }
+      }
+    }
+
+    /**
+     * Adds an error if the element has a scope but doesn't allow scoping, or if it has more than
+     * one {@linkplain Scope scope} annotation.
+     */
+    private void checkScopes() {
+      ImmutableSet<Scope> scopes = scopesOf(element);
+      String error = null;
+      switch (allowsScoping) {
+        case ALLOWS_SCOPING:
+          if (scopes.size() <= 1) {
+            return;
+          }
+          error = bindingElements("cannot use more than one @Scope");
+          break;
+        case NO_SCOPING:
+          error = bindingElements("cannot be scoped");
+          break;
+      }
+      verifyNotNull(error);
+      for (Scope scope : scopes) {
+        report.addError(error, element, scope.scopeAnnotation());
+      }
+    }
+
+    /**
+     * Adds an error if the {@link #bindingElementType() type} is a {@linkplain FrameworkTypes
+     * framework type}.
+     */
+    private void checkFrameworkType() {
+      if (bindingElementType().filter(FrameworkTypes::isFrameworkType).isPresent()) {
+        report.addError(bindingElements("must not %s framework types", bindingElementTypeVerb()));
+      }
+    }
+  }
+
+  /** Whether to check multibinding annotations. */
+  enum AllowsMultibindings {
+    /**
+     * This element disallows multibinding annotations, so don't bother checking for their validity.
+     * {@link MultibindingAnnotationsProcessingStep} will add errors if the element has any
+     * multibinding annotations.
+     */
+    NO_MULTIBINDINGS,
+
+    /** This element allows multibinding annotations, so validate them. */
+    ALLOWS_MULTIBINDINGS,
+    ;
+
+    private boolean allowsMultibindings() {
+      return this == ALLOWS_MULTIBINDINGS;
+    }
+  }
+
+  /** How to check scoping annotations. */
+  enum AllowsScoping {
+    /** This element disallows scoping, so check that no scope annotations are present. */
+    NO_SCOPING,
+
+    /** This element allows scoping, so validate that there's at most one scope annotation. */
+    ALLOWS_SCOPING,
+    ;
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingExpression.java b/java/dagger/internal/codegen/BindingExpression.java
new file mode 100644
index 0000000..65200f7
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingExpression.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 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 dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import javax.lang.model.type.TypeMirror;
+
+/** A factory of code expressions used to access a single request for a binding in a component. */
+// TODO(user): Rename this to RequestExpression?
+abstract class BindingExpression {
+
+  /**
+   * Returns an expression that evaluates to the value of a request based on the given requesting
+   * class.
+   *
+   * @param requestingClass the class that will contain the expression
+   */
+  abstract Expression getDependencyExpression(ClassName requestingClass);
+
+  /**
+   * Equivalent to {@link #getDependencyExpression} that is used only when the request is for an
+   * implementation of a component method. By default, just delegates to {@link
+   * #getDependencyExpression}.
+   */
+  Expression getDependencyExpressionForComponentMethod(
+      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
+    return getDependencyExpression(component.name());
+  }
+
+  /** Returns {@code true} if this binding expression should be encapsulated in a method. */
+  boolean requiresMethodEncapsulation() {
+    return false;
+  }
+
+  /**
+   * Returns an expression for the implementation of a component method with the given request.
+   *
+   * @param component the component that will contain the implemented method
+   */
+  CodeBlock getComponentMethodImplementation(
+      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
+    // By default, just delegate to #getDependencyExpression().
+    return CodeBlock.of(
+        "return $L;",
+        getDependencyExpressionForComponentMethod(componentMethod, component).codeBlock());
+  }
+
+  /**
+   * Returns an expression for the implementation of a modifiable binding method for the given
+   * component.
+   */
+  CodeBlock getModifiableBindingMethodImplementation(
+      ModifiableBindingMethod modifiableBindingMethod,
+      ComponentImplementation component,
+      DaggerTypes types) {
+    Expression dependencyExpression = getDependencyExpression(component.name());
+
+    // It's possible to have a case where a modifiable component method delegates to another
+    // binding method from an enclosing class that is not itself a component method. In that case,
+    // the enclosing class's method may return a publicly accessible type, but the nested class will
+    // have a return type that is defined by the component method. In that case, a downcast is
+    // necessary so that the return statement is valid.
+    //
+    // E.g.:
+    //
+    // public class DaggerAncestor implements Ancestor {
+    //   protected Object packagePrivateModifiable() { ... }
+    //
+    //   protected class LeafImpl extends DaggerLeaf {
+    //     @Override
+    //     public final PackagePrivateModifiable componentMethod() {
+    //       return (PackagePrivateModifiable) DaggerAncestor.this.packagePrivateModifiable();
+    //     }
+    //   }
+    // }
+    //
+    // DaggerAncestor.packagePrivateModifiable returns Object even though the actual instance's type
+    // is PackagePrivateModifiable. So a cast is necessary.
+    //
+    // This isn't necessary for getComponentMethodImplementation() because that's only used for
+    // non-modifiable bindings
+    TypeMirror returnType = modifiableBindingMethod.returnType();
+    if (!types.isAssignable(dependencyExpression.type(), returnType)
+       && isTypeAccessibleFrom(returnType, component.name().packageName())) {
+      dependencyExpression = dependencyExpression.castTo(returnType);
+    }
+
+    return CodeBlock.of("return $L;", dependencyExpression.codeBlock());
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingFactory.java b/java/dagger/internal/codegen/BindingFactory.java
new file mode 100644
index 0000000..564b412
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingFactory.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2017 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.MoreElements.isAnnotationPresent;
+import static com.google.auto.common.MoreTypes.asDeclared;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.Binding.hasNonDefaultTypeParameters;
+import static dagger.internal.codegen.ComponentDescriptor.isComponentProductionMethod;
+import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
+import static dagger.internal.codegen.ContributionBinding.bindingKindForMultibindingKey;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifier;
+import static dagger.internal.codegen.MapKeys.getMapKey;
+import static dagger.internal.codegen.MoreAnnotationMirrors.wrapOptionalInEquivalence;
+import static dagger.internal.codegen.Scopes.uniqueScopeOf;
+import static dagger.model.BindingKind.BOUND_INSTANCE;
+import static dagger.model.BindingKind.COMPONENT;
+import static dagger.model.BindingKind.COMPONENT_DEPENDENCY;
+import static dagger.model.BindingKind.COMPONENT_PRODUCTION;
+import static dagger.model.BindingKind.COMPONENT_PROVISION;
+import static dagger.model.BindingKind.DELEGATE;
+import static dagger.model.BindingKind.INJECTION;
+import static dagger.model.BindingKind.MEMBERS_INJECTOR;
+import static dagger.model.BindingKind.OPTIONAL;
+import static dagger.model.BindingKind.PRODUCTION;
+import static dagger.model.BindingKind.PROVISION;
+import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
+import static javax.lang.model.element.ElementKind.CONSTRUCTOR;
+import static javax.lang.model.element.ElementKind.METHOD;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Iterables;
+import dagger.Module;
+import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.ProductionBinding.ProductionKind;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import java.util.Optional;
+import java.util.function.BiFunction;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+/** A factory for {@link Binding} objects. */
+final class BindingFactory {
+  private final DaggerTypes types;
+  private final KeyFactory keyFactory;
+  private final DependencyRequestFactory dependencyRequestFactory;
+  private final InjectionSiteFactory injectionSiteFactory;
+  private final DaggerElements elements;
+
+  @Inject
+  BindingFactory(
+      DaggerTypes types,
+      DaggerElements elements,
+      KeyFactory keyFactory,
+      DependencyRequestFactory dependencyRequestFactory,
+      InjectionSiteFactory injectionSiteFactory) {
+    this.types = types;
+    this.elements = elements;
+    this.keyFactory = keyFactory;
+    this.dependencyRequestFactory = dependencyRequestFactory;
+    this.injectionSiteFactory = injectionSiteFactory;
+  }
+
+  /**
+   * Returns an {@link dagger.model.BindingKind#INJECTION} binding.
+   *
+   * @param constructorElement the {@code @Inject}-annotated constructor
+   * @param resolvedType the parameterized type if the constructor is for a generic class and the
+   *     binding should be for the parameterized type
+   */
+  // TODO(dpb): See if we can just pass the parameterized type and not also the constructor.
+  ProvisionBinding injectionBinding(
+      ExecutableElement constructorElement, Optional<TypeMirror> resolvedType) {
+    checkArgument(constructorElement.getKind().equals(CONSTRUCTOR));
+    checkArgument(isAnnotationPresent(constructorElement, Inject.class));
+    checkArgument(!getQualifier(constructorElement).isPresent());
+
+    ExecutableType constructorType = MoreTypes.asExecutable(constructorElement.asType());
+    DeclaredType constructedType =
+        MoreTypes.asDeclared(constructorElement.getEnclosingElement().asType());
+    // If the class this is constructing has some type arguments, resolve everything.
+    if (!constructedType.getTypeArguments().isEmpty() && resolvedType.isPresent()) {
+      DeclaredType resolved = MoreTypes.asDeclared(resolvedType.get());
+      // Validate that we're resolving from the correct type.
+      checkState(
+          types.isSameType(types.erasure(resolved), types.erasure(constructedType)),
+          "erased expected type: %s, erased actual type: %s",
+          types.erasure(resolved),
+          types.erasure(constructedType));
+      constructorType = MoreTypes.asExecutable(types.asMemberOf(resolved, constructorElement));
+      constructedType = resolved;
+    }
+
+    Key key = keyFactory.forInjectConstructorWithResolvedType(constructedType);
+    ImmutableSet<DependencyRequest> provisionDependencies =
+        dependencyRequestFactory.forRequiredResolvedVariables(
+            constructorElement.getParameters(), constructorType.getParameterTypes());
+
+    ProvisionBinding.Builder builder =
+        ProvisionBinding.builder()
+            .contributionType(ContributionType.UNIQUE)
+            .bindingElement(constructorElement)
+            .key(key)
+            .provisionDependencies(provisionDependencies)
+            .injectionSites(injectionSiteFactory.getInjectionSites(constructedType))
+            .kind(INJECTION)
+            .scope(uniqueScopeOf(constructorElement.getEnclosingElement()));
+
+    TypeElement bindingTypeElement = MoreElements.asType(constructorElement.getEnclosingElement());
+    if (hasNonDefaultTypeParameters(bindingTypeElement, key.type(), types)) {
+      builder.unresolved(injectionBinding(constructorElement, Optional.empty()));
+    }
+    return builder.build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#PROVISION} binding for a {@code @Provides}-annotated
+   * method.
+   *
+   * @param contributedBy the installed module that declares or inherits the method
+   */
+  ProvisionBinding providesMethodBinding(
+      ExecutableElement providesMethod, TypeElement contributedBy) {
+    return setMethodBindingProperties(
+            ProvisionBinding.builder(),
+            providesMethod,
+            contributedBy,
+            keyFactory.forProvidesMethod(providesMethod, contributedBy),
+            this::providesMethodBinding)
+        .kind(PROVISION)
+        .scope(uniqueScopeOf(providesMethod))
+        .nullableType(getNullableType(providesMethod))
+        .build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#PRODUCTION} binding for a {@code @Produces}-annotated
+   * method.
+   *
+   * @param contributedBy the installed module that declares or inherits the method
+   */
+  ProductionBinding producesMethodBinding(
+      ExecutableElement producesMethod, TypeElement contributedBy) {
+    // TODO(beder): Add nullability checking with Java 8.
+    ProductionBinding.Builder builder =
+        setMethodBindingProperties(
+                ProductionBinding.builder(),
+                producesMethod,
+                contributedBy,
+                keyFactory.forProducesMethod(producesMethod, contributedBy),
+                this::producesMethodBinding)
+            .kind(PRODUCTION)
+            .productionKind(ProductionKind.fromProducesMethod(producesMethod))
+            .thrownTypes(producesMethod.getThrownTypes())
+            .executorRequest(dependencyRequestFactory.forProductionImplementationExecutor())
+            .monitorRequest(dependencyRequestFactory.forProductionComponentMonitor());
+    return builder.build();
+  }
+
+  private <C extends ContributionBinding, B extends ContributionBinding.Builder<C, B>>
+      B setMethodBindingProperties(
+          B builder,
+          ExecutableElement method,
+          TypeElement contributedBy,
+          Key key,
+          BiFunction<ExecutableElement, TypeElement, C> create) {
+    checkArgument(method.getKind().equals(METHOD));
+    ExecutableType methodType =
+        MoreTypes.asExecutable(
+            types.asMemberOf(MoreTypes.asDeclared(contributedBy.asType()), method));
+    if (!types.isSameType(methodType, method.asType())) {
+      builder.unresolved(create.apply(method, MoreElements.asType(method.getEnclosingElement())));
+    }
+    return builder
+        .contributionType(ContributionType.fromBindingElement(method))
+        .bindingElement(method)
+        .contributingModule(contributedBy)
+        .key(key)
+        .dependencies(
+            dependencyRequestFactory.forRequiredResolvedVariables(
+                method.getParameters(), methodType.getParameterTypes()))
+        .wrappedMapKeyAnnotation(wrapOptionalInEquivalence(getMapKey(method)));
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#MULTIBOUND_MAP} or {@link
+   * dagger.model.BindingKind#MULTIBOUND_SET} binding given a set of multibinding contribution
+   * bindings.
+   *
+   * @param key a key that may be satisfied by a multibinding
+   */
+  ContributionBinding syntheticMultibinding(
+      Key key, Iterable<ContributionBinding> multibindingContributions) {
+    ContributionBinding.Builder<?, ?> builder =
+        multibindingRequiresProduction(key, multibindingContributions)
+            ? ProductionBinding.builder()
+            : ProvisionBinding.builder();
+    return builder
+        .contributionType(ContributionType.UNIQUE)
+        .key(key)
+        .dependencies(
+            dependencyRequestFactory.forMultibindingContributions(key, multibindingContributions))
+        .kind(bindingKindForMultibindingKey(key))
+        .build();
+  }
+
+  private boolean multibindingRequiresProduction(
+      Key key, Iterable<ContributionBinding> multibindingContributions) {
+    if (MapType.isMap(key)) {
+      MapType mapType = MapType.from(key);
+      if (mapType.valuesAreTypeOf(Producer.class) || mapType.valuesAreTypeOf(Produced.class)) {
+        return true;
+      }
+    } else if (SetType.isSet(key) && SetType.from(key).elementsAreTypeOf(Produced.class)) {
+      return true;
+    }
+    return Iterables.any(
+        multibindingContributions, binding -> binding.bindingType().equals(BindingType.PRODUCTION));
+  }
+
+  /** Returns a {@link dagger.model.BindingKind#COMPONENT} binding for the component. */
+  ProvisionBinding componentBinding(TypeElement componentDefinitionType) {
+    checkNotNull(componentDefinitionType);
+    return ProvisionBinding.builder()
+        .contributionType(ContributionType.UNIQUE)
+        .bindingElement(componentDefinitionType)
+        .key(keyFactory.forType(componentDefinitionType.asType()))
+        .kind(COMPONENT)
+        .build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#COMPONENT_DEPENDENCY} binding for a component's
+   * dependency.
+   */
+  ProvisionBinding componentDependencyBinding(ComponentRequirement dependency) {
+    checkNotNull(dependency);
+    return ProvisionBinding.builder()
+        .contributionType(ContributionType.UNIQUE)
+        .bindingElement(dependency.typeElement())
+        .key(keyFactory.forType(dependency.type()))
+        .kind(COMPONENT_DEPENDENCY)
+        .build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#COMPONENT_PROVISION} or {@link
+   * dagger.model.BindingKind#COMPONENT_PRODUCTION} binding for a method on a component's
+   * dependency.
+   *
+   * @param componentDescriptor the component with the dependency, not the dependency that has the
+   *     method
+   */
+  ContributionBinding componentDependencyMethodBinding(
+      ComponentDescriptor componentDescriptor, ExecutableElement dependencyMethod) {
+    checkArgument(dependencyMethod.getKind().equals(METHOD));
+    checkArgument(dependencyMethod.getParameters().isEmpty());
+    ContributionBinding.Builder<?, ?> builder;
+    if (componentDescriptor.isProduction()
+        && isComponentProductionMethod(elements, dependencyMethod)) {
+      builder =
+          ProductionBinding.builder()
+              .key(keyFactory.forProductionComponentMethod(dependencyMethod))
+              .kind(COMPONENT_PRODUCTION)
+              .thrownTypes(dependencyMethod.getThrownTypes());
+    } else {
+      builder =
+          ProvisionBinding.builder()
+              .key(keyFactory.forComponentMethod(dependencyMethod))
+              .nullableType(getNullableType(dependencyMethod))
+              .kind(COMPONENT_PROVISION)
+              .scope(uniqueScopeOf(dependencyMethod));
+    }
+    return builder
+        .contributionType(ContributionType.UNIQUE)
+        .bindingElement(dependencyMethod)
+        .build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#BOUND_INSTANCE} binding for a
+   * {@code @BindsInstance}-annotated builder setter method or factory method parameter.
+   */
+  ProvisionBinding boundInstanceBinding(ComponentRequirement requirement, Element element) {
+    checkArgument(element instanceof VariableElement || element instanceof ExecutableElement);
+    VariableElement parameterElement =
+        element instanceof VariableElement
+            ? MoreElements.asVariable(element)
+            : getOnlyElement(MoreElements.asExecutable(element).getParameters());
+    return ProvisionBinding.builder()
+        .contributionType(ContributionType.UNIQUE)
+        .bindingElement(element)
+        .key(requirement.key().get())
+        .nullableType(getNullableType(parameterElement))
+        .kind(BOUND_INSTANCE)
+        .build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#SUBCOMPONENT_CREATOR} binding declared by a component
+   * method that returns a subcomponent builder. Use {{@link
+   * #subcomponentCreatorBinding(ImmutableSet)}} for bindings declared using {@link
+   * Module#subcomponents()}.
+   *
+   * @param component the component that declares or inherits the method
+   */
+  ProvisionBinding subcomponentCreatorBinding(
+      ExecutableElement subcomponentCreatorMethod, TypeElement component) {
+    checkArgument(subcomponentCreatorMethod.getKind().equals(METHOD));
+    checkArgument(subcomponentCreatorMethod.getParameters().isEmpty());
+    Key key =
+        keyFactory.forSubcomponentCreatorMethod(
+            subcomponentCreatorMethod, asDeclared(component.asType()));
+    return ProvisionBinding.builder()
+        .contributionType(ContributionType.UNIQUE)
+        .bindingElement(subcomponentCreatorMethod)
+        .key(key)
+        .kind(SUBCOMPONENT_CREATOR)
+        .build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#SUBCOMPONENT_CREATOR} binding declared using {@link
+   * Module#subcomponents()}.
+   */
+  ProvisionBinding subcomponentCreatorBinding(
+      ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
+    SubcomponentDeclaration subcomponentDeclaration = subcomponentDeclarations.iterator().next();
+    return ProvisionBinding.builder()
+        .contributionType(ContributionType.UNIQUE)
+        .key(subcomponentDeclaration.key())
+        .kind(SUBCOMPONENT_CREATOR)
+        .build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#DELEGATE} binding.
+   *
+   * @param delegateDeclaration the {@code @Binds}-annotated declaration
+   * @param actualBinding the binding that satisfies the {@code @Binds} declaration
+   */
+  ContributionBinding delegateBinding(
+      DelegateDeclaration delegateDeclaration, ContributionBinding actualBinding) {
+    switch (actualBinding.bindingType()) {
+      case PRODUCTION:
+        return buildDelegateBinding(
+            ProductionBinding.builder().nullableType(actualBinding.nullableType()),
+            delegateDeclaration,
+            Producer.class);
+
+      case PROVISION:
+        return buildDelegateBinding(
+            ProvisionBinding.builder()
+                .scope(uniqueScopeOf(delegateDeclaration.bindingElement().get()))
+                .nullableType(actualBinding.nullableType()),
+            delegateDeclaration,
+            Provider.class);
+
+      case MEMBERS_INJECTION: // fall-through to throw
+    }
+    throw new AssertionError("bindingType: " + actualBinding);
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#DELEGATE} binding used when there is no binding that
+   * satisfies the {@code @Binds} declaration.
+   */
+  ContributionBinding unresolvedDelegateBinding(DelegateDeclaration delegateDeclaration) {
+    return buildDelegateBinding(
+        ProvisionBinding.builder().scope(uniqueScopeOf(delegateDeclaration.bindingElement().get())),
+        delegateDeclaration,
+        Provider.class);
+  }
+
+  private ContributionBinding buildDelegateBinding(
+      ContributionBinding.Builder<?, ?> builder,
+      DelegateDeclaration delegateDeclaration,
+      Class<?> frameworkType) {
+    return builder
+        .contributionType(delegateDeclaration.contributionType())
+        .bindingElement(delegateDeclaration.bindingElement().get())
+        .contributingModule(delegateDeclaration.contributingModule().get())
+        .key(keyFactory.forDelegateBinding(delegateDeclaration, frameworkType))
+        .dependencies(delegateDeclaration.delegateRequest())
+        .wrappedMapKeyAnnotation(delegateDeclaration.wrappedMapKey())
+        .kind(DELEGATE)
+        .build();
+  }
+
+  /**
+   * Returns an {@link dagger.model.BindingKind#OPTIONAL} binding for {@code key}.
+   *
+   * @param requestKind the kind of request for the optional binding
+   * @param underlyingKeyBindings the possibly empty set of bindings that exist in the component for
+   *     the underlying (non-optional) key
+   */
+  ContributionBinding syntheticOptionalBinding(
+      Key key, RequestKind requestKind, ResolvedBindings underlyingKeyBindings) {
+    ContributionBinding.Builder<?, ?> builder =
+        syntheticOptionalBindingBuilder(requestKind, underlyingKeyBindings)
+            .contributionType(ContributionType.UNIQUE)
+            .key(key)
+            .kind(OPTIONAL);
+    if (!underlyingKeyBindings.isEmpty()) {
+      builder.dependencies(
+          dependencyRequestFactory.forSyntheticPresentOptionalBinding(key, requestKind));
+    }
+    return builder.build();
+  }
+
+  private ContributionBinding.Builder<?, ?> syntheticOptionalBindingBuilder(
+      RequestKind requestKind, ResolvedBindings underlyingKeyBindings) {
+    return !underlyingKeyBindings.isEmpty()
+            && (underlyingKeyBindings.bindingTypes().contains(BindingType.PRODUCTION)
+                || requestKind.equals(RequestKind.PRODUCER) // handles producerFromProvider cases
+                || requestKind.equals(RequestKind.PRODUCED)) // handles producerFromProvider cases
+        ? ProductionBinding.builder()
+        : ProvisionBinding.builder();
+  }
+
+  /** Returns a {@link dagger.model.BindingKind#MEMBERS_INJECTOR} binding. */
+  ProvisionBinding membersInjectorBinding(
+      Key key, MembersInjectionBinding membersInjectionBinding) {
+    return ProvisionBinding.builder()
+        .key(key)
+        .contributionType(ContributionType.UNIQUE)
+        .kind(MEMBERS_INJECTOR)
+        .bindingElement(MoreTypes.asTypeElement(membersInjectionBinding.key().type()))
+        .provisionDependencies(membersInjectionBinding.dependencies())
+        .injectionSites(membersInjectionBinding.injectionSites())
+        .build();
+  }
+
+  /**
+   * Returns a {@link dagger.model.BindingKind#MEMBERS_INJECTION} binding.
+   *
+   * @param resolvedType if {@code declaredType} is a generic class and {@code resolvedType} is a
+   *     parameterization of that type, the returned binding will be for the resolved type
+   */
+  // TODO(dpb): See if we can just pass one nongeneric/parameterized type.
+  MembersInjectionBinding membersInjectionBinding(
+      DeclaredType declaredType, Optional<TypeMirror> resolvedType) {
+    // If the class this is injecting has some type arguments, resolve everything.
+    if (!declaredType.getTypeArguments().isEmpty() && resolvedType.isPresent()) {
+      DeclaredType resolved = asDeclared(resolvedType.get());
+      // Validate that we're resolving from the correct type.
+      checkState(
+          types.isSameType(types.erasure(resolved), types.erasure(declaredType)),
+          "erased expected type: %s, erased actual type: %s",
+          types.erasure(resolved),
+          types.erasure(declaredType));
+      declaredType = resolved;
+    }
+    ImmutableSortedSet<InjectionSite> injectionSites =
+        injectionSiteFactory.getInjectionSites(declaredType);
+    ImmutableSet<DependencyRequest> dependencies =
+        injectionSites
+            .stream()
+            .flatMap(injectionSite -> injectionSite.dependencies().stream())
+            .collect(toImmutableSet());
+
+    Key key = keyFactory.forMembersInjectedType(declaredType);
+    TypeElement typeElement = MoreElements.asType(declaredType.asElement());
+    return new AutoValue_MembersInjectionBinding(
+        key,
+        dependencies,
+        typeElement,
+        hasNonDefaultTypeParameters(typeElement, key.type(), types)
+            ? Optional.of(
+                membersInjectionBinding(asDeclared(typeElement.asType()), Optional.empty()))
+            : Optional.empty(),
+        injectionSites);
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingGraph.java b/java/dagger/internal/codegen/BindingGraph.java
new file mode 100644
index 0000000..2f548b2
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingGraph.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.DaggerStreams.presentValues;
+import static dagger.internal.codegen.DaggerStreams.stream;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimaps;
+import com.google.common.graph.Traverser;
+import dagger.Subcomponent;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+
+/** The canonical representation of a full-resolved graph. */
+@AutoValue
+abstract class BindingGraph {
+  abstract ComponentDescriptor componentDescriptor();
+
+  /**
+   * The resolved bindings for all {@link ContributionBinding}s in this graph, keyed by {@link Key}.
+   */
+  // TODO(ronshapiro): when MembersInjectionBinding no longer extends Binding, rename this to
+  // bindings()
+  abstract ImmutableMap<Key, ResolvedBindings> contributionBindings();
+
+  /**
+   * The resolved bindings for all {@link MembersInjectionBinding}s in this graph, keyed by {@link
+   * Key}.
+   */
+  abstract ImmutableMap<Key, ResolvedBindings> membersInjectionBindings();
+
+  /**
+   * Returns the {@link ResolvedBindings resolved bindings} instance for {@code
+   * bindingExpressionKey}. If the bindings will be used for members injection, a {@link
+   * ResolvedBindings} with {@linkplain #membersInjectionBindings() members injection bindings} will
+   * be returned, otherwise a {@link ResolvedBindings} with {@link #contributionBindings()} will be
+   * returned.
+   */
+  final ResolvedBindings resolvedBindings(BindingRequest request) {
+    return request.isRequestKind(RequestKind.MEMBERS_INJECTION)
+        ? membersInjectionBindings().get(request.key())
+        : contributionBindings().get(request.key());
+  }
+
+  final Iterable<ResolvedBindings> resolvedBindings() {
+    // Don't return an immutable collection - this is only ever used for looping over all bindings
+    // in the graph. Copying is wasteful, especially if is a hashing collection, since the values
+    // should all, by definition, be distinct.
+    // TODO(dpb): consider inlining this to callers and removing this.
+    return Iterables.concat(membersInjectionBindings().values(), contributionBindings().values());
+  }
+
+  abstract ImmutableList<BindingGraph> subgraphs();
+
+  /**
+   * The type that defines the component for this graph.
+   *
+   * @see ComponentDescriptor#typeElement()
+   */
+  TypeElement componentTypeElement() {
+    return componentDescriptor().typeElement();
+  }
+
+  /**
+   * Returns the set of modules that are owned by this graph regardless of whether or not any of
+   * their bindings are used in this graph. For graphs representing top-level {@link
+   * dagger.Component components}, this set will be the same as {@linkplain
+   * ComponentDescriptor#modules() the component's transitive modules}. For {@linkplain Subcomponent
+   * subcomponents}, this set will be the transitive modules that are not owned by any of their
+   * ancestors.
+   */
+  abstract ImmutableSet<ModuleDescriptor> ownedModules();
+
+  @Memoized
+  ImmutableSet<TypeElement> ownedModuleTypes() {
+    return FluentIterable.from(ownedModules()).transform(ModuleDescriptor::moduleElement).toSet();
+  }
+
+  /**
+   * Returns the factory method for this subcomponent, if it exists.
+   *
+   * <p>This factory method is the one defined in the parent component's interface.
+   *
+   * <p>In the example below, the {@link BindingGraph#factoryMethod} for {@code ChildComponent}
+   * would return the {@link ExecutableElement}: {@code childComponent(ChildModule1)} .
+   *
+   * <pre><code>
+   *   {@literal @Component}
+   *   interface ParentComponent {
+   *     ChildComponent childComponent(ChildModule1 childModule);
+   *   }
+   * </code></pre>
+   */
+  // TODO(b/73294201): Consider returning the resolved ExecutableType for the factory method.
+  abstract Optional<ExecutableElement> factoryMethod();
+
+  /**
+   * Returns a map between the {@linkplain ComponentRequirement component requirement} and the
+   * corresponding {@link VariableElement} for each module parameter in the {@linkplain
+   * BindingGraph#factoryMethod factory method}.
+   */
+  // TODO(dpb): Consider disallowing modules if none of their bindings are used.
+  ImmutableMap<ComponentRequirement, VariableElement> factoryMethodParameters() {
+    checkState(factoryMethod().isPresent());
+    ImmutableMap.Builder<ComponentRequirement, VariableElement> builder = ImmutableMap.builder();
+    for (VariableElement parameter : factoryMethod().get().getParameters()) {
+      builder.put(ComponentRequirement.forModule(parameter.asType()), parameter);
+    }
+    return builder.build();
+  }
+
+  private static final Traverser<BindingGraph> SUBGRAPH_TRAVERSER =
+      Traverser.forTree(BindingGraph::subgraphs);
+
+  /**
+   * The types for which the component needs instances.
+   *
+   * <ul>
+   *   <li>component dependencies
+   *   <li>{@linkplain #ownedModules() owned modules} with concrete instance bindings that are used
+   *       in the graph
+   *   <li>bound instances
+   * </ul>
+   */
+  @Memoized
+  ImmutableSet<ComponentRequirement> componentRequirements() {
+    ImmutableSet<TypeElement> requiredModules = requiredModuleElements();
+    ImmutableSet.Builder<ComponentRequirement> requirements = ImmutableSet.builder();
+    componentDescriptor().requirements().stream()
+        .filter(
+            requirement ->
+                !requirement.kind().isModule()
+                    || requiredModules.contains(requirement.typeElement()))
+        .forEach(requirements::add);
+    if (factoryMethod().isPresent()) {
+      requirements.addAll(factoryMethodParameters().keySet());
+    }
+    return requirements.build();
+  }
+
+  private ImmutableSet<TypeElement> requiredModuleElements() {
+    return stream(SUBGRAPH_TRAVERSER.depthFirstPostOrder(this))
+        .flatMap(graph -> graph.contributionBindings().values().stream())
+        .flatMap(bindings -> bindings.contributionBindings().stream())
+        .map(ContributionBinding::contributingModule)
+        .distinct()
+        .flatMap(presentValues())
+        .filter(ownedModuleTypes()::contains)
+        .collect(toImmutableSet());
+  }
+
+  /** Returns the {@link ComponentDescriptor}s for this component and its subcomponents. */
+  ImmutableSet<ComponentDescriptor> componentDescriptors() {
+    return FluentIterable.from(SUBGRAPH_TRAVERSER.depthFirstPreOrder(this))
+        .transform(BindingGraph::componentDescriptor)
+        .toSet();
+  }
+
+  /**
+   * {@code true} if this graph contains all bindings installed in the component; {@code false} if
+   * it contains only those bindings that are reachable from at least one entry point.
+   */
+  abstract boolean isFullBindingGraph();
+
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  @Override // Suppresses ErrorProne warning that hashCode was overridden w/o equals
+  public abstract boolean equals(Object other);
+
+  static BindingGraph create(
+      ComponentDescriptor componentDescriptor,
+      Map<Key, ResolvedBindings> resolvedContributionBindingsMap,
+      Map<Key, ResolvedBindings> resolvedMembersInjectionBindings,
+      List<BindingGraph> subgraphs,
+      Set<ModuleDescriptor> ownedModules,
+      Optional<ExecutableElement> factoryMethod,
+      boolean isFullBindingGraph) {
+    checkForDuplicates(subgraphs);
+    return new AutoValue_BindingGraph(
+        componentDescriptor,
+        ImmutableMap.copyOf(resolvedContributionBindingsMap),
+        ImmutableMap.copyOf(resolvedMembersInjectionBindings),
+        ImmutableList.copyOf(subgraphs),
+        ImmutableSet.copyOf(ownedModules),
+        factoryMethod,
+        isFullBindingGraph);
+  }
+
+  private static final void checkForDuplicates(Iterable<BindingGraph> graphs) {
+    Map<TypeElement, Collection<BindingGraph>> duplicateGraphs =
+        Maps.filterValues(
+            Multimaps.index(graphs, graph -> graph.componentDescriptor().typeElement()).asMap(),
+            overlapping -> overlapping.size() > 1);
+    if (!duplicateGraphs.isEmpty()) {
+      throw new IllegalArgumentException("Expected no duplicates: " + duplicateGraphs);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingGraphConverter.java b/java/dagger/internal/codegen/BindingGraphConverter.java
new file mode 100644
index 0000000..a2cc799
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingGraphConverter.java
@@ -0,0 +1,239 @@
+/*
+ * 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.asTypeElement;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.DaggerGraphs.unreachableNodes;
+import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.graph.MutableNetwork;
+import com.google.common.graph.Network;
+import com.google.common.graph.NetworkBuilder;
+import dagger.model.BindingGraph.ComponentNode;
+import dagger.model.BindingGraph.DependencyEdge;
+import dagger.model.BindingGraph.Edge;
+import dagger.model.BindingGraph.MissingBinding;
+import dagger.model.BindingGraph.Node;
+import dagger.model.BindingGraphProxies;
+import dagger.model.ComponentPath;
+import dagger.model.DependencyRequest;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/** Converts {@link dagger.internal.codegen.BindingGraph}s to {@link dagger.model.BindingGraph}s. */
+final class BindingGraphConverter {
+  private final BindingDeclarationFormatter bindingDeclarationFormatter;
+
+  @Inject
+  BindingGraphConverter(BindingDeclarationFormatter bindingDeclarationFormatter) {
+    this.bindingDeclarationFormatter = bindingDeclarationFormatter;
+  }
+
+  /**
+   * Creates the external {@link dagger.model.BindingGraph} representing the given internal {@link
+   * dagger.internal.codegen.BindingGraph}.
+   */
+  dagger.model.BindingGraph convert(BindingGraph bindingGraph) {
+    Traverser traverser = new Traverser(bindingGraph);
+    traverser.traverseComponents();
+
+    // When bindings are copied down into child graphs because they transitively depend on local
+    // multibindings or optional bindings, the parent-owned binding is still there. If that
+    // parent-owned binding is not reachable from its component, it doesn't need to be in the graph
+    // because it will never be used. So remove all nodes that are not reachable from the root
+    // component—unless we're converting a full binding graph.
+    if (!bindingGraph.isFullBindingGraph()) {
+      unreachableNodes(traverser.network.asGraph(), rootComponentNode(traverser.network))
+          .forEach(traverser.network::removeNode);
+    }
+
+    return BindingGraphProxies.bindingGraph(traverser.network, bindingGraph.isFullBindingGraph());
+  }
+
+  // TODO(dpb): Example of BindingGraph logic applied to derived networks.
+  private ComponentNode rootComponentNode(Network<Node, Edge> network) {
+    return (ComponentNode)
+        Iterables.find(
+            network.nodes(),
+            node -> node instanceof ComponentNode && node.componentPath().atRoot());
+  }
+
+  private final class Traverser extends ComponentTreeTraverser {
+    private final MutableNetwork<Node, Edge> network =
+        NetworkBuilder.directed().allowsParallelEdges(true).allowsSelfLoops(true).build();
+    private final boolean isRootSubcomponent;
+    private final boolean isFullBindingGraph;
+
+    private final ComponentPath rootComponentPath;
+    private ComponentNode parentComponent;
+    private ComponentNode currentComponent;
+
+    Traverser(BindingGraph graph) {
+      super(graph);
+      rootComponentPath = ComponentPath.create(ImmutableList.of(graph.componentTypeElement()));
+      isRootSubcomponent = graph.componentDescriptor().isSubcomponent();
+      isFullBindingGraph = graph.isFullBindingGraph();
+    }
+
+    @Override
+    protected void visitComponent(BindingGraph graph) {
+      ComponentNode grandparentComponent = parentComponent;
+      parentComponent = currentComponent;
+      currentComponent = ComponentNodeImpl.create(componentPath(), graph.componentDescriptor());
+
+      network.addNode(currentComponent);
+
+      for (ResolvedBindings resolvedBindings : graph.resolvedBindings()) {
+        for (BindingNode binding : bindingNodes(resolvedBindings)) {
+          addBinding(binding);
+          if (binding.kind().equals(SUBCOMPONENT_CREATOR)
+              && binding.componentPath().equals(currentComponent.componentPath())) {
+            network.addEdge(
+                binding,
+                subcomponentNode(binding.key().type(), graph),
+                new SubcomponentCreatorBindingEdgeImpl(
+                    resolvedBindings.subcomponentDeclarations()));
+          }
+        }
+      }
+
+      super.visitComponent(graph);
+
+      currentComponent = parentComponent;
+      parentComponent = grandparentComponent;
+    }
+
+    @Override
+    protected void visitEntryPoint(DependencyRequest entryPoint, BindingGraph graph) {
+      addDependencyEdges(currentComponent, entryPoint);
+      super.visitEntryPoint(entryPoint, graph);
+    }
+
+    @Override
+    protected void visitSubcomponentFactoryMethod(
+        BindingGraph graph, BindingGraph parent, ExecutableElement factoryMethod) {
+      network.addEdge(
+          parentComponent, currentComponent, new ChildFactoryMethodEdgeImpl(factoryMethod));
+      super.visitSubcomponentFactoryMethod(graph, parent, factoryMethod);
+    }
+
+    /**
+     * Adds a {@link dagger.model.BindingGraph.DependencyEdge} from a node to the binding(s) that
+     * satisfy a dependency request.
+     */
+    private void addDependencyEdges(Node source, DependencyRequest dependencyRequest) {
+      ResolvedBindings dependencies = resolvedDependencies(source, dependencyRequest);
+      if (dependencies.isEmpty()) {
+        addDependencyEdge(source, dependencyRequest, missingBindingNode(dependencies));
+      } else {
+        for (BindingNode dependency : bindingNodes(dependencies)) {
+          addDependencyEdge(source, dependencyRequest, dependency);
+        }
+      }
+    }
+
+    private void addDependencyEdge(
+        Node source, DependencyRequest dependencyRequest, Node dependency) {
+      network.addNode(dependency);
+      if (!hasDependencyEdge(source, dependency, dependencyRequest)) {
+        network.addEdge(
+            source,
+            dependency,
+            new DependencyEdgeImpl(dependencyRequest, source instanceof ComponentNode));
+      }
+    }
+
+    private boolean hasDependencyEdge(
+        Node source, Node dependency, DependencyRequest dependencyRequest) {
+      // An iterative approach is used instead of a Stream because this method is called in a hot
+      // loop, and the Stream calculates the size of network.edgesConnecting(), which is slow. This
+      // seems to be because caculating the edges connecting two nodes in a Network that supports
+      // parallel edges is must check the equality of many nodes, and BindingNode's equality
+      // semantics drag in the equality of many other expensive objects
+      for (Edge edge : network.edgesConnecting(source, dependency)) {
+        if (edge instanceof DependencyEdge) {
+          if (((DependencyEdge) edge).dependencyRequest().equals(dependencyRequest)) {
+            return true;
+          }
+        }
+      }
+      return false;
+    }
+
+    private ResolvedBindings resolvedDependencies(
+        Node source, DependencyRequest dependencyRequest) {
+      return graphForAncestor(source.componentPath().currentComponent())
+          .resolvedBindings(bindingRequest(dependencyRequest));
+    }
+
+    /** Adds a binding and all its dependencies. */
+    private void addBinding(BindingNode binding) {
+      network.addNode(binding);
+      for (DependencyRequest dependencyRequest : binding.dependencies()) {
+        addDependencyEdges(binding, dependencyRequest);
+      }
+    }
+
+    private ImmutableSet<BindingNode> bindingNodes(ResolvedBindings resolvedBindings) {
+      ImmutableSet.Builder<BindingNode> bindingNodes = ImmutableSet.builder();
+      resolvedBindings
+          .allBindings()
+          .asMap()
+          .forEach(
+              (component, bindings) -> {
+                for (Binding binding : bindings) {
+                  bindingNodes.add(bindingNode(resolvedBindings, binding, component));
+                }
+              });
+      return bindingNodes.build();
+    }
+
+    private BindingNode bindingNode(
+        ResolvedBindings resolvedBindings, Binding binding, TypeElement owningComponent) {
+      return BindingNode.create(
+          pathFromRootToAncestor(owningComponent),
+          binding,
+          resolvedBindings.multibindingDeclarations(),
+          resolvedBindings.optionalBindingDeclarations(),
+          resolvedBindings.subcomponentDeclarations(),
+          bindingDeclarationFormatter);
+    }
+
+    private MissingBinding missingBindingNode(ResolvedBindings dependencies) {
+      // TODO(b/117833324): Revisit whether limiting missing binding nodes to the root component is
+      // necessary to limit the amount of missing binding nodes in the network, or if perhaps *all*
+      // missing binding nodes should be structured this way.
+      return BindingGraphProxies.missingBindingNode(
+          isRootSubcomponent && !isFullBindingGraph ? rootComponentPath : componentPath(),
+          dependencies.key());
+    }
+
+    private ComponentNode subcomponentNode(TypeMirror subcomponentBuilderType, BindingGraph graph) {
+      TypeElement subcomponentBuilderElement = asTypeElement(subcomponentBuilderType);
+      ComponentDescriptor subcomponent =
+          graph.componentDescriptor().getChildComponentWithBuilderType(subcomponentBuilderElement);
+      return ComponentNodeImpl.create(
+          componentPath().childPath(subcomponent.typeElement()), subcomponent);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingGraphFactory.java b/java/dagger/internal/codegen/BindingGraphFactory.java
new file mode 100644
index 0000000..d96da8a
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingGraphFactory.java
@@ -0,0 +1,1061 @@
+/*
+ * Copyright (C) 2014 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.isType;
+import static com.google.auto.common.MoreTypes.isTypeOf;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.isEmpty;
+import static dagger.internal.codegen.ComponentDescriptor.isComponentContributionMethod;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.RequestKinds.getRequestKind;
+import static dagger.internal.codegen.SourceFiles.generatedMonitoringModuleName;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.model.BindingKind.DELEGATE;
+import static dagger.model.BindingKind.INJECTION;
+import static dagger.model.BindingKind.OPTIONAL;
+import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
+import static dagger.model.RequestKind.MEMBERS_INJECTION;
+import static java.util.function.Predicate.isEqual;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.Sets;
+import dagger.MembersInjector;
+import dagger.Reusable;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.Scope;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import dagger.producers.internal.ProductionExecutorModule;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Queue;
+import java.util.Set;
+import java.util.function.Function;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+/** A factory for {@link BindingGraph} objects. */
+@Singleton
+final class BindingGraphFactory implements ClearableCache {
+  private final DaggerElements elements;
+  private final InjectBindingRegistry injectBindingRegistry;
+  private final KeyFactory keyFactory;
+  private final BindingFactory bindingFactory;
+  private final ModuleDescriptor.Factory moduleDescriptorFactory;
+  private final Map<Key, ImmutableSet<Key>> keysMatchingRequestCache = new HashMap<>();
+
+  @Inject
+  BindingGraphFactory(
+      DaggerElements elements,
+      InjectBindingRegistry injectBindingRegistry,
+      KeyFactory keyFactory,
+      BindingFactory bindingFactory,
+      ModuleDescriptor.Factory moduleDescriptorFactory) {
+    this.elements = elements;
+    this.injectBindingRegistry = injectBindingRegistry;
+    this.keyFactory = keyFactory;
+    this.bindingFactory = bindingFactory;
+    this.moduleDescriptorFactory = moduleDescriptorFactory;
+  }
+
+  /**
+   * Creates a binding graph for a component.
+   *
+   * @param createFullBindingGraph if {@code true}, the binding graph will include all bindings;
+   *     otherwise it will include only bindings reachable from at least one entry point
+   */
+  BindingGraph create(ComponentDescriptor componentDescriptor, boolean createFullBindingGraph) {
+    return create(Optional.empty(), componentDescriptor, createFullBindingGraph);
+  }
+
+  private BindingGraph create(
+      Optional<Resolver> parentResolver,
+      ComponentDescriptor componentDescriptor,
+      boolean createFullBindingGraph) {
+    ImmutableSet.Builder<ContributionBinding> explicitBindingsBuilder = ImmutableSet.builder();
+    ImmutableSet.Builder<DelegateDeclaration> delegatesBuilder = ImmutableSet.builder();
+    ImmutableSet.Builder<OptionalBindingDeclaration> optionalsBuilder = ImmutableSet.builder();
+
+    if (componentDescriptor.isRealComponent()) {
+      // binding for the component itself
+      explicitBindingsBuilder.add(
+          bindingFactory.componentBinding(componentDescriptor.typeElement()));
+    }
+
+    // Collect Component dependencies.
+    for (ComponentRequirement dependency : componentDescriptor.dependencies()) {
+      explicitBindingsBuilder.add(bindingFactory.componentDependencyBinding(dependency));
+      List<ExecutableElement> dependencyMethods =
+          methodsIn(elements.getAllMembers(dependency.typeElement()));
+      for (ExecutableElement method : dependencyMethods) {
+        // MembersInjection methods aren't "provided" explicitly, so ignore them.
+        if (isComponentContributionMethod(elements, method)) {
+          explicitBindingsBuilder.add(
+              bindingFactory.componentDependencyMethodBinding(componentDescriptor, method));
+        }
+      }
+    }
+
+    // Collect bindings on the creator.
+    componentDescriptor
+        .creatorDescriptor()
+        .ifPresent(
+            creatorDescriptor ->
+                creatorDescriptor.boundInstanceRequirements().stream()
+                    .map(
+                        requirement ->
+                            bindingFactory.boundInstanceBinding(
+                                requirement, creatorDescriptor.elementForRequirement(requirement)))
+                    .forEach(explicitBindingsBuilder::add));
+
+    componentDescriptor
+        .childComponentsDeclaredByBuilderEntryPoints()
+        .forEach(
+            (builderEntryPoint, childComponent) -> {
+              if (!componentDescriptor
+                  .childComponentsDeclaredByModules()
+                  .contains(childComponent)) {
+                explicitBindingsBuilder.add(
+                    bindingFactory.subcomponentCreatorBinding(
+                        builderEntryPoint.methodElement(), componentDescriptor.typeElement()));
+              }
+            });
+
+    ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations = ImmutableSet.builder();
+    ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarations = ImmutableSet.builder();
+
+    // Collect transitive module bindings and multibinding declarations.
+    for (ModuleDescriptor moduleDescriptor : modules(componentDescriptor, parentResolver)) {
+      explicitBindingsBuilder.addAll(moduleDescriptor.bindings());
+      multibindingDeclarations.addAll(moduleDescriptor.multibindingDeclarations());
+      subcomponentDeclarations.addAll(moduleDescriptor.subcomponentDeclarations());
+      delegatesBuilder.addAll(moduleDescriptor.delegateDeclarations());
+      optionalsBuilder.addAll(moduleDescriptor.optionalDeclarations());
+    }
+
+    final Resolver requestResolver =
+        new Resolver(
+            parentResolver,
+            componentDescriptor,
+            indexBindingDeclarationsByKey(explicitBindingsBuilder.build()),
+            indexBindingDeclarationsByKey(multibindingDeclarations.build()),
+            indexBindingDeclarationsByKey(subcomponentDeclarations.build()),
+            indexBindingDeclarationsByKey(delegatesBuilder.build()),
+            indexBindingDeclarationsByKey(optionalsBuilder.build()));
+
+    componentDescriptor.entryPointMethods().stream()
+        .map(method -> method.dependencyRequest().get())
+        .forEach(
+            entryPoint -> {
+              if (entryPoint.kind().equals(MEMBERS_INJECTION)) {
+                requestResolver.resolveMembersInjection(entryPoint.key());
+              } else {
+                requestResolver.resolve(entryPoint.key());
+              }
+            });
+
+    if (createFullBindingGraph) {
+      // Resolve the keys for all bindings in all modules, stripping any multibinding contribution
+      // identifier so that the multibinding itself is resolved.
+      modules(componentDescriptor, parentResolver).stream()
+          .flatMap(module -> module.allBindingKeys().stream())
+          .map(key -> key.toBuilder().multibindingContributionIdentifier(Optional.empty()).build())
+          .forEach(requestResolver::resolve);
+    }
+
+    // Resolve all bindings for subcomponents, creating subgraphs for all subcomponents that have
+    // been detected during binding resolution. If a binding for a subcomponent is never resolved,
+    // no BindingGraph will be created for it and no implementation will be generated. This is
+    // done in a queue since resolving one subcomponent might resolve a key for a subcomponent
+    // from a parent graph. This is done until no more new subcomponents are resolved.
+    Set<ComponentDescriptor> resolvedSubcomponents = new HashSet<>();
+    ImmutableList.Builder<BindingGraph> subgraphs = ImmutableList.builder();
+    for (ComponentDescriptor subcomponent :
+        Iterables.consumingIterable(requestResolver.subcomponentsToResolve)) {
+      if (resolvedSubcomponents.add(subcomponent)) {
+        subgraphs.add(create(Optional.of(requestResolver), subcomponent, createFullBindingGraph));
+      }
+    }
+
+    return BindingGraph.create(
+        componentDescriptor,
+        requestResolver.getResolvedContributionBindings(),
+        requestResolver.getResolvedMembersInjectionBindings(),
+        subgraphs.build(),
+        requestResolver.getOwnedModules(),
+        requestResolver.getFactoryMethod(),
+        createFullBindingGraph);
+  }
+
+  /**
+   * Returns all the modules that should be installed in the component. For production components
+   * and production subcomponents that have a parent that is not a production component or
+   * subcomponent, also includes the production monitoring module for the component and the
+   * production executor module.
+   */
+  private ImmutableSet<ModuleDescriptor> modules(
+      ComponentDescriptor componentDescriptor, Optional<Resolver> parentResolver) {
+    return shouldIncludeImplicitProductionModules(componentDescriptor, parentResolver)
+        ? new ImmutableSet.Builder<ModuleDescriptor>()
+            .addAll(componentDescriptor.modules())
+            .add(descriptorForMonitoringModule(componentDescriptor.typeElement()))
+            .add(descriptorForProductionExecutorModule())
+            .build()
+        : componentDescriptor.modules();
+  }
+
+  private boolean shouldIncludeImplicitProductionModules(
+      ComponentDescriptor component, Optional<Resolver> parentResolver) {
+    return component.isProduction()
+        && ((!component.isSubcomponent() && component.isRealComponent())
+            || (parentResolver.isPresent()
+                && !parentResolver.get().componentDescriptor.isProduction()));
+  }
+
+  /**
+   * Returns a descriptor for a generated module that handles monitoring for production components.
+   * This module is generated in the {@link MonitoringModuleProcessingStep}.
+   *
+   * @throws TypeNotPresentException if the module has not been generated yet. This will cause the
+   *     processor to retry in a later processing round.
+   */
+  private ModuleDescriptor descriptorForMonitoringModule(TypeElement componentDefinitionType) {
+    return moduleDescriptorFactory.create(
+        elements.checkTypePresent(
+            generatedMonitoringModuleName(componentDefinitionType).toString()));
+  }
+
+  /** Returns a descriptor {@link ProductionExecutorModule}. */
+  private ModuleDescriptor descriptorForProductionExecutorModule() {
+    return moduleDescriptorFactory.create(elements.getTypeElement(ProductionExecutorModule.class));
+  }
+
+  /** Indexes {@code bindingDeclarations} by {@link BindingDeclaration#key()}. */
+  private static <T extends BindingDeclaration>
+      ImmutableSetMultimap<Key, T> indexBindingDeclarationsByKey(Iterable<T> declarations) {
+    return ImmutableSetMultimap.copyOf(Multimaps.index(declarations, BindingDeclaration::key));
+  }
+
+  @Override
+  public void clearCache() {
+    keysMatchingRequestCache.clear();
+  }
+
+  private final class Resolver {
+    final Optional<Resolver> parentResolver;
+    final ComponentDescriptor componentDescriptor;
+    final ImmutableSetMultimap<Key, ContributionBinding> explicitBindings;
+    final ImmutableSet<ContributionBinding> explicitBindingsSet;
+    final ImmutableSetMultimap<Key, ContributionBinding> explicitMultibindings;
+    final ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations;
+    final ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations;
+    final ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations;
+    final ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations;
+    final ImmutableSetMultimap<Key, DelegateDeclaration> delegateMultibindingDeclarations;
+    final Map<Key, ResolvedBindings> resolvedContributionBindings = new LinkedHashMap<>();
+    final Map<Key, ResolvedBindings> resolvedMembersInjectionBindings = new LinkedHashMap<>();
+    final Deque<Key> cycleStack = new ArrayDeque<>();
+    final Map<Key, Boolean> keyDependsOnLocalBindingsCache = new HashMap<>();
+    final Map<Binding, Boolean> bindingDependsOnLocalBindingsCache = new HashMap<>();
+    final Queue<ComponentDescriptor> subcomponentsToResolve = new ArrayDeque<>();
+
+    Resolver(
+        Optional<Resolver> parentResolver,
+        ComponentDescriptor componentDescriptor,
+        ImmutableSetMultimap<Key, ContributionBinding> explicitBindings,
+        ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations,
+        ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations,
+        ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations,
+        ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations) {
+      this.parentResolver = parentResolver;
+      this.componentDescriptor = checkNotNull(componentDescriptor);
+      this.explicitBindings = checkNotNull(explicitBindings);
+      this.explicitBindingsSet = ImmutableSet.copyOf(explicitBindings.values());
+      this.multibindingDeclarations = checkNotNull(multibindingDeclarations);
+      this.subcomponentDeclarations = checkNotNull(subcomponentDeclarations);
+      this.delegateDeclarations = checkNotNull(delegateDeclarations);
+      this.optionalBindingDeclarations = checkNotNull(optionalBindingDeclarations);
+      this.explicitMultibindings = multibindingContributionsByMultibindingKey(explicitBindingsSet);
+      this.delegateMultibindingDeclarations =
+          multibindingContributionsByMultibindingKey(delegateDeclarations.values());
+      subcomponentsToResolve.addAll(
+          componentDescriptor.childComponentsDeclaredByFactoryMethods().values());
+      subcomponentsToResolve.addAll(
+          componentDescriptor.childComponentsDeclaredByBuilderEntryPoints().values());
+    }
+
+    /** Returns the optional factory method for this component. */
+    Optional<ExecutableElement> getFactoryMethod() {
+      return parentResolver
+          .flatMap(
+              parent ->
+                  parent.componentDescriptor.getFactoryMethodForChildComponent(componentDescriptor))
+          .map(method -> method.methodElement());
+    }
+
+    /**
+     * Returns the resolved contribution bindings for the given {@link Key}:
+     *
+     * <ul>
+     *   <li>All explicit bindings for:
+     *       <ul>
+     *         <li>the requested key
+     *         <li>{@code Set<T>} if the requested key's type is {@code Set<Produced<T>>}
+     *         <li>{@code Map<K, Provider<V>>} if the requested key's type is {@code Map<K,
+     *             Producer<V>>}.
+     *       </ul>
+     *   <li>A synthetic binding that depends on {@code Map<K, Producer<V>>} if the requested key's
+     *       type is {@code Map<K, V>} and there are some explicit bindings for {@code Map<K,
+     *       Producer<V>>}.
+     *   <li>A synthetic binding that depends on {@code Map<K, Provider<V>>} if the requested key's
+     *       type is {@code Map<K, V>} and there are some explicit bindings for {@code Map<K,
+     *       Provider<V>>} but no explicit bindings for {@code Map<K, Producer<V>>}.
+     *   <li>An implicit {@link Inject @Inject}-annotated constructor binding if there is one and
+     *       there are no explicit bindings or synthetic bindings.
+     * </ul>
+     */
+    ResolvedBindings lookUpBindings(Key requestKey) {
+      Set<ContributionBinding> bindings = new LinkedHashSet<>();
+      bindings.addAll(getExplicitBindings(requestKey));
+
+      ImmutableSet<ContributionBinding> multibindingContributions =
+          getAllMatchingBindingDeclarations(requestKey, this::getExplicitMultibindings);
+      ImmutableSet<MultibindingDeclaration> multibindingDeclarations =
+          getAllMatchingBindingDeclarations(requestKey, this::getMultibindingDeclarations);
+
+      syntheticMultibinding(requestKey, multibindingContributions, multibindingDeclarations)
+          .ifPresent(bindings::add);
+
+      ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations =
+          getAllMatchingBindingDeclarations(requestKey, this::getOptionalBindingDeclarations);
+      syntheticOptionalBinding(requestKey, optionalBindingDeclarations).ifPresent(bindings::add);
+
+      ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations =
+          getSubcomponentDeclarations(requestKey);
+      syntheticSubcomponentBuilderBinding(subcomponentDeclarations)
+          .ifPresent(
+              binding -> {
+                bindings.add(binding);
+                addSubcomponentToOwningResolver(binding);
+              });
+
+      if (isType(requestKey.type()) && isTypeOf(MembersInjector.class, requestKey.type())) {
+        injectBindingRegistry
+            .getOrFindMembersInjectorProvisionBinding(requestKey)
+            .ifPresent(bindings::add);
+      }
+
+      // If there are no bindings, add the implicit @Inject-constructed binding if there is one.
+      if (bindings.isEmpty()) {
+        injectBindingRegistry.getOrFindProvisionBinding(requestKey)
+            .filter(binding -> !isIncorrectlyScopedInPartialGraph(binding))
+            .ifPresent(bindings::add);
+      }
+
+      return ResolvedBindings.forContributionBindings(
+          requestKey,
+          indexBindingsByOwningComponent(requestKey, ImmutableSet.copyOf(bindings)),
+          multibindingDeclarations,
+          subcomponentDeclarations,
+          optionalBindingDeclarations);
+    }
+
+    /**
+     * Returns true if this binding graph resolution is for a partial graph and the {@code @Inject}
+     * binding's scope doesn't match any of the components in the current component ancestry. If so,
+     * the binding is not owned by any of the currently known components, and will be owned by a
+     * future ancestor (or, if never owned, will result in an incompatibly scoped binding error at
+     * the root component).
+     */
+    private boolean isIncorrectlyScopedInPartialGraph(ProvisionBinding binding) {
+      checkArgument(binding.kind().equals(INJECTION));
+      Resolver owningResolver = getOwningResolver(binding).orElse(this);
+      ComponentDescriptor owningComponent = owningResolver.componentDescriptor;
+      return rootComponent().isSubcomponent()
+          && binding.scope().isPresent()
+          && !binding.scope().get().isReusable()
+          && !owningComponent.scopes().contains(binding.scope().get());
+    }
+
+    private ComponentDescriptor rootComponent() {
+      return parentResolver.map(Resolver::rootComponent).orElse(componentDescriptor);
+    }
+
+    /** Returns the resolved members injection bindings for the given {@link Key}. */
+    ResolvedBindings lookUpMembersInjectionBinding(Key requestKey) {
+      // no explicit deps for members injection, so just look it up
+      Optional<MembersInjectionBinding> binding =
+          injectBindingRegistry.getOrFindMembersInjectionBinding(requestKey);
+      return binding.isPresent()
+          ? ResolvedBindings.forMembersInjectionBinding(
+              requestKey, componentDescriptor, binding.get())
+          : ResolvedBindings.noBindings(requestKey);
+    }
+
+    /**
+     * When a binding is resolved for a {@link SubcomponentDeclaration}, adds corresponding {@link
+     * ComponentDescriptor subcomponent} to a queue in the owning component's resolver. The queue
+     * will be used to detect which subcomponents need to be resolved.
+     */
+    private void addSubcomponentToOwningResolver(ProvisionBinding subcomponentCreatorBinding) {
+      checkArgument(subcomponentCreatorBinding.kind().equals(SUBCOMPONENT_CREATOR));
+      Resolver owningResolver = getOwningResolver(subcomponentCreatorBinding).get();
+
+      TypeElement builderType = MoreTypes.asTypeElement(subcomponentCreatorBinding.key().type());
+      owningResolver.subcomponentsToResolve.add(
+          owningResolver.componentDescriptor.getChildComponentWithBuilderType(builderType));
+    }
+
+    /**
+     * Profiling has determined that computing the keys matching {@code requestKey} has measurable
+     * performance impact. It is called repeatedly (at least 3 times per key resolved per {@link
+     * BindingGraph}. {@code javac}'s name-checking performance seems suboptimal (converting byte
+     * strings to Strings repeatedly), and the matching keys creations relies on that. This also
+     * ensures that the resulting keys have their hash codes cached on successive calls to this
+     * method.
+     *
+     * <p>This caching may become obsolete if:
+     *
+     * <ul>
+     *   <li>We decide to intern all {@link Key} instances
+     *   <li>We fix javac's name-checking peformance (though we may want to keep this for older
+     *       javac users)
+     * </ul>
+     */
+    private ImmutableSet<Key> keysMatchingRequest(Key requestKey) {
+      return keysMatchingRequestCache.computeIfAbsent(
+          requestKey, this::keysMatchingRequestUncached);
+    }
+
+    private ImmutableSet<Key> keysMatchingRequestUncached(Key requestKey) {
+      ImmutableSet.Builder<Key> keys = ImmutableSet.builder();
+      keys.add(requestKey);
+      keyFactory.unwrapSetKey(requestKey, Produced.class).ifPresent(keys::add);
+      keyFactory.rewrapMapKey(requestKey, Producer.class, Provider.class).ifPresent(keys::add);
+      keyFactory.rewrapMapKey(requestKey, Provider.class, Producer.class).ifPresent(keys::add);
+      keys.addAll(keyFactory.implicitFrameworkMapKeys(requestKey));
+      return keys.build();
+    }
+
+    /**
+     * Returns a synthetic binding that depends on individual multibinding contributions.
+     *
+     * <p>If there are no {@code multibindingContributions} or {@code multibindingDeclarations},
+     * returns {@link Optional#empty()}.
+     *
+     * <p>If there are production {@code multibindingContributions} or the request is for any of the
+     * following types, returns a {@link ProductionBinding}.
+     *
+     * <ul>
+     *   <li>{@code Set<Produced<T>>}
+     *   <li>{@code Map<K, Producer<V>>}
+     *   <li>{@code Map<K, Produced<V>>}
+     * </ul>
+     *
+     * Otherwise, returns a {@link ProvisionBinding}.
+     */
+    private Optional<ContributionBinding> syntheticMultibinding(
+        Key key,
+        Iterable<ContributionBinding> multibindingContributions,
+        Iterable<MultibindingDeclaration> multibindingDeclarations) {
+      return isEmpty(multibindingContributions) && isEmpty(multibindingDeclarations)
+          ? Optional.empty()
+          : Optional.of(bindingFactory.syntheticMultibinding(key, multibindingContributions));
+    }
+
+    private Optional<ProvisionBinding> syntheticSubcomponentBuilderBinding(
+        ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
+      return subcomponentDeclarations.isEmpty()
+          ? Optional.empty()
+          : Optional.of(bindingFactory.subcomponentCreatorBinding(subcomponentDeclarations));
+    }
+
+    /**
+     * Returns a synthetic binding for {@code @Qualifier Optional<Type>} if there are any {@code
+     * optionalBindingDeclarations}.
+     *
+     * <p>If there are no bindings for the underlying key (the key for dependency requests for
+     * {@code Type}), returns a provision binding that always returns {@link Optional#empty()}.
+     *
+     * <p>If there are any production bindings for the underlying key, returns a production binding.
+     * Otherwise returns a provision binding.
+     */
+    private Optional<ContributionBinding> syntheticOptionalBinding(
+        Key key, ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations) {
+      return optionalBindingDeclarations.isEmpty()
+          ? Optional.empty()
+          : Optional.of(
+              bindingFactory.syntheticOptionalBinding(
+                  key,
+                  getRequestKind(OptionalType.from(key).valueType()),
+                  lookUpBindings(keyFactory.unwrapOptional(key).get())));
+    }
+
+    private ImmutableSet<ContributionBinding> createDelegateBindings(
+        ImmutableSet<DelegateDeclaration> delegateDeclarations) {
+      ImmutableSet.Builder<ContributionBinding> builder = ImmutableSet.builder();
+      for (DelegateDeclaration delegateDeclaration : delegateDeclarations) {
+        builder.add(createDelegateBinding(delegateDeclaration));
+      }
+      return builder.build();
+    }
+
+    /**
+     * Creates one (and only one) delegate binding for a delegate declaration, based on the resolved
+     * bindings of the right-hand-side of a {@link dagger.Binds} method. If there are duplicate
+     * bindings for the dependency key, there should still be only one binding for the delegate key.
+     */
+    private ContributionBinding createDelegateBinding(DelegateDeclaration delegateDeclaration) {
+      Key delegateKey = delegateDeclaration.delegateRequest().key();
+      if (cycleStack.contains(delegateKey)) {
+        return bindingFactory.unresolvedDelegateBinding(delegateDeclaration);
+      }
+
+      ResolvedBindings resolvedDelegate;
+      try {
+        cycleStack.push(delegateKey);
+        resolvedDelegate = lookUpBindings(delegateKey);
+      } finally {
+        cycleStack.pop();
+      }
+      if (resolvedDelegate.contributionBindings().isEmpty()) {
+        // This is guaranteed to result in a missing binding error, so it doesn't matter if the
+        // binding is a Provision or Production, except if it is a @IntoMap method, in which
+        // case the key will be of type Map<K, Provider<V>>, which will be "upgraded" into a
+        // Map<K, Producer<V>> if it's requested in a ProductionComponent. This may result in a
+        // strange error, that the RHS needs to be provided with an @Inject or @Provides
+        // annotated method, but a user should be able to figure out if a @Produces annotation
+        // is needed.
+        // TODO(gak): revisit how we model missing delegates if/when we clean up how we model
+        // binding declarations
+        return bindingFactory.unresolvedDelegateBinding(delegateDeclaration);
+      }
+      // It doesn't matter which of these is selected, since they will later on produce a
+      // duplicate binding error.
+      ContributionBinding explicitDelegate =
+          resolvedDelegate.contributionBindings().iterator().next();
+      return bindingFactory.delegateBinding(delegateDeclaration, explicitDelegate);
+    }
+
+    // TODO(dpb,ronshapiro): requestKey appears to be interchangeable with each binding's .key(),
+    // but should it? We're currently conflating the two all over the place and it would be good
+    // to unify, or if it's necessary, clarify why with docs+tests. Specifically, should we also
+    // be checking these for keysMatchingRequest?
+    private ImmutableSetMultimap<TypeElement, ContributionBinding> indexBindingsByOwningComponent(
+        Key requestKey, Iterable<? extends ContributionBinding> bindings) {
+      ImmutableSetMultimap.Builder<TypeElement, ContributionBinding> index =
+          ImmutableSetMultimap.builder();
+      for (ContributionBinding binding : bindings) {
+        index.put(getOwningComponent(requestKey, binding), binding);
+      }
+      return index.build();
+    }
+
+    /**
+     * Returns the component that should contain the framework field for {@code binding}.
+     *
+     * <p>If {@code binding} is either not bound in an ancestor component or depends transitively on
+     * bindings in this component, returns this component.
+     *
+     * <p>Otherwise, resolves {@code request} in this component's parent in order to resolve any
+     * multibinding contributions in the parent, and returns the parent-resolved {@link
+     * ResolvedBindings#owningComponent(ContributionBinding)}.
+     */
+    private TypeElement getOwningComponent(Key requestKey, ContributionBinding binding) {
+      if (isResolvedInParent(requestKey, binding)
+          && !new LocalDependencyChecker().dependsOnLocalBindings(binding)) {
+        ResolvedBindings parentResolvedBindings =
+            parentResolver.get().resolvedContributionBindings.get(requestKey);
+        return parentResolvedBindings.owningComponent(binding);
+      } else {
+        return componentDescriptor.typeElement();
+      }
+    }
+
+    /**
+     * Returns {@code true} if {@code binding} is owned by an ancestor. If so, {@linkplain #resolve
+     * resolves} the {@link Key} in this component's parent. Don't resolve directly in the owning
+     * component in case it depends on multibindings in any of its descendants.
+     */
+    private boolean isResolvedInParent(Key requestKey, ContributionBinding binding) {
+      Optional<Resolver> owningResolver = getOwningResolver(binding);
+      if (owningResolver.isPresent() && !owningResolver.get().equals(this)) {
+        parentResolver.get().resolve(requestKey);
+        return true;
+      } else {
+        return false;
+      }
+    }
+
+    private Optional<Resolver> getOwningResolver(ContributionBinding binding) {
+      // TODO(ronshapiro): extract the different pieces of this method into their own methods
+      if ((binding.scope().isPresent() && binding.scope().get().isProductionScope())
+          || binding.bindingType().equals(BindingType.PRODUCTION)) {
+        for (Resolver requestResolver : getResolverLineage()) {
+          // Resolve @Inject @ProductionScope bindings at the highest production component.
+          if (binding.kind().equals(INJECTION)
+              && requestResolver.componentDescriptor.isProduction()) {
+            return Optional.of(requestResolver);
+          }
+
+          // Resolve explicit @Produces and @ProductionScope bindings at the highest component that
+          // installs the binding.
+          if (requestResolver.containsExplicitBinding(binding)) {
+            return Optional.of(requestResolver);
+          }
+        }
+      }
+
+      if (binding.scope().isPresent() && binding.scope().get().isReusable()) {
+        for (Resolver requestResolver : getResolverLineage().reverse()) {
+          // If a @Reusable binding was resolved in an ancestor, use that component.
+          ResolvedBindings resolvedBindings =
+              requestResolver.resolvedContributionBindings.get(binding.key());
+          if (resolvedBindings != null
+              && resolvedBindings.contributionBindings().contains(binding)) {
+            return Optional.of(requestResolver);
+          }
+        }
+        // If a @Reusable binding was not resolved in any ancestor, resolve it here.
+        return Optional.empty();
+      }
+
+      for (Resolver requestResolver : getResolverLineage().reverse()) {
+        if (requestResolver.containsExplicitBinding(binding)) {
+          return Optional.of(requestResolver);
+        }
+      }
+
+      // look for scope separately.  we do this for the case where @Singleton can appear twice
+      // in the † compatibility mode
+      Optional<Scope> bindingScope = binding.scope();
+      if (bindingScope.isPresent()) {
+        for (Resolver requestResolver : getResolverLineage().reverse()) {
+          if (requestResolver.componentDescriptor.scopes().contains(bindingScope.get())) {
+            return Optional.of(requestResolver);
+          }
+        }
+      }
+      return Optional.empty();
+    }
+
+    private boolean containsExplicitBinding(ContributionBinding binding) {
+      return explicitBindingsSet.contains(binding)
+          || resolverContainsDelegateDeclarationForBinding(binding)
+          || subcomponentDeclarations.containsKey(binding.key());
+    }
+
+    /** Returns true if {@code binding} was installed in a module in this resolver's component. */
+    private boolean resolverContainsDelegateDeclarationForBinding(ContributionBinding binding) {
+      return binding.kind().equals(DELEGATE)
+          && delegateDeclarations.get(binding.key()).stream()
+              .anyMatch(
+                  declaration ->
+                      declaration.contributingModule().equals(binding.contributingModule())
+                          && declaration.bindingElement().equals(binding.bindingElement()));
+    }
+
+    /** Returns the resolver lineage from parent to child. */
+    private ImmutableList<Resolver> getResolverLineage() {
+      ImmutableList.Builder<Resolver> resolverList = ImmutableList.builder();
+      for (Optional<Resolver> currentResolver = Optional.of(this);
+          currentResolver.isPresent();
+          currentResolver = currentResolver.get().parentResolver) {
+        resolverList.add(currentResolver.get());
+      }
+      return resolverList.build().reverse();
+    }
+
+    /**
+     * For all {@linkplain #keysMatchingRequest(Key) keys matching {@code requestKey}}, applies
+     * {@code getDeclarationsPerKey} and collects the values into an {@link ImmutableSet}.
+     */
+    private <T extends BindingDeclaration> ImmutableSet<T> getAllMatchingBindingDeclarations(
+        Key requestKey, Function<Key, Collection<T>> getDeclarationsPerKey) {
+      return keysMatchingRequest(requestKey)
+          .stream()
+          .flatMap(key -> getDeclarationsPerKey.apply(key).stream())
+          .collect(toImmutableSet());
+    }
+
+    /**
+     * Returns the explicit {@link ContributionBinding}s that match the {@code key} from this and
+     * all ancestor resolvers.
+     */
+    private ImmutableSet<ContributionBinding> getExplicitBindings(Key key) {
+      ImmutableSet.Builder<ContributionBinding> bindings = ImmutableSet.builder();
+      for (Resolver resolver : getResolverLineage()) {
+        bindings.addAll(resolver.getLocalExplicitBindings(key));
+      }
+      return bindings.build();
+    }
+
+    /**
+     * Returns the explicit {@link ContributionBinding}s that match the {@code key} from this
+     * resolver.
+     */
+    private ImmutableSet<ContributionBinding> getLocalExplicitBindings(Key key) {
+      return new ImmutableSet.Builder<ContributionBinding>()
+          .addAll(explicitBindings.get(key))
+          // @Binds @IntoMap declarations have key Map<K, V>, unlike @Provides @IntoMap or @Produces
+          // @IntoMap, which have Map<K, Provider/Producer<V>> keys. So unwrap the key's type's
+          // value type if it's a Map<K, Provider/Producer<V>> before looking in
+          // delegateDeclarations. createDelegateBindings() will create bindings with the properly
+          // wrapped key type.
+          .addAll(
+              createDelegateBindings(delegateDeclarations.get(keyFactory.unwrapMapValueType(key))))
+          .build();
+    }
+
+    /**
+     * Returns the explicit multibinding contributions that contribute to the map or set requested
+     * by {@code key} from this and all ancestor resolvers.
+     */
+    private ImmutableSet<ContributionBinding> getExplicitMultibindings(Key key) {
+      ImmutableSet.Builder<ContributionBinding> multibindings = ImmutableSet.builder();
+      for (Resolver resolver : getResolverLineage()) {
+        multibindings.addAll(resolver.getLocalExplicitMultibindings(key));
+      }
+      return multibindings.build();
+    }
+
+    /**
+     * Returns the explicit multibinding contributions that contribute to the map or set requested
+     * by {@code key} from this resolver.
+     */
+    private ImmutableSet<ContributionBinding> getLocalExplicitMultibindings(Key key) {
+      ImmutableSet.Builder<ContributionBinding> multibindings = ImmutableSet.builder();
+      multibindings.addAll(explicitMultibindings.get(key));
+      if (!MapType.isMap(key)
+          || MapType.from(key).isRawType()
+          || MapType.from(key).valuesAreFrameworkType()) {
+        // @Binds @IntoMap declarations have key Map<K, V>, unlike @Provides @IntoMap or @Produces
+        // @IntoMap, which have Map<K, Provider/Producer<V>> keys. So unwrap the key's type's
+        // value type if it's a Map<K, Provider/Producer<V>> before looking in
+        // delegateMultibindingDeclarations. createDelegateBindings() will create bindings with the
+        // properly wrapped key type.
+        multibindings.addAll(
+            createDelegateBindings(
+                delegateMultibindingDeclarations.get(keyFactory.unwrapMapValueType(key))));
+      }
+      return multibindings.build();
+    }
+
+    /**
+     * Returns the {@link MultibindingDeclaration}s that match the {@code key} from this and all
+     * ancestor resolvers.
+     */
+    private ImmutableSet<MultibindingDeclaration> getMultibindingDeclarations(Key key) {
+      ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations =
+          ImmutableSet.builder();
+      for (Resolver resolver : getResolverLineage()) {
+        multibindingDeclarations.addAll(resolver.multibindingDeclarations.get(key));
+      }
+      return multibindingDeclarations.build();
+    }
+
+    /**
+     * Returns the {@link SubcomponentDeclaration}s that match the {@code key} from this and all
+     * ancestor resolvers.
+     */
+    private ImmutableSet<SubcomponentDeclaration> getSubcomponentDeclarations(Key key) {
+      ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarations =
+          ImmutableSet.builder();
+      for (Resolver resolver : getResolverLineage()) {
+        subcomponentDeclarations.addAll(resolver.subcomponentDeclarations.get(key));
+      }
+      return subcomponentDeclarations.build();
+    }
+    /**
+     * Returns the {@link OptionalBindingDeclaration}s that match the {@code key} from this and all
+     * ancestor resolvers.
+     */
+    private ImmutableSet<OptionalBindingDeclaration> getOptionalBindingDeclarations(Key key) {
+      Optional<Key> unwrapped = keyFactory.unwrapOptional(key);
+      if (!unwrapped.isPresent()) {
+        return ImmutableSet.of();
+      }
+      ImmutableSet.Builder<OptionalBindingDeclaration> declarations = ImmutableSet.builder();
+      for (Resolver resolver : getResolverLineage()) {
+        declarations.addAll(resolver.optionalBindingDeclarations.get(unwrapped.get()));
+      }
+      return declarations.build();
+    }
+
+    /**
+     * Returns the {@link ResolvedBindings} for {@code key} that was resolved in this resolver or an
+     * ancestor resolver. Only checks for {@link ContributionBinding}s as {@link
+     * MembersInjectionBinding}s are not inherited.
+     */
+    private Optional<ResolvedBindings> getPreviouslyResolvedBindings(Key key) {
+      Optional<ResolvedBindings> result =
+          Optional.ofNullable(resolvedContributionBindings.get(key));
+      if (result.isPresent()) {
+        return result;
+      } else if (parentResolver.isPresent()) {
+        return parentResolver.get().getPreviouslyResolvedBindings(key);
+      } else {
+        return Optional.empty();
+      }
+    }
+
+    private void resolveMembersInjection(Key key) {
+      ResolvedBindings bindings = lookUpMembersInjectionBinding(key);
+      resolveDependencies(bindings);
+      resolvedMembersInjectionBindings.put(key, bindings);
+    }
+
+    void resolve(Key key) {
+      // If we find a cycle, stop resolving. The original request will add it with all of the
+      // other resolved deps.
+      if (cycleStack.contains(key)) {
+        return;
+      }
+
+      // If the binding was previously resolved in this (sub)component, don't resolve it again.
+      if (resolvedContributionBindings.containsKey(key)) {
+        return;
+      }
+
+      /*
+       * If the binding was previously resolved in an ancestor component, then we may be able to
+       * avoid resolving it here and just depend on the ancestor component resolution.
+       *
+       * 1. If it depends transitively on multibinding contributions or optional bindings with
+       *    bindings from this subcomponent, then we have to resolve it in this subcomponent so
+       *    that it sees the local bindings.
+       *
+       * 2. If there are any explicit bindings in this component, they may conflict with those in
+       *    the ancestor component, so resolve them here so that conflicts can be caught.
+       */
+      if (getPreviouslyResolvedBindings(key).isPresent()) {
+        /* Resolve in the parent in case there are multibinding contributions or conflicts in some
+         * component between this one and the previously-resolved one. */
+        parentResolver.get().resolve(key);
+        if (!new LocalDependencyChecker().dependsOnLocalBindings(key)
+            && getLocalExplicitBindings(key).isEmpty()) {
+          /* Cache the inherited parent component's bindings in case resolving at the parent found
+           * bindings in some component between this one and the previously-resolved one. */
+          resolvedContributionBindings.put(key, getPreviouslyResolvedBindings(key).get());
+          return;
+        }
+      }
+
+      cycleStack.push(key);
+      try {
+        ResolvedBindings bindings = lookUpBindings(key);
+        resolvedContributionBindings.put(key, bindings);
+        resolveDependencies(bindings);
+      } finally {
+        cycleStack.pop();
+      }
+    }
+
+    /**
+     * {@link #resolve(Key) Resolves} each of the dependencies of the bindings owned by this
+     * component.
+     */
+    private void resolveDependencies(ResolvedBindings resolvedBindings) {
+      for (Binding binding : resolvedBindings.bindingsOwnedBy(componentDescriptor)) {
+        for (DependencyRequest dependency : binding.dependencies()) {
+          resolve(dependency.key());
+        }
+      }
+    }
+
+    /**
+     * Returns all of the {@link ResolvedBindings} for {@link ContributionBinding}s from this and
+     * all ancestor resolvers, indexed by {@link ResolvedBindings#key()}.
+     */
+    Map<Key, ResolvedBindings> getResolvedContributionBindings() {
+      Map<Key, ResolvedBindings> bindings = new LinkedHashMap<>();
+      parentResolver.ifPresent(parent -> bindings.putAll(parent.getResolvedContributionBindings()));
+      bindings.putAll(resolvedContributionBindings);
+      return bindings;
+    }
+
+    /**
+     * Returns all of the {@link ResolvedBindings} for {@link MembersInjectionBinding} from this
+     * resolvers, indexed by {@link ResolvedBindings#key()}.
+     */
+    ImmutableMap<Key, ResolvedBindings> getResolvedMembersInjectionBindings() {
+      return ImmutableMap.copyOf(resolvedMembersInjectionBindings);
+    }
+
+    ImmutableSet<ModuleDescriptor> getInheritedModules() {
+      return parentResolver.isPresent()
+          ? Sets.union(
+                  parentResolver.get().getInheritedModules(),
+                  parentResolver.get().componentDescriptor.modules())
+              .immutableCopy()
+          : ImmutableSet.<ModuleDescriptor>of();
+    }
+
+    ImmutableSet<ModuleDescriptor> getOwnedModules() {
+      return Sets.difference(componentDescriptor.modules(), getInheritedModules()).immutableCopy();
+    }
+
+    private final class LocalDependencyChecker {
+      private final Set<Object> cycleChecker = new HashSet<>();
+
+      /**
+       * Returns {@code true} if any of the bindings resolved for {@code key} are multibindings with
+       * contributions declared within this component's modules or optional bindings with present
+       * values declared within this component's modules, or if any of its unscoped dependencies
+       * depend on such bindings.
+       *
+       * <p>We don't care about scoped dependencies because they will never depend on bindings from
+       * subcomponents.
+       *
+       * @throws IllegalArgumentException if {@link #getPreviouslyResolvedBindings(Key)} is empty
+       */
+      boolean dependsOnLocalBindings(Key key) {
+        // Don't recur infinitely if there are valid cycles in the dependency graph.
+        // http://b/23032377
+        if (!cycleChecker.add(key)) {
+          return false;
+        }
+        return reentrantComputeIfAbsent(
+            keyDependsOnLocalBindingsCache, key, this::dependsOnLocalBindingsUncached);
+      }
+
+      private boolean dependsOnLocalBindingsUncached(Key key) {
+        checkArgument(
+            getPreviouslyResolvedBindings(key).isPresent(),
+            "no previously resolved bindings in %s for %s",
+            Resolver.this,
+            key);
+        ResolvedBindings previouslyResolvedBindings = getPreviouslyResolvedBindings(key).get();
+        if (hasLocalMultibindingContributions(key)
+            || hasLocalOptionalBindingContribution(previouslyResolvedBindings)) {
+          return true;
+        }
+
+        for (Binding binding : previouslyResolvedBindings.bindings()) {
+          if (dependsOnLocalBindings(binding)) {
+            return true;
+          }
+        }
+        return false;
+      }
+
+      /**
+       * Returns {@code true} if {@code binding} is unscoped (or has {@link Reusable @Reusable}
+       * scope) and depends on multibindings with contributions declared within this component's
+       * modules, or if any of its unscoped or {@link Reusable @Reusable} scoped dependencies depend
+       * on such local multibindings.
+       *
+       * <p>We don't care about non-reusable scoped dependencies because they will never depend on
+       * multibindings with contributions from subcomponents.
+       */
+      boolean dependsOnLocalBindings(Binding binding) {
+        if (!cycleChecker.add(binding)) {
+          return false;
+        }
+        return reentrantComputeIfAbsent(
+            bindingDependsOnLocalBindingsCache, binding, this::dependsOnLocalBindingsUncached);
+      }
+
+      private boolean dependsOnLocalBindingsUncached(Binding binding) {
+        if ((!binding.scope().isPresent() || binding.scope().get().isReusable())
+            // TODO(beder): Figure out what happens with production subcomponents.
+            && !binding.bindingType().equals(BindingType.PRODUCTION)) {
+          for (DependencyRequest dependency : binding.dependencies()) {
+            if (dependsOnLocalBindings(dependency.key())) {
+              return true;
+            }
+          }
+        }
+        return false;
+      }
+
+      /**
+       * Returns {@code true} if there is at least one multibinding contribution declared within
+       * this component's modules that matches the key.
+       */
+      private boolean hasLocalMultibindingContributions(Key requestKey) {
+        return keysMatchingRequest(requestKey)
+            .stream()
+            .anyMatch(key -> !getLocalExplicitMultibindings(key).isEmpty());
+      }
+
+      /**
+       * Returns {@code true} if there is a contribution in this component for an {@code
+       * Optional<Foo>} key that has not been contributed in a parent.
+       */
+      private boolean hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings) {
+        if (resolvedBindings
+            .contributionBindings()
+            .stream()
+            .map(ContributionBinding::kind)
+            .anyMatch(isEqual(OPTIONAL))) {
+          return !getLocalExplicitBindings(keyFactory.unwrapOptional(resolvedBindings.key()).get())
+              .isEmpty();
+        } else {
+          // If a parent contributes a @Provides Optional<Foo> binding and a child has a
+          // @BindsOptionalOf Foo method, the two should conflict, even if there is no binding for
+          // Foo on its own
+          return !getOptionalBindingDeclarations(resolvedBindings.key()).isEmpty();
+        }
+      }
+    }
+  }
+
+  /**
+   * A multimap of those {@code declarations} that are multibinding contribution declarations,
+   * indexed by the key of the set or map to which they contribute.
+   */
+  static <T extends BindingDeclaration>
+      ImmutableSetMultimap<Key, T> multibindingContributionsByMultibindingKey(
+          Iterable<T> declarations) {
+    ImmutableSetMultimap.Builder<Key, T> builder = ImmutableSetMultimap.builder();
+    for (T declaration : declarations) {
+      if (declaration.key().multibindingContributionIdentifier().isPresent()) {
+        builder.put(
+            declaration
+                .key()
+                .toBuilder()
+                .multibindingContributionIdentifier(Optional.empty())
+                .build(),
+            declaration);
+      }
+    }
+    return builder.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingGraphPlugins.java b/java/dagger/internal/codegen/BindingGraphPlugins.java
new file mode 100644
index 0000000..e2c3812
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingGraphPlugins.java
@@ -0,0 +1,77 @@
+/*
+ * 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 dagger.internal.codegen.DaggerStreams.toImmutableSet;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.spi.BindingGraphPlugin;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+
+/** Initializes {@link BindingGraphPlugin}s. */
+final class BindingGraphPlugins {
+  private final ImmutableSet<BindingGraphPlugin> plugins;
+  private final Filer filer;
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+  private final Map<String, String> processingOptions;
+
+  @Inject
+  BindingGraphPlugins(
+      @Validation Set<BindingGraphPlugin> validationPlugins,
+      ImmutableSet<BindingGraphPlugin> externalPlugins,
+      Filer filer,
+      DaggerTypes types,
+      DaggerElements elements,
+      @ProcessingOptions Map<String, String> processingOptions) {
+    this.plugins = Sets.union(validationPlugins, externalPlugins).immutableCopy();
+    this.filer = filer;
+    this.types = types;
+    this.elements = elements;
+    this.processingOptions = processingOptions;
+  }
+
+  /** Returns {@link BindingGraphPlugin#supportedOptions()} from all the plugins. */
+  ImmutableSet<String> allSupportedOptions() {
+    return plugins.stream()
+        .flatMap(plugin -> plugin.supportedOptions().stream())
+        .collect(toImmutableSet());
+  }
+
+  /** Initializes the plugins. */
+  // TODO(ronshapiro): Should we validate the uniqueness of plugin names?
+  void initializePlugins() {
+    plugins.forEach(this::initializePlugin);
+  }
+
+  private void initializePlugin(BindingGraphPlugin plugin) {
+    plugin.initFiler(filer);
+    plugin.initTypes(types);
+    plugin.initElements(elements);
+    Set<String> supportedOptions = plugin.supportedOptions();
+    if (!supportedOptions.isEmpty()) {
+      plugin.initOptions(Maps.filterKeys(processingOptions, supportedOptions::contains));
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingGraphStatisticsCollector.java b/java/dagger/internal/codegen/BindingGraphStatisticsCollector.java
new file mode 100644
index 0000000..129647f
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingGraphStatisticsCollector.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 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.errorprone.util.ASTHelpers.getSymbol;
+import static dagger.internal.codegen.ComponentAnnotation.rootComponentAnnotation;
+
+import com.google.errorprone.VisitorState;
+import com.google.errorprone.bugpatterns.BugChecker;
+import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
+import com.google.errorprone.matchers.Description;
+import com.sun.source.tree.ClassTree;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.util.Context;
+import dagger.BindsInstance;
+import dagger.Component;
+import dagger.model.BindingGraph;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/** A {@link BugChecker} that collects statistics derived from a {@link BindingGraph}. */
+public abstract class BindingGraphStatisticsCollector extends BugChecker
+    implements ClassTreeMatcher {
+  private BindingGraphConverter bindingGraphConverter;
+  private BindingGraphFactory bindingGraphFactory;
+  private ComponentDescriptorFactory componentDescriptorFactory;
+  private boolean isInjected;
+
+  @Singleton
+  @Component(modules = JavacPluginModule.class)
+  interface Injector {
+    void inject(BindingGraphStatisticsCollector collector);
+
+    @Component.Factory
+    interface Factory {
+      Injector create(@BindsInstance Context context);
+    }
+  }
+
+  // BugCheckers must have no-arg constructors, so we'll use method injection instead.
+  @Inject
+  void inject(
+      BindingGraphConverter bindingGraphConverter,
+      BindingGraphFactory bindingGraphFactory,
+      ComponentDescriptorFactory componentDescriptorFactory) {
+    this.bindingGraphConverter = bindingGraphConverter;
+    this.bindingGraphFactory = bindingGraphFactory;
+    this.componentDescriptorFactory = componentDescriptorFactory;
+  }
+
+  @Override
+  public final Description matchClass(ClassTree tree, VisitorState state) {
+    injectIfNecessary(state.context);
+
+    ClassSymbol symbol = getSymbol(tree);
+    rootComponentAnnotation(symbol)
+        .map(annotation -> createBindingGraph(symbol))
+        .ifPresent(graph -> visitBindingGraph(graph, state));
+
+    return Description.NO_MATCH;
+  }
+
+  private BindingGraph createBindingGraph(ClassSymbol component) {
+    return bindingGraphConverter.convert(
+        bindingGraphFactory.create(
+            componentDescriptorFactory.rootComponentDescriptor(component), false));
+  }
+
+  /** Visits a {@link BindingGraph} and emits stats to a {@link VisitorState}. */
+  protected abstract void visitBindingGraph(BindingGraph graph, VisitorState state);
+
+  private void injectIfNecessary(Context context) {
+    if (isInjected) {
+      return;
+    }
+    DaggerBindingGraphStatisticsCollector_Injector.factory().create(context).inject(this);
+    isInjected = true;
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingGraphValidationModule.java b/java/dagger/internal/codegen/BindingGraphValidationModule.java
new file mode 100644
index 0000000..63e1fa2
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingGraphValidationModule.java
@@ -0,0 +1,78 @@
+/*
+ * 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 dagger.Binds;
+import dagger.Module;
+import dagger.multibindings.IntoSet;
+import dagger.spi.BindingGraphPlugin;
+
+/** Binds the set of {@link BindingGraphPlugin}s used to implement Dagger validation. */
+@Module
+interface BindingGraphValidationModule {
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin dependencyCycle(DependencyCycleValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin dependsOnProductionExecutor(DependsOnProductionExecutorValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin duplicateBindings(DuplicateBindingsValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin incompatiblyScopedBindings(IncompatiblyScopedBindingsValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin injectBinding(InjectBindingValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin mapMultibinding(MapMultibindingValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin missingBinding(MissingBindingValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin nullableBinding(NullableBindingValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin provisionDependencyOnProducerBinding(
+      ProvisionDependencyOnProducerBindingValidator validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin subcomponentFactoryMethod(SubcomponentFactoryMethodValidator validation);
+}
diff --git a/java/dagger/internal/codegen/BindingGraphValidator.java b/java/dagger/internal/codegen/BindingGraphValidator.java
new file mode 100644
index 0000000..df17b15
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingGraphValidator.java
@@ -0,0 +1,63 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.common.collect.ImmutableSet;
+import dagger.internal.codegen.DiagnosticReporterFactory.DiagnosticReporterImpl;
+import dagger.model.BindingGraph;
+import dagger.spi.BindingGraphPlugin;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/** Validates a {@link BindingGraph}. */
+@Singleton
+final class BindingGraphValidator {
+  private final ImmutableSet<BindingGraphPlugin> validationPlugins;
+  private final ImmutableSet<BindingGraphPlugin> externalPlugins;
+  private final DiagnosticReporterFactory diagnosticReporterFactory;
+
+  @Inject
+  BindingGraphValidator(
+      @Validation Set<BindingGraphPlugin> validationPlugins,
+      ImmutableSet<BindingGraphPlugin> externalPlugins,
+      DiagnosticReporterFactory diagnosticReporterFactory) {
+    this.validationPlugins = ImmutableSet.copyOf(validationPlugins);
+    this.externalPlugins = ImmutableSet.copyOf(externalPlugins);
+    this.diagnosticReporterFactory = checkNotNull(diagnosticReporterFactory);
+  }
+
+  /** Returns {@code true} if no errors are reported for {@code graph}. */
+  boolean isValid(BindingGraph graph) {
+    return isValid(validationPlugins, graph) && isValid(externalPlugins, graph);
+  }
+
+  private boolean isValid(ImmutableSet<BindingGraphPlugin> plugins, BindingGraph graph) {
+    boolean isValid = true;
+    for (BindingGraphPlugin plugin : plugins) {
+      DiagnosticReporterImpl reporter = diagnosticReporterFactory.reporter(graph, plugin);
+      plugin.visitGraph(graph, reporter);
+      if (reporter.reportedDiagnosticKinds().contains(ERROR)) {
+        isValid = false;
+      }
+    }
+    return isValid;
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingMethodProcessingStep.java b/java/dagger/internal/codegen/BindingMethodProcessingStep.java
new file mode 100644
index 0000000..e6c4f8e
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingMethodProcessingStep.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkArgument;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.collect.ImmutableSet;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+import javax.annotation.processing.Messager;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+
+/** A step that validates all binding methods that were not validated while processing modules. */
+final class BindingMethodProcessingStep extends TypeCheckingProcessingStep<ExecutableElement> {
+
+  private final Messager messager;
+  private final AnyBindingMethodValidator anyBindingMethodValidator;
+
+  @Inject
+  BindingMethodProcessingStep(
+      Messager messager, AnyBindingMethodValidator anyBindingMethodValidator) {
+    super(MoreElements::asExecutable);
+    this.messager = messager;
+    this.anyBindingMethodValidator = anyBindingMethodValidator;
+  }
+
+  @Override
+  public Set<? extends Class<? extends Annotation>> annotations() {
+    return anyBindingMethodValidator.methodAnnotations();
+  }
+
+  @Override
+  protected void process(
+      ExecutableElement method, ImmutableSet<Class<? extends Annotation>> annotations) {
+    checkArgument(
+        anyBindingMethodValidator.isBindingMethod(method),
+        "%s is not annotated with any of %s",
+        method,
+        annotations());
+    if (!anyBindingMethodValidator.wasAlreadyValidated(method)) {
+      anyBindingMethodValidator.validate(method).printMessagesTo(messager);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingMethodValidator.java b/java/dagger/internal/codegen/BindingMethodValidator.java
new file mode 100644
index 0000000..21c05cc
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingMethodValidator.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2016 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 dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
+import static java.util.stream.Collectors.joining;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.errorprone.annotations.FormatMethod;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.lang.annotation.Annotation;
+import java.util.Optional;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+/** A validator for methods that represent binding declarations. */
+abstract class BindingMethodValidator extends BindingElementValidator<ExecutableElement> {
+
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+  private final DependencyRequestValidator dependencyRequestValidator;
+  private final Class<? extends Annotation> methodAnnotation;
+  private final ImmutableSet<? extends Class<? extends Annotation>> enclosingElementAnnotations;
+  private final Abstractness abstractness;
+  private final ExceptionSuperclass exceptionSuperclass;
+
+  /**
+   * Creates a validator object.
+   *
+   * @param methodAnnotation the annotation on a method that identifies it as a binding method
+   * @param enclosingElementAnnotation the method must be declared in a class or interface annotated
+   *     with this annotation
+   */
+  protected BindingMethodValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      DependencyRequestValidator dependencyRequestValidator,
+      Class<? extends Annotation> methodAnnotation,
+      Class<? extends Annotation> enclosingElementAnnotation,
+      Abstractness abstractness,
+      ExceptionSuperclass exceptionSuperclass,
+      AllowsMultibindings allowsMultibindings,
+      AllowsScoping allowsScoping) {
+    this(
+        elements,
+        types,
+        methodAnnotation,
+        ImmutableSet.of(enclosingElementAnnotation),
+        dependencyRequestValidator,
+        abstractness,
+        exceptionSuperclass,
+        allowsMultibindings,
+        allowsScoping);
+  }
+
+  /**
+   * Creates a validator object.
+   *
+   * @param methodAnnotation the annotation on a method that identifies it as a binding method
+   * @param enclosingElementAnnotations the method must be declared in a class or interface
+   *     annotated with one of these annotations
+   */
+  protected BindingMethodValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      Class<? extends Annotation> methodAnnotation,
+      Iterable<? extends Class<? extends Annotation>> enclosingElementAnnotations,
+      DependencyRequestValidator dependencyRequestValidator,
+      Abstractness abstractness,
+      ExceptionSuperclass exceptionSuperclass,
+      AllowsMultibindings allowsMultibindings,
+      AllowsScoping allowsScoping) {
+    super(methodAnnotation, allowsMultibindings, allowsScoping);
+    this.elements = elements;
+    this.types = types;
+    this.methodAnnotation = methodAnnotation;
+    this.enclosingElementAnnotations = ImmutableSet.copyOf(enclosingElementAnnotations);
+    this.dependencyRequestValidator = dependencyRequestValidator;
+    this.abstractness = abstractness;
+    this.exceptionSuperclass = exceptionSuperclass;
+  }
+
+  /** The annotation that identifies binding methods validated by this object. */
+  final Class<? extends Annotation> methodAnnotation() {
+    return methodAnnotation;
+  }
+
+  /**
+   * Returns an error message of the form "@<i>annotation</i> methods <i>rule</i>", where
+   * <i>rule</i> comes from calling {@link String#format(String, Object...)} on {@code ruleFormat}
+   * and the other arguments.
+   */
+  @FormatMethod
+  protected final String bindingMethods(String ruleFormat, Object... args) {
+    return bindingElements(ruleFormat, args);
+  }
+
+  @Override
+  protected final String bindingElements() {
+    return String.format("@%s methods", methodAnnotation.getSimpleName());
+  }
+
+  @Override
+  protected final String bindingElementTypeVerb() {
+    return "return";
+  }
+
+  /** Abstract validator for individual binding method elements. */
+  protected abstract class MethodValidator extends ElementValidator {
+    protected MethodValidator(ExecutableElement element) {
+      super(element);
+    }
+
+    @Override
+    protected final Optional<TypeMirror> bindingElementType() {
+      return Optional.of(element.getReturnType());
+    }
+
+    @Override
+    protected final void checkAdditionalProperties() {
+      checkEnclosingElement();
+      checkTypeParameters();
+      checkNotPrivate();
+      checkAbstractness();
+      checkThrows();
+      checkParameters();
+      checkAdditionalMethodProperties();
+    }
+
+    /** Checks additional properties of the binding method. */
+    protected void checkAdditionalMethodProperties() {}
+
+    /**
+     * Adds an error if the method is not declared in a class or interface annotated with one of the
+     * {@link #enclosingElementAnnotations}.
+     */
+    private void checkEnclosingElement() {
+      if (!isAnyAnnotationPresent(
+          element.getEnclosingElement(), enclosingElementAnnotations)) {
+        report.addError(
+            bindingMethods(
+                "can only be present within a @%s",
+                enclosingElementAnnotations.stream()
+                    .map(Class::getSimpleName)
+                    .collect(joining(" or @"))));
+      }
+    }
+
+    /** Adds an error if the method is generic. */
+    private void checkTypeParameters() {
+      if (!element.getTypeParameters().isEmpty()) {
+        report.addError(bindingMethods("may not have type parameters"));
+      }
+    }
+
+    /** Adds an error if the method is private. */
+    private void checkNotPrivate() {
+      if (element.getModifiers().contains(PRIVATE)) {
+        report.addError(bindingMethods("cannot be private"));
+      }
+    }
+
+    /** Adds an error if the method is abstract but must not be, or is not and must be. */
+    private void checkAbstractness() {
+      boolean isAbstract = element.getModifiers().contains(ABSTRACT);
+      switch (abstractness) {
+        case MUST_BE_ABSTRACT:
+          if (!isAbstract) {
+            report.addError(bindingMethods("must be abstract"));
+          }
+          break;
+
+        case MUST_BE_CONCRETE:
+          if (isAbstract) {
+            report.addError(bindingMethods("cannot be abstract"));
+          }
+      }
+    }
+
+    /**
+     * Adds an error if the method declares throws anything but an {@link Error} or an appropriate
+     * subtype of {@link Exception}.
+     */
+    private void checkThrows() {
+      exceptionSuperclass.checkThrows(BindingMethodValidator.this, element, report);
+    }
+
+    /** Adds errors for the method parameters. */
+    protected void checkParameters() {
+      for (VariableElement parameter : element.getParameters()) {
+        checkParameter(parameter);
+      }
+    }
+
+    /**
+     * Adds errors for a method parameter. This implementation reports an error if the parameter has
+     * more than one qualifier.
+     */
+    protected void checkParameter(VariableElement parameter) {
+      dependencyRequestValidator.validateDependencyRequest(report, parameter, parameter.asType());
+    }
+  }
+
+  /** An abstract/concrete restriction on methods. */
+  protected enum Abstractness {
+    MUST_BE_ABSTRACT,
+    MUST_BE_CONCRETE
+  }
+
+  /**
+   * The exception class that all {@code throws}-declared throwables must extend, other than {@link
+   * Error}.
+   */
+  protected enum ExceptionSuperclass {
+    /** Methods may not declare any throwable types. */
+    NO_EXCEPTIONS {
+      @Override
+      protected String errorMessage(BindingMethodValidator validator) {
+        return validator.bindingMethods("may not throw");
+      }
+
+      @Override
+      protected void checkThrows(
+          BindingMethodValidator validator,
+          ExecutableElement element,
+          ValidationReport.Builder<ExecutableElement> report) {
+        if (!element.getThrownTypes().isEmpty()) {
+          report.addError(validator.bindingMethods("may not throw"));
+          return;
+        }
+      }
+    },
+
+    /** Methods may throw checked or unchecked exceptions or errors. */
+    EXCEPTION(Exception.class) {
+      @Override
+      protected String errorMessage(BindingMethodValidator validator) {
+        return validator.bindingMethods(
+            "may only throw unchecked exceptions or exceptions subclassing Exception");
+      }
+    },
+
+    /** Methods may throw unchecked exceptions or errors. */
+    RUNTIME_EXCEPTION(RuntimeException.class) {
+      @Override
+      protected String errorMessage(BindingMethodValidator validator) {
+        return validator.bindingMethods("may only throw unchecked exceptions");
+      }
+    },
+    ;
+
+    private final Class<? extends Exception> superclass;
+
+    ExceptionSuperclass() {
+      this(null);
+    }
+
+    ExceptionSuperclass(Class<? extends Exception> superclass) {
+      this.superclass = superclass;
+    }
+
+    /**
+     * Adds an error if the method declares throws anything but an {@link Error} or an appropriate
+     * subtype of {@link Exception}.
+     *
+     * <p>This method is overridden in {@link #NO_EXCEPTIONS}.
+     */
+    protected void checkThrows(
+        BindingMethodValidator validator,
+        ExecutableElement element,
+        ValidationReport.Builder<ExecutableElement> report) {
+      TypeMirror exceptionSupertype = validator.elements.getTypeElement(superclass).asType();
+      TypeMirror errorType = validator.elements.getTypeElement(Error.class).asType();
+      for (TypeMirror thrownType : element.getThrownTypes()) {
+        if (!validator.types.isSubtype(thrownType, exceptionSupertype)
+            && !validator.types.isSubtype(thrownType, errorType)) {
+          report.addError(errorMessage(validator));
+          break;
+        }
+      }
+    }
+
+    protected abstract String errorMessage(BindingMethodValidator validator);
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingMethodValidatorsModule.java b/java/dagger/internal/codegen/BindingMethodValidatorsModule.java
new file mode 100644
index 0000000..28a272d
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingMethodValidatorsModule.java
@@ -0,0 +1,60 @@
+/*
+ * 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.common.collect.Maps.uniqueIndex;
+
+import com.google.common.collect.ImmutableMap;
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.IntoSet;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+/**
+ * Binds each {@link BindingMethodValidator} into a map, keyed by {@link
+ * BindingMethodValidator#methodAnnotation()}.
+ */
+@Module
+interface BindingMethodValidatorsModule {
+  @Provides
+  static ImmutableMap<Class<? extends Annotation>, BindingMethodValidator> indexValidators(
+      Set<BindingMethodValidator> validators) {
+    return uniqueIndex(validators, BindingMethodValidator::methodAnnotation);
+  }
+
+  @Binds
+  @IntoSet
+  BindingMethodValidator provides(ProvidesMethodValidator validator);
+
+  @Binds
+  @IntoSet
+  BindingMethodValidator produces(ProducesMethodValidator validator);
+
+  @Binds
+  @IntoSet
+  BindingMethodValidator binds(BindsMethodValidator validator);
+
+  @Binds
+  @IntoSet
+  BindingMethodValidator multibinds(MultibindsMethodValidator validator);
+
+  @Binds
+  @IntoSet
+  BindingMethodValidator bindsOptionalOf(BindsOptionalOfMethodValidator validator);
+}
diff --git a/java/dagger/internal/codegen/BindingNode.java b/java/dagger/internal/codegen/BindingNode.java
new file mode 100644
index 0000000..a7da092
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingNode.java
@@ -0,0 +1,137 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.BindingType.PRODUCTION;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import dagger.BindsOptionalOf;
+import dagger.Module;
+import dagger.model.BindingKind;
+import dagger.model.ComponentPath;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.Scope;
+import dagger.multibindings.Multibinds;
+import java.util.Optional;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * An implementation of {@link dagger.model.Binding} that also exposes {@link BindingDeclaration}s
+ * associated with the binding.
+ */
+// TODO(dpb): Consider a supertype of dagger.model.Binding that dagger.internal.codegen.Binding
+// could also implement.
+@AutoValue
+abstract class BindingNode implements dagger.model.Binding {
+  static BindingNode create(
+      ComponentPath component,
+      Binding delegate,
+      ImmutableSet<MultibindingDeclaration> multibindingDeclarations,
+      ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations,
+      ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations,
+      BindingDeclarationFormatter bindingDeclarationFormatter) {
+    BindingNode node =
+        new AutoValue_BindingNode(
+            component,
+            delegate,
+            multibindingDeclarations,
+            optionalBindingDeclarations,
+            subcomponentDeclarations);
+    node.bindingDeclarationFormatter = checkNotNull(bindingDeclarationFormatter);
+    return node;
+  }
+
+  private BindingDeclarationFormatter bindingDeclarationFormatter;
+
+  abstract Binding delegate();
+
+  abstract ImmutableSet<MultibindingDeclaration> multibindingDeclarations();
+
+  abstract ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations();
+
+  abstract ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations();
+
+  /**
+   * The {@link Element}s (other than the binding's {@link #bindingElement()}) that are associated
+   * with the binding.
+   *
+   * <ul>
+   *   <li>{@linkplain BindsOptionalOf optional binding} declarations
+   *   <li>{@linkplain Module#subcomponents() module subcomponent} declarations
+   *   <li>{@linkplain Multibinds multibinding} declarations
+   * </ul>
+   */
+  final Iterable<BindingDeclaration> associatedDeclarations() {
+    return Iterables.concat(
+        multibindingDeclarations(), optionalBindingDeclarations(), subcomponentDeclarations());
+  }
+
+  @Override
+  public Key key() {
+    return delegate().key();
+  }
+
+  @Override
+  public ImmutableSet<DependencyRequest> dependencies() {
+    return delegate().dependencies();
+  }
+
+  @Override
+  public Optional<Element> bindingElement() {
+    return delegate().bindingElement();
+  }
+
+  @Override
+  public Optional<TypeElement> contributingModule() {
+    return delegate().contributingModule();
+  }
+
+  @Override
+  public boolean requiresModuleInstance() {
+    return delegate().requiresModuleInstance();
+  }
+
+  @Override
+  public Optional<Scope> scope() {
+    return delegate().scope();
+  }
+
+  @Override
+  public boolean isNullable() {
+    return delegate().isNullable();
+  }
+
+  @Override
+  public boolean isProduction() {
+    return delegate().bindingType().equals(PRODUCTION);
+  }
+
+  @Override
+  public BindingKind kind() {
+    return delegate().kind();
+  }
+
+  @Override
+  public final String toString() {
+    return bindingDeclarationFormatter.format(delegate());
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingRequest.java b/java/dagger/internal/codegen/BindingRequest.java
new file mode 100644
index 0000000..27067aa
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingRequest.java
@@ -0,0 +1,125 @@
+/*
+ * 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 dagger.internal.codegen.RequestKinds.requestType;
+
+import com.google.auto.value.AutoValue;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.BindingRequestProto;
+import dagger.internal.codegen.serialization.FrameworkTypeWrapper;
+import dagger.internal.codegen.serialization.RequestKindWrapper;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import java.util.Optional;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A request for a binding, which may be in the form of a request for a dependency to pass to a
+ * constructor or module method ({@link RequestKind}) or an internal request for a framework
+ * instance ({@link FrameworkType}).
+ */
+@AutoValue
+abstract class BindingRequest {
+  /** Creates a {@link BindingRequest} for the given {@link DependencyRequest}. */
+  static BindingRequest bindingRequest(DependencyRequest dependencyRequest) {
+    return bindingRequest(dependencyRequest.key(), dependencyRequest.kind());
+  }
+
+  /**
+   * Creates a {@link BindingRequest} for a normal dependency request for the given {@link Key} and
+   * {@link RequestKind}.
+   */
+  static BindingRequest bindingRequest(Key key, RequestKind requestKind) {
+    // When there's a request that has a 1:1 mapping to a FrameworkType, the request should be
+    // associated with that FrameworkType as well, because we want to ensure that if a request
+    // comes in for that as a dependency first and as a framework instance later, they resolve to
+    // the same binding expression.
+    // TODO(cgdecker): Instead of doing this, make ComponentBindingExpressions create a
+    // BindingExpression for the RequestKind that simply delegates to the BindingExpression for the
+    // FrameworkType. Then there are separate BindingExpressions, but we don't end up doing weird
+    // things like creating two fields when there should only be one.
+    return new AutoValue_BindingRequest(
+        key, Optional.of(requestKind), FrameworkType.forRequestKind(requestKind));
+  }
+
+  /**
+   * Creates a {@link BindingRequest} for a request for a framework instance for the given {@link
+   * Key} with the given {@link FrameworkType}.
+   */
+  static BindingRequest bindingRequest(Key key, FrameworkType frameworkType) {
+    return new AutoValue_BindingRequest(
+        key, frameworkType.requestKind(), Optional.of(frameworkType));
+  }
+
+  /** Creates a {@link BindingRequest} for the given {@link FrameworkDependency}. */
+  static BindingRequest bindingRequest(FrameworkDependency frameworkDependency) {
+    return bindingRequest(frameworkDependency.key(), frameworkDependency.frameworkType());
+  }
+
+  /** Returns the {@link Key} for the requested binding. */
+  abstract Key key();
+
+  /** Returns the request kind associated with this request, if any. */
+  abstract Optional<RequestKind> requestKind();
+
+  /** Returns the framework type associated with this request, if any. */
+  abstract Optional<FrameworkType> frameworkType();
+
+  /** Returns whether this request is of the given kind. */
+  final boolean isRequestKind(RequestKind requestKind) {
+    return requestKind.equals(requestKind().orElse(null));
+  }
+
+  final TypeMirror requestedType(TypeMirror contributedType, DaggerTypes types) {
+    if (requestKind().isPresent()) {
+      return requestType(requestKind().get(), contributedType, types);
+    }
+    return types.wrapType(contributedType, frameworkType().get().frameworkClass());
+  }
+
+  /** Returns a name that can be used for the kind of request this is. */
+  final String kindName() {
+    Object requestKindObject =
+        requestKind().isPresent()
+            ? requestKind().get()
+            : frameworkType().get().frameworkClass().getSimpleName();
+    return requestKindObject.toString();
+  }
+
+  /** Returns {@code true} if this request can be satisfied by a production binding. */
+  final boolean canBeSatisfiedByProductionBinding() {
+    if (requestKind().isPresent()) {
+      return RequestKinds.canBeSatisfiedByProductionBinding(requestKind().get());
+    }
+    return frameworkType().get().equals(FrameworkType.PRODUCER_NODE);
+  }
+
+  /** Creates a proto representation of this binding request. */
+  BindingRequestProto toProto() {
+    BindingRequestProto.Builder builder =
+        BindingRequestProto.newBuilder().setKey(KeyFactory.toProto(key()));
+    if (frameworkType().isPresent()) {
+      builder.setFrameworkType(
+          FrameworkTypeWrapper.FrameworkType.valueOf(frameworkType().get().name()));
+    } else {
+      builder.setRequestKind(RequestKindWrapper.RequestKind.valueOf(requestKind().get().name()));
+    }
+    return builder.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/BindingType.java b/java/dagger/internal/codegen/BindingType.java
new file mode 100644
index 0000000..37109c7
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingType.java
@@ -0,0 +1,31 @@
+/*
+ * 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 dagger.MembersInjector;
+
+/** Whether a binding or declaration is for provision, production, or a {@link MembersInjector}. */
+enum BindingType {
+  /** A binding with this type is a {@link ProvisionBinding}. */
+  PROVISION,
+
+  /** A binding with this type is a {@link MembersInjectionBinding}. */
+  MEMBERS_INJECTION,
+
+  /** A binding with this type is a {@link ProductionBinding}. */
+  PRODUCTION,
+}
diff --git a/java/dagger/internal/codegen/BindsInstanceElementValidator.java b/java/dagger/internal/codegen/BindsInstanceElementValidator.java
new file mode 100644
index 0000000..9249c8e
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsInstanceElementValidator.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 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 dagger.BindsInstance;
+import javax.lang.model.element.Element;
+
+abstract class BindsInstanceElementValidator<E extends Element> extends BindingElementValidator<E> {
+  BindsInstanceElementValidator() {
+    super(BindsInstance.class, AllowsMultibindings.NO_MULTIBINDINGS, AllowsScoping.NO_SCOPING);
+  }
+
+  @Override
+  protected final String bindingElements() {
+    // Even though @BindsInstance may be placed on methods, the subject of errors is the
+    // parameter
+    return "@BindsInstance parameters";
+  }
+
+  @Override
+  protected final String bindingElementTypeVerb() {
+    return "be";
+  }
+}
diff --git a/java/dagger/internal/codegen/BindsInstanceMethodValidator.java b/java/dagger/internal/codegen/BindsInstanceMethodValidator.java
new file mode 100644
index 0000000..1a491c7
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsInstanceMethodValidator.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 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.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.ComponentAnnotation.anyComponentAnnotation;
+import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+
+import com.google.auto.common.MoreElements;
+import java.util.List;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+final class BindsInstanceMethodValidator extends BindsInstanceElementValidator<ExecutableElement> {
+  @Inject
+  BindsInstanceMethodValidator() {}
+
+  @Override
+  protected ElementValidator elementValidator(ExecutableElement element) {
+    return new Validator(element);
+  }
+
+  private class Validator extends ElementValidator {
+    Validator(ExecutableElement element) {
+      super(element);
+    }
+
+    @Override
+    protected void checkAdditionalProperties() {
+      if (!element.getModifiers().contains(ABSTRACT)) {
+        report.addError("@BindsInstance methods must be abstract");
+      }
+      if (element.getParameters().size() != 1) {
+        report.addError(
+            "@BindsInstance methods should have exactly one parameter for the bound type");
+      }
+      TypeElement enclosingType = MoreElements.asType(element.getEnclosingElement());
+      moduleAnnotation(enclosingType)
+          .ifPresent(moduleAnnotation -> report.addError(didYouMeanBinds(moduleAnnotation)));
+      anyComponentAnnotation(enclosingType)
+          .ifPresent(
+              componentAnnotation ->
+                  report.addError(
+                      String.format(
+                          "@BindsInstance methods should not be included in @%1$ss. "
+                              + "Did you mean to put it in a @%1$s.Builder?",
+                          componentAnnotation.simpleName())));
+    }
+
+    @Override
+    protected Optional<TypeMirror> bindingElementType() {
+      List<? extends VariableElement> parameters =
+          MoreElements.asExecutable(element).getParameters();
+      return parameters.size() == 1
+          ? Optional.of(getOnlyElement(parameters).asType())
+          : Optional.empty();
+    }
+  }
+
+  private static String didYouMeanBinds(ModuleAnnotation moduleAnnotation) {
+    return String.format(
+        "@BindsInstance methods should not be included in @%ss. Did you mean @Binds?",
+        moduleAnnotation.annotationClass().getSimpleName());
+  }
+}
diff --git a/java/dagger/internal/codegen/BindsInstanceParameterValidator.java b/java/dagger/internal/codegen/BindsInstanceParameterValidator.java
new file mode 100644
index 0000000..b2dc8d8
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsInstanceParameterValidator.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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 javax.lang.model.element.ElementKind.METHOD;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.type.TypeKind.DECLARED;
+import static javax.lang.model.type.TypeKind.TYPEVAR;
+
+import com.google.auto.common.MoreElements;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+final class BindsInstanceParameterValidator extends BindsInstanceElementValidator<VariableElement> {
+  @Inject
+  BindsInstanceParameterValidator() {}
+
+  @Override
+  protected ElementValidator elementValidator(VariableElement element) {
+    return new Validator(element);
+  }
+
+  private class Validator extends ElementValidator {
+    Validator(VariableElement element) {
+      super(element);
+    }
+
+    @Override
+    protected void checkAdditionalProperties() {
+      Element enclosing = element.getEnclosingElement();
+      if (!enclosing.getKind().equals(METHOD)) {
+        report.addError(
+            "@BindsInstance should only be applied to methods or parameters of methods");
+        return;
+      }
+
+      ExecutableElement method = MoreElements.asExecutable(enclosing);
+      if (!method.getModifiers().contains(ABSTRACT)) {
+        report.addError("@BindsInstance parameters may only be used in abstract methods");
+      }
+
+      TypeKind returnKind = method.getReturnType().getKind();
+      if (!(returnKind.equals(DECLARED) || returnKind.equals(TYPEVAR))) {
+        report.addError(
+            "@BindsInstance parameters may not be used in methods with a void, array or primitive "
+                + "return type");
+      }
+    }
+
+    @Override
+    protected Optional<TypeMirror> bindingElementType() {
+      return Optional.of(element.asType());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/BindsInstanceProcessingStep.java b/java/dagger/internal/codegen/BindsInstanceProcessingStep.java
new file mode 100644
index 0000000..4c222a9
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsInstanceProcessingStep.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 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.common.MoreElements;
+import com.google.common.collect.ImmutableSet;
+import dagger.BindsInstance;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+import javax.annotation.processing.Messager;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+
+/**
+ * Processing step that validates that the {@code BindsInstance} annotation is applied to the
+ * correct elements.
+ */
+final class BindsInstanceProcessingStep extends TypeCheckingProcessingStep<Element> {
+  private final BindsInstanceMethodValidator methodValidator;
+  private final BindsInstanceParameterValidator parameterValidator;
+  private final Messager messager;
+
+  @Inject
+  BindsInstanceProcessingStep(
+      BindsInstanceMethodValidator methodValidator,
+      BindsInstanceParameterValidator parameterValidator,
+      Messager messager) {
+    super(element -> element);
+    this.methodValidator = methodValidator;
+    this.parameterValidator = parameterValidator;
+    this.messager = messager;
+  }
+
+  @Override
+  public Set<? extends Class<? extends Annotation>> annotations() {
+    return ImmutableSet.of(BindsInstance.class);
+  }
+
+  @Override
+  protected void process(Element element, ImmutableSet<Class<? extends Annotation>> annotations) {
+    switch (element.getKind()) {
+      case PARAMETER:
+        parameterValidator.validate(MoreElements.asVariable(element)).printMessagesTo(messager);
+        break;
+      case METHOD:
+        methodValidator.validate(MoreElements.asExecutable(element)).printMessagesTo(messager);
+        break;
+      default:
+        throw new AssertionError(element);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/BindsMethodValidator.java b/java/dagger/internal/codegen/BindsMethodValidator.java
new file mode 100644
index 0000000..e198c3a
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsMethodValidator.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 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 dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.ALLOWS_SCOPING;
+import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
+import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.RUNTIME_EXCEPTION;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import dagger.Binds;
+import dagger.Module;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.producers.ProducerModule;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+/** A validator for {@link Binds} methods. */
+final class BindsMethodValidator extends BindingMethodValidator {
+  private final DaggerTypes types;
+  private final BindsTypeChecker bindsTypeChecker;
+
+  @Inject
+  BindsMethodValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      DependencyRequestValidator dependencyRequestValidator) {
+    super(
+        elements,
+        types,
+        Binds.class,
+        ImmutableSet.of(Module.class, ProducerModule.class),
+        dependencyRequestValidator,
+        MUST_BE_ABSTRACT,
+        RUNTIME_EXCEPTION,
+        ALLOWS_MULTIBINDINGS,
+        ALLOWS_SCOPING);
+    this.types = types;
+    this.bindsTypeChecker = new BindsTypeChecker(types, elements);
+  }
+
+  @Override
+  protected ElementValidator elementValidator(ExecutableElement element) {
+    return new Validator(element);
+  }
+
+  private class Validator extends MethodValidator {
+    Validator(ExecutableElement element) {
+      super(element);
+    }
+
+    @Override
+    protected void checkParameters() {
+      if (element.getParameters().size() != 1) {
+        report.addError(
+            bindingMethods(
+                "must have exactly one parameter, whose type is assignable to the return type"));
+      } else {
+        super.checkParameters();
+      }
+    }
+
+    @Override
+    protected void checkParameter(VariableElement parameter) {
+      super.checkParameter(parameter);
+      TypeMirror leftHandSide = boxIfNecessary(element.getReturnType());
+      TypeMirror rightHandSide = parameter.asType();
+      ContributionType contributionType = ContributionType.fromBindingElement(element);
+      if (contributionType.equals(ContributionType.SET_VALUES) && !SetType.isSet(leftHandSide)) {
+        report.addError(
+            "@Binds @ElementsIntoSet methods must return a Set and take a Set parameter");
+      }
+
+      if (!bindsTypeChecker.isAssignable(rightHandSide, leftHandSide, contributionType)) {
+        // TODO(ronshapiro): clarify this error message for @ElementsIntoSet cases, where the
+        // right-hand-side might not be assignable to the left-hand-side, but still compatible with
+        // Set.addAll(Collection<? extends E>)
+        report.addError("@Binds methods' parameter type must be assignable to the return type");
+      }
+    }
+
+    private TypeMirror boxIfNecessary(TypeMirror maybePrimitive) {
+      if (maybePrimitive.getKind().isPrimitive()) {
+        return types.boxedClass(MoreTypes.asPrimitiveType(maybePrimitive)).asType();
+      }
+      return maybePrimitive;
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/BindsOptionalOfMethodValidator.java b/java/dagger/internal/codegen/BindsOptionalOfMethodValidator.java
new file mode 100644
index 0000000..e1c9d73
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsOptionalOfMethodValidator.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 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 dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.NO_SCOPING;
+import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
+import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifiers;
+import static dagger.internal.codegen.InjectionAnnotations.injectedConstructors;
+import static dagger.internal.codegen.Keys.isValidImplicitProvisionKey;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import dagger.BindsOptionalOf;
+import dagger.Module;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.producers.ProducerModule;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.TypeMirror;
+
+/** A validator for {@link BindsOptionalOf} methods. */
+final class BindsOptionalOfMethodValidator extends BindingMethodValidator {
+
+  private final DaggerTypes types;
+
+  @Inject
+  BindsOptionalOfMethodValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      DependencyRequestValidator dependencyRequestValidator) {
+    super(
+        elements,
+        types,
+        BindsOptionalOf.class,
+        ImmutableSet.of(Module.class, ProducerModule.class),
+        dependencyRequestValidator,
+        MUST_BE_ABSTRACT,
+        NO_EXCEPTIONS,
+        NO_MULTIBINDINGS,
+        NO_SCOPING);
+    this.types = types;
+  }
+
+  @Override
+  protected ElementValidator elementValidator(ExecutableElement element) {
+    return new Validator(element);
+  }
+
+  private class Validator extends MethodValidator {
+    Validator(ExecutableElement element) {
+      super(element);
+    }
+
+    @Override
+    protected void checkKeyType(TypeMirror keyType) {
+      super.checkKeyType(keyType);
+      if (isValidImplicitProvisionKey(
+              getQualifiers(element).stream().findFirst(), keyType, types)
+          && !injectedConstructors(MoreElements.asType(MoreTypes.asDeclared(keyType).asElement()))
+              .isEmpty()) {
+        report.addError(
+            "@BindsOptionalOf methods cannot return unqualified types that have an @Inject-"
+                + "annotated constructor because those are always present");
+      }
+    }
+
+    @Override
+    protected void checkParameters() {
+      if (!element.getParameters().isEmpty()) {
+        report.addError("@BindsOptionalOf methods cannot have parameters");
+      }
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/BindsTypeChecker.java b/java/dagger/internal/codegen/BindsTypeChecker.java
new file mode 100644
index 0000000..acecc9e
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsTypeChecker.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2017 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.common.collect.Iterables.getOnlyElement;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+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.TypeMirror;
+
+/**
+ * Checks the assignability of one type to another, given a {@link ContributionType} context. This
+ * is used by {@link BindsMethodValidator} to validate that the right-hand-side of a {@link
+ * dagger.Binds} method is valid, as well as in {@link DelegateBindingExpression} when the
+ * right-hand-side in generated code might be an erased type due to accessibility.
+ */
+final class BindsTypeChecker {
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+
+  @Inject
+  BindsTypeChecker(DaggerTypes types, DaggerElements elements) {
+    this.types = types;
+    this.elements = elements;
+  }
+
+  /**
+   * Checks the assignability of {@code rightHandSide} to {@code leftHandSide} given a {@link
+   * ContributionType} context.
+   */
+  boolean isAssignable(
+      TypeMirror rightHandSide, TypeMirror leftHandSide, ContributionType contributionType) {
+    return types.isAssignable(rightHandSide, desiredAssignableType(leftHandSide, contributionType));
+  }
+
+  private TypeMirror desiredAssignableType(
+      TypeMirror leftHandSide, ContributionType contributionType) {
+    switch (contributionType) {
+      case UNIQUE:
+        return leftHandSide;
+      case SET:
+        DeclaredType parameterizedSetType = types.getDeclaredType(setElement(), leftHandSide);
+        return methodParameterType(parameterizedSetType, "add");
+      case SET_VALUES:
+        return methodParameterType(MoreTypes.asDeclared(leftHandSide), "addAll");
+      case MAP:
+        DeclaredType parameterizedMapType =
+            types.getDeclaredType(mapElement(), unboundedWildcard(), leftHandSide);
+        return methodParameterTypes(parameterizedMapType, "put").get(1);
+    }
+    throw new AssertionError("Unknown contribution type: " + contributionType);
+  }
+
+  private ImmutableList<TypeMirror> methodParameterTypes(DeclaredType type, String methodName) {
+    ImmutableList.Builder<ExecutableElement> methodsForName = ImmutableList.builder();
+    for (ExecutableElement method :
+        // type.asElement().getEnclosedElements() is not used because some non-standard JDKs (e.g.
+        // J2CL) don't redefine Set.add() (whose only purpose of being redefined in the standard JDK
+        // is documentation, and J2CL's implementation doesn't declare docs for JDK types).
+        // MoreElements.getLocalAndInheritedMethods ensures that the method will always be present.
+        MoreElements.getLocalAndInheritedMethods(MoreTypes.asTypeElement(type), types, elements)) {
+      if (method.getSimpleName().contentEquals(methodName)) {
+        methodsForName.add(method);
+      }
+    }
+    ExecutableElement method = getOnlyElement(methodsForName.build());
+    return ImmutableList.copyOf(
+        MoreTypes.asExecutable(types.asMemberOf(type, method)).getParameterTypes());
+  }
+
+  private TypeMirror methodParameterType(DeclaredType type, String methodName) {
+    return getOnlyElement(methodParameterTypes(type, methodName));
+  }
+
+  private TypeElement setElement() {
+    return elements.getTypeElement(Set.class);
+  }
+
+  private TypeElement mapElement() {
+    return elements.getTypeElement(Map.class);
+  }
+
+  private TypeMirror unboundedWildcard() {
+    return types.getWildcardType(null, null);
+  }
+}
diff --git a/java/dagger/internal/codegen/ChildFactoryMethodEdgeImpl.java b/java/dagger/internal/codegen/ChildFactoryMethodEdgeImpl.java
new file mode 100644
index 0000000..a5e0219
--- /dev/null
+++ b/java/dagger/internal/codegen/ChildFactoryMethodEdgeImpl.java
@@ -0,0 +1,42 @@
+/*
+ * 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 dagger.internal.codegen.ElementFormatter.elementToString;
+
+import dagger.model.BindingGraph.ChildFactoryMethodEdge;
+import javax.lang.model.element.ExecutableElement;
+
+/** An implementation of {@link ChildFactoryMethodEdge}. */
+final class ChildFactoryMethodEdgeImpl implements ChildFactoryMethodEdge {
+
+  private final ExecutableElement factoryMethod;
+
+  ChildFactoryMethodEdgeImpl(ExecutableElement factoryMethod) {
+    this.factoryMethod = factoryMethod;
+  }
+
+  @Override
+  public ExecutableElement factoryMethod() {
+    return factoryMethod;
+  }
+
+  @Override
+  public String toString() {
+    return elementToString(factoryMethod);
+  }
+}
diff --git a/java/dagger/internal/codegen/ClearableCache.java b/java/dagger/internal/codegen/ClearableCache.java
new file mode 100644
index 0000000..66ce3ef
--- /dev/null
+++ b/java/dagger/internal/codegen/ClearableCache.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 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;
+
+/** A cache of objects that can be cleared. */
+interface ClearableCache {
+  /** Releases cached references. */
+  void clearCache();
+}
diff --git a/java/dagger/internal/codegen/CompilerOptions.java b/java/dagger/internal/codegen/CompilerOptions.java
new file mode 100644
index 0000000..bc3cbf8
--- /dev/null
+++ b/java/dagger/internal/codegen/CompilerOptions.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 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.squareup.javapoet.AnnotationSpec;
+import dagger.internal.GenerationOptions;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+/** A collection of options that dictate how the compiler will run. */
+abstract class CompilerOptions {
+  abstract boolean usesProducers();
+
+  /**
+   * Returns true if the fast initialization flag, {@code fastInit}, is enabled.
+   *
+   * <p>If enabled, the generated code will attempt to optimize for fast component initialization.
+   * This is done by reducing the number of factory classes loaded during initialization and the
+   * number of eagerly initialized fields at the cost of potential memory leaks and higher
+   * per-provision instantiation time.
+   */
+  abstract boolean fastInit();
+
+  abstract boolean formatGeneratedSource();
+
+  abstract boolean writeProducerNameInToken();
+
+  abstract Diagnostic.Kind nullableValidationKind();
+
+  final boolean doCheckForNulls() {
+    return nullableValidationKind().equals(Diagnostic.Kind.ERROR);
+  }
+
+  abstract Diagnostic.Kind privateMemberValidationKind();
+
+  abstract Diagnostic.Kind staticMemberValidationKind();
+
+  /**
+   * If {@code true}, Dagger will generate factories and components even if some members-injected
+   * types have {@code private} or {@code static} {@code @Inject}-annotated members.
+   *
+   * <p>This should only ever be enabled by the TCK tests. Disabling this validation could lead to
+   * generating code that does not compile.
+   */
+  abstract boolean ignorePrivateAndStaticInjectionForComponent();
+
+  abstract ValidationType scopeCycleValidationType();
+
+  abstract boolean warnIfInjectionFactoryNotGeneratedUpstream();
+
+  abstract boolean headerCompilation();
+
+  abstract boolean aheadOfTimeSubcomponents();
+
+  /**
+   * Enables a testing configuration where all superclass {@link ComponentImplementation}s are
+   * derived from their serialized forms.
+   */
+  abstract boolean forceUseSerializedComponentImplementations();
+
+  /**
+   * If {@code true}, in {@link #aheadOfTimeSubcomponents()} mode, Dagger will emit metadata
+   * annotations to deserialize aspects of the {@link ComponentImplementation}.
+   *
+   * This should only be disabled in compile-testing tests that want to ignore the annotations when
+   * asserting on generated source.
+   */
+  abstract boolean emitModifiableMetadataAnnotations();
+
+  abstract boolean useGradleIncrementalProcessing();
+
+  /**
+   * Returns the validation that should be done for the full binding graph for the element.
+   *
+   * @throws IllegalArgumentException if {@code element} is not a module or (sub)component
+   */
+  abstract ValidationType fullBindingGraphValidationType(TypeElement element);
+
+  abstract Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind();
+
+  abstract ValidationType explicitBindingConflictsWithInjectValidationType();
+
+  /**
+   * Creates a new {@link CompilerOptions} from the serialized {@link GenerationOptions} of a base
+   * component implementation.
+   */
+  final CompilerOptions withGenerationOptions(GenerationOptions generationOptions) {
+    return new ForwardingCompilerOptions(this) {
+      @Override
+      public boolean fastInit() {
+        return generationOptions.fastInit();
+      }
+    };
+  }
+
+  /**
+   * Returns a {@link GenerationOptions} annotation that serializes any options for this compilation
+   * that should be reused in future compilations.
+   */
+  final AnnotationSpec toGenerationOptionsAnnotation() {
+    return AnnotationSpec.builder(GenerationOptions.class)
+        .addMember("fastInit", "$L", fastInit())
+        .build();
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentAnnotation.java b/java/dagger/internal/codegen/ComponentAnnotation.java
new file mode 100644
index 0000000..a8f2ece
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentAnnotation.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2019 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.AnnotationMirrors.getAnnotationValue;
+import static com.google.auto.common.MoreTypes.asTypeElements;
+import static com.google.auto.common.MoreTypes.isTypeOf;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.MoreAnnotationValues.asAnnotationValues;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import dagger.Component;
+import dagger.Subcomponent;
+import dagger.producers.ProducerModule;
+import dagger.producers.ProductionComponent;
+import dagger.producers.ProductionSubcomponent;
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A {@code @Component}, {@code @Subcomponent}, {@code @ProductionComponent}, or
+ * {@code @ProductionSubcomponent} annotation, or a {@code @Module} or {@code @ProducerModule}
+ * annotation that is being treated as a component annotation when validating full binding graphs
+ * for modules.
+ */
+abstract class ComponentAnnotation {
+  /** The root component annotation types. */
+  private static final ImmutableSet<Class<? extends Annotation>> ROOT_COMPONENT_ANNOTATIONS =
+     ImmutableSet.of(Component.class, ProductionComponent.class);
+
+  /** The subcomponent annotation types. */
+  private static final ImmutableSet<Class<? extends Annotation>> SUBCOMPONENT_ANNOTATIONS =
+     ImmutableSet.of(Subcomponent.class, ProductionSubcomponent.class);
+
+  /** All component annotation types. */
+  private static final ImmutableSet<Class<? extends Annotation>> ALL_COMPONENT_ANNOTATIONS =
+     ImmutableSet.<Class<? extends Annotation>>builder()
+         .addAll(ROOT_COMPONENT_ANNOTATIONS)
+         .addAll(SUBCOMPONENT_ANNOTATIONS)
+         .build();
+
+  /** The annotation itself. */
+  abstract AnnotationMirror annotation();
+
+  /** The simple name of the annotation type. */
+  String simpleName() {
+    return MoreAnnotationMirrors.simpleName(annotation()).toString();
+  }
+
+  /**
+   * Returns {@code true} if the annotation is a {@code @Subcomponent} or
+   * {@code @ProductionSubcomponent}.
+   */
+  abstract boolean isSubcomponent();
+
+  /**
+   * Returns {@code true} if the annotation is a {@code @ProductionComponent},
+   * {@code @ProductionSubcomponent}, or {@code @ProducerModule}.
+   */
+  abstract boolean isProduction();
+
+  /**
+   * Returns {@code true} if the annotation is a real component annotation and not a module
+   * annotation.
+   */
+  abstract boolean isRealComponent();
+
+  /** The values listed as {@code dependencies}. */
+  abstract ImmutableList<AnnotationValue> dependencyValues();
+
+  /** The types listed as {@code dependencies}. */
+  ImmutableList<TypeMirror> dependencyTypes() {
+    return dependencyValues().stream().map(MoreAnnotationValues::asType).collect(toImmutableList());
+  }
+
+  /**
+   * The types listed as {@code dependencies}.
+   *
+   * @throws IllegalArgumentException if any of {@link #dependencyTypes()} are error types
+   */
+  ImmutableList<TypeElement> dependencies() {
+    return asTypeElements(dependencyTypes()).asList();
+  }
+
+  /** The values listed as {@code modules}. */
+  abstract ImmutableList<AnnotationValue> moduleValues();
+
+  /** The types listed as {@code modules}. */
+  ImmutableList<TypeMirror> moduleTypes() {
+    return moduleValues().stream().map(MoreAnnotationValues::asType).collect(toImmutableList());
+  }
+
+  /**
+   * The types listed as {@code modules}.
+   *
+   * @throws IllegalArgumentException if any of {@link #moduleTypes()} are error types
+   */
+  ImmutableSet<TypeElement> modules() {
+    return asTypeElements(moduleTypes());
+  }
+
+  protected final ImmutableList<AnnotationValue> getAnnotationValues(String parameterName) {
+    return asAnnotationValues(getAnnotationValue(annotation(), parameterName));
+  }
+
+  /**
+   * Returns an object representing a root component annotation, not a subcomponent annotation, if
+   * one is present on {@code typeElement}.
+   */
+  static Optional<ComponentAnnotation> rootComponentAnnotation(TypeElement typeElement) {
+    return anyComponentAnnotation(typeElement, ROOT_COMPONENT_ANNOTATIONS);
+  }
+
+  /**
+   * Returns an object representing a subcomponent annotation, if one is present on {@code
+   * typeElement}.
+   */
+  static Optional<ComponentAnnotation> subcomponentAnnotation(TypeElement typeElement) {
+    return anyComponentAnnotation(typeElement, SUBCOMPONENT_ANNOTATIONS);
+  }
+
+  /**
+   * Returns an object representing a root component or subcomponent annotation, if one is present
+   * on {@code typeElement}.
+   */
+  static Optional<ComponentAnnotation> anyComponentAnnotation(TypeElement typeElement) {
+    return anyComponentAnnotation(typeElement, ALL_COMPONENT_ANNOTATIONS);
+  }
+
+  private static Optional<ComponentAnnotation> anyComponentAnnotation(
+      TypeElement typeElement, Collection<Class<? extends Annotation>> annotations) {
+    return getAnyAnnotation(typeElement, annotations).map(ComponentAnnotation::componentAnnotation);
+  }
+
+  /** Returns {@code true} if the argument is a component annotation. */
+  static boolean isComponentAnnotation(AnnotationMirror annotation) {
+    return ALL_COMPONENT_ANNOTATIONS.stream()
+        .anyMatch(annotationClass -> isTypeOf(annotationClass, annotation.getAnnotationType()));
+  }
+
+  /** Creates an object representing a component or subcomponent annotation. */
+  static ComponentAnnotation componentAnnotation(AnnotationMirror annotation) {
+    RealComponentAnnotation.Builder annotationBuilder =
+        RealComponentAnnotation.builder().annotation(annotation);
+
+    if (isTypeOf(Component.class, annotation.getAnnotationType())) {
+      return annotationBuilder.isProduction(false).isSubcomponent(false).build();
+    }
+    if (isTypeOf(Subcomponent.class, annotation.getAnnotationType())) {
+      return annotationBuilder.isProduction(false).isSubcomponent(true).build();
+    }
+    if (isTypeOf(ProductionComponent.class, annotation.getAnnotationType())) {
+      return annotationBuilder.isProduction(true).isSubcomponent(false).build();
+    }
+    if (isTypeOf(ProductionSubcomponent.class, annotation.getAnnotationType())) {
+      return annotationBuilder.isProduction(true).isSubcomponent(true).build();
+    }
+    throw new IllegalArgumentException(
+        annotation
+            + " must be a Component, Subcomponent, ProductionComponent, "
+            + "or ProductionSubcomponent annotation");
+  }
+
+  /** Creates a fictional component annotation representing a module. */
+  static ComponentAnnotation fromModuleAnnotation(ModuleAnnotation moduleAnnotation) {
+    return new AutoValue_ComponentAnnotation_FictionalComponentAnnotation(moduleAnnotation);
+  }
+
+  /** The root component annotation types. */
+  static ImmutableSet<Class<? extends Annotation>> rootComponentAnnotations() {
+    return ROOT_COMPONENT_ANNOTATIONS;
+  }
+
+  /** The subcomponent annotation types. */
+  static ImmutableSet<Class<? extends Annotation>> subcomponentAnnotations() {
+    return SUBCOMPONENT_ANNOTATIONS;
+  }
+
+  /** All component annotation types. */
+  static ImmutableSet<Class<? extends Annotation>> allComponentAnnotations() {
+    return ALL_COMPONENT_ANNOTATIONS;
+  }
+
+  /**
+   * An actual component annotation.
+   *
+   * @see FictionalComponentAnnotation
+   */
+  @AutoValue
+  abstract static class RealComponentAnnotation extends ComponentAnnotation {
+
+    @Override
+    @Memoized
+    ImmutableList<AnnotationValue> dependencyValues() {
+      return isSubcomponent() ? ImmutableList.of() : getAnnotationValues("dependencies");
+    }
+
+    @Override
+    @Memoized
+    ImmutableList<TypeMirror> dependencyTypes() {
+      return super.dependencyTypes();
+    }
+
+    @Override
+    @Memoized
+    ImmutableList<TypeElement> dependencies() {
+      return super.dependencies();
+    }
+
+    @Override
+    boolean isRealComponent() {
+      return true;
+    }
+
+    @Override
+    @Memoized
+    ImmutableList<AnnotationValue> moduleValues() {
+      return getAnnotationValues("modules");
+    }
+
+    @Override
+    @Memoized
+    ImmutableList<TypeMirror> moduleTypes() {
+      return super.moduleTypes();
+    }
+
+    @Override
+    @Memoized
+    ImmutableSet<TypeElement> modules() {
+      return super.modules();
+    }
+
+    static Builder builder() {
+      return new AutoValue_ComponentAnnotation_RealComponentAnnotation.Builder();
+    }
+
+    @AutoValue.Builder
+    interface Builder {
+      Builder annotation(AnnotationMirror annotation);
+
+      Builder isSubcomponent(boolean isSubcomponent);
+
+      Builder isProduction(boolean isProduction);
+
+      RealComponentAnnotation build();
+    }
+  }
+
+  /**
+   * A fictional component annotation used to represent modules or other collections of bindings as
+   * a component.
+   */
+  @AutoValue
+  abstract static class FictionalComponentAnnotation extends ComponentAnnotation {
+
+    @Override
+    AnnotationMirror annotation() {
+      return moduleAnnotation().annotation();
+    }
+
+    @Override
+    boolean isSubcomponent() {
+      return false;
+    }
+
+    @Override
+    boolean isProduction() {
+      return moduleAnnotation().annotationClass().equals(ProducerModule.class);
+    }
+
+    @Override
+    boolean isRealComponent() {
+      return false;
+    }
+
+    @Override
+    ImmutableList<AnnotationValue> dependencyValues() {
+      return ImmutableList.of();
+    }
+
+    @Override
+    ImmutableList<AnnotationValue> moduleValues() {
+      return moduleAnnotation().includesAsAnnotationValues();
+    }
+
+    @Override
+    @Memoized
+    ImmutableList<TypeMirror> moduleTypes() {
+      return super.moduleTypes();
+    }
+
+    @Override
+    @Memoized
+    ImmutableSet<TypeElement> modules() {
+      return super.modules();
+    }
+
+    abstract ModuleAnnotation moduleAnnotation();
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
new file mode 100644
index 0000000..37cf1e8
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -0,0 +1,713 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Verify.verify;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.BindingType.MEMBERS_INJECTION;
+import static dagger.internal.codegen.DelegateBindingExpression.isBindsScopeStrongerThanDependencyScope;
+import static dagger.internal.codegen.MemberSelect.staticFactoryCreation;
+import static dagger.internal.codegen.RequestKinds.isDerivedFromProvider;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.DOUBLE_CHECK;
+import static dagger.internal.codegen.javapoet.TypeNames.SINGLE_CHECK;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypePubliclyAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static dagger.model.BindingKind.DELEGATE;
+import static dagger.model.BindingKind.MULTIBOUND_MAP;
+import static dagger.model.BindingKind.MULTIBOUND_SET;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.MethodBindingExpression.MethodImplementationStrategy;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import dagger.model.RequestKind;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.type.TypeMirror;
+
+/** A central repository of code expressions used to access any binding available to a component. */
+@PerComponentImplementation
+final class ComponentBindingExpressions {
+  // TODO(dpb,ronshapiro): refactor this and ComponentRequirementExpressions into a
+  // HierarchicalComponentMap<K, V>, or perhaps this use a flattened ImmutableMap, built from its
+  // parents? If so, maybe make BindingExpression.Factory create it.
+
+  private final Optional<ComponentBindingExpressions> parent;
+  private final BindingGraph graph;
+  private final ComponentImplementation componentImplementation;
+  private final ComponentRequirementExpressions componentRequirementExpressions;
+  private final OptionalFactories optionalFactories;
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+  private final SourceVersion sourceVersion;
+  private final CompilerOptions compilerOptions;
+  private final MembersInjectionMethods membersInjectionMethods;
+  private final InnerSwitchingProviders innerSwitchingProviders;
+  private final ModifiableBindingExpressions modifiableBindingExpressions;
+  private final Map<BindingRequest, BindingExpression> expressions = new HashMap<>();
+
+  @Inject
+  ComponentBindingExpressions(
+      @ParentComponent Optional<ComponentBindingExpressions> parent,
+      BindingGraph graph,
+      ComponentImplementation componentImplementation,
+      ComponentRequirementExpressions componentRequirementExpressions,
+      OptionalFactories optionalFactories,
+      DaggerTypes types,
+      DaggerElements elements,
+      SourceVersion sourceVersion,
+      @GenerationCompilerOptions CompilerOptions compilerOptions) {
+    this.parent = parent;
+    this.graph = graph;
+    this.componentImplementation = componentImplementation;
+    this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
+    this.optionalFactories = checkNotNull(optionalFactories);
+    this.types = checkNotNull(types);
+    this.elements = checkNotNull(elements);
+    this.sourceVersion = checkNotNull(sourceVersion);
+    this.compilerOptions = checkNotNull(compilerOptions);
+    this.membersInjectionMethods =
+        new MembersInjectionMethods(componentImplementation, this, graph, elements, types);
+    this.innerSwitchingProviders =
+        new InnerSwitchingProviders(componentImplementation, this, types);
+    this.modifiableBindingExpressions =
+        new ModifiableBindingExpressions(
+            parent.map(cbe -> cbe.modifiableBindingExpressions),
+            this,
+            graph,
+            componentImplementation,
+            compilerOptions,
+            types);
+  }
+
+  /* Returns the {@link ModifiableBindingExpressions} for this component. */
+  ModifiableBindingExpressions modifiableBindingExpressions() {
+    return modifiableBindingExpressions;
+  }
+
+  /**
+   * Returns an expression that evaluates to the value of a binding request for a binding owned by
+   * this component or an ancestor.
+   *
+   * @param requestingClass the class that will contain the expression
+   * @throws IllegalStateException if there is no binding expression that satisfies the request
+   */
+  Expression getDependencyExpression(BindingRequest request, ClassName requestingClass) {
+    return getBindingExpression(request).getDependencyExpression(requestingClass);
+  }
+
+  /**
+   * Equivalent to {@link #getDependencyExpression(BindingRequest, ClassName)} that is used only
+   * when the request is for implementation of a component method.
+   *
+   * @throws IllegalStateException if there is no binding expression that satisfies the request
+   */
+  Expression getDependencyExpressionForComponentMethod(
+      BindingRequest request,
+      ComponentMethodDescriptor componentMethod,
+      ComponentImplementation componentImplementation) {
+    return getBindingExpression(request)
+        .getDependencyExpressionForComponentMethod(componentMethod, componentImplementation);
+  }
+
+  /**
+   * Returns the {@link CodeBlock} for the method arguments used with the factory {@code create()}
+   * method for the given {@link ContributionBinding binding}.
+   */
+  CodeBlock getCreateMethodArgumentsCodeBlock(ContributionBinding binding) {
+    return makeParametersCodeBlock(getCreateMethodArgumentsCodeBlocks(binding));
+  }
+
+  private ImmutableList<CodeBlock> getCreateMethodArgumentsCodeBlocks(ContributionBinding binding) {
+    ImmutableList.Builder<CodeBlock> arguments = ImmutableList.builder();
+
+    if (binding.requiresModuleInstance()) {
+      arguments.add(
+          componentRequirementExpressions.getExpressionDuringInitialization(
+              ComponentRequirement.forModule(binding.contributingModule().get().asType()),
+              componentImplementation.name()));
+    }
+
+    binding.frameworkDependencies().stream()
+        .map(BindingRequest::bindingRequest)
+        .map(request -> getDependencyExpression(request, componentImplementation.name()))
+        .map(Expression::codeBlock)
+        .forEach(arguments::add);
+
+    return arguments.build();
+  }
+
+  /**
+   * Returns an expression that evaluates to the value of a dependency request, for passing to a
+   * binding method, an {@code @Inject}-annotated constructor or member, or a proxy for one.
+   *
+   * <p>If the method is a generated static {@link InjectionMethods injection method}, each
+   * parameter will be {@link Object} if the dependency's raw type is inaccessible. If that is the
+   * case for this dependency, the returned expression will use a cast to evaluate to the raw type.
+   *
+   * @param requestingClass the class that will contain the expression
+   */
+  Expression getDependencyArgumentExpression(
+      DependencyRequest dependencyRequest, ClassName requestingClass) {
+
+    TypeMirror dependencyType = dependencyRequest.key().type();
+    BindingRequest bindingRequest = bindingRequest(dependencyRequest);
+    Expression dependencyExpression = getDependencyExpression(bindingRequest, requestingClass);
+
+    if (compilerOptions.aheadOfTimeSubcomponents()) {
+      TypeMirror requestedType =
+          bindingRequest.requestedType(dependencyRequest.key().type(), types);
+      // If dependencyExpression.type() has been erased to it's publicly accessible type in AOT,
+      // we must sometimes cast the expression so that it is usable in the current component. To do
+      // so, we check that without the cast the assignment would fail, that argument to this proxy
+      // method erased the type, and that the raw type of the requested type is actually accessible
+      // in the current class so that the cast is valid.
+      if (!types.isAssignable(dependencyExpression.type(), requestedType)
+          && !isRawTypePubliclyAccessible(requestedType)
+          && isRawTypeAccessible(requestedType, requestingClass.packageName())) {
+        return dependencyExpression.castTo(types.erasure(requestedType));
+      }
+    }
+
+    if (dependencyRequest.kind().equals(RequestKind.INSTANCE)
+        && !isTypeAccessibleFrom(dependencyType, requestingClass.packageName())
+        && isRawTypeAccessible(dependencyType, requestingClass.packageName())) {
+      return dependencyExpression.castTo(types.erasure(dependencyType));
+    }
+
+    return dependencyExpression;
+  }
+
+  /** Returns the implementation of a component method. */
+  MethodSpec getComponentMethod(ComponentMethodDescriptor componentMethod) {
+    checkArgument(componentMethod.dependencyRequest().isPresent());
+    BindingRequest request = bindingRequest(componentMethod.dependencyRequest().get());
+    MethodSpec.Builder method =
+        MethodSpec.overriding(
+            componentMethod.methodElement(),
+            MoreTypes.asDeclared(graph.componentTypeElement().asType()),
+            types);
+    // Even though this is not used if the method is abstract, we need to invoke the binding
+    // expression in order for the side of effect of the method being added to the
+    // ComponentImplementation
+    CodeBlock methodBody =
+        getBindingExpression(request)
+            .getComponentMethodImplementation(componentMethod, componentImplementation);
+    if (!componentImplementation.superclassImplementation().isPresent()
+        && !modifiableBindingExpressions
+            .getModifiableBindingType(request)
+            .hasBaseClassImplementation()
+        && !componentImplementation.getModifiableBindingMethod(request).isPresent()) {
+      return method.addModifiers(ABSTRACT).build();
+    }
+    return method.addCode(methodBody).build();
+  }
+
+  /** Returns the {@link BindingExpression} for the given {@link BindingRequest}. */
+  BindingExpression getBindingExpression(BindingRequest request) {
+    if (expressions.containsKey(request)) {
+      return expressions.get(request);
+    }
+    Optional<BindingExpression> expression =
+        modifiableBindingExpressions.maybeCreateModifiableBindingExpression(request);
+    if (!expression.isPresent()) {
+      ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
+      if (resolvedBindings != null
+          && !resolvedBindings.bindingsOwnedBy(graph.componentDescriptor()).isEmpty()) {
+        expression = Optional.of(createBindingExpression(resolvedBindings, request));
+      }
+    }
+    if (!expression.isPresent()
+        && compilerOptions.aheadOfTimeSubcomponents()
+        && request.requestKind().isPresent()
+        && isDerivedFromProvider(request.requestKind().get())) {
+      RequestKind requestKind = request.requestKind().get();
+      expression =
+          Optional.of(
+              new DerivedFromFrameworkInstanceBindingExpression(
+                  request.key(), FrameworkType.PROVIDER, requestKind, this, types));
+    }
+
+    if (expression.isPresent()) {
+      expressions.put(request, expression.get());
+      return expression.get();
+    }
+    checkArgument(parent.isPresent(), "no expression found for %s", request);
+    return parent.get().getBindingExpression(request);
+  }
+
+  /** Creates a binding expression. */
+  BindingExpression createBindingExpression(
+      ResolvedBindings resolvedBindings, BindingRequest request) {
+    switch (resolvedBindings.bindingType()) {
+      case MEMBERS_INJECTION:
+        checkArgument(request.isRequestKind(RequestKind.MEMBERS_INJECTION));
+        return new MembersInjectionBindingExpression(resolvedBindings, membersInjectionMethods);
+
+      case PROVISION:
+        return provisionBindingExpression(resolvedBindings, request);
+
+      case PRODUCTION:
+        return productionBindingExpression(resolvedBindings, request);
+    }
+    throw new AssertionError(resolvedBindings);
+  }
+
+  /**
+   * Returns a binding expression that uses a {@link javax.inject.Provider} for provision bindings
+   * or a {@link dagger.producers.Producer} for production bindings.
+   */
+  private BindingExpression frameworkInstanceBindingExpression(ResolvedBindings resolvedBindings) {
+    // TODO(user): Consider merging the static factory creation logic into CreationExpressions?
+    Optional<MemberSelect> staticMethod =
+        useStaticFactoryCreation(resolvedBindings.contributionBinding())
+            ? staticFactoryCreation(resolvedBindings)
+            : Optional.empty();
+    FrameworkInstanceCreationExpression frameworkInstanceCreationExpression =
+        resolvedBindings.scope().isPresent()
+            ? scope(resolvedBindings, frameworkInstanceCreationExpression(resolvedBindings))
+            : frameworkInstanceCreationExpression(resolvedBindings);
+    FrameworkInstanceSupplier frameworkInstanceSupplier =
+        staticMethod.isPresent()
+            ? staticMethod::get
+            : new FrameworkFieldInitializer(
+                componentImplementation, resolvedBindings, frameworkInstanceCreationExpression);
+
+    switch (resolvedBindings.bindingType()) {
+      case PROVISION:
+        return new ProviderInstanceBindingExpression(
+            resolvedBindings, frameworkInstanceSupplier, types, elements);
+      case PRODUCTION:
+        return new ProducerNodeInstanceBindingExpression(
+            resolvedBindings, frameworkInstanceSupplier, types, elements, componentImplementation);
+      default:
+        throw new AssertionError("invalid binding type: " + resolvedBindings.bindingType());
+    }
+  }
+
+  private FrameworkInstanceCreationExpression scope(
+      ResolvedBindings resolvedBindings, FrameworkInstanceCreationExpression unscoped) {
+    return () ->
+        CodeBlock.of(
+            "$T.provider($L)",
+            resolvedBindings.scope().get().isReusable() ? SINGLE_CHECK : DOUBLE_CHECK,
+            unscoped.creationExpression());
+  }
+
+  /**
+   * Returns a creation expression for a {@link javax.inject.Provider} for provision bindings or a
+   * {@link dagger.producers.Producer} for production bindings.
+   */
+  private FrameworkInstanceCreationExpression frameworkInstanceCreationExpression(
+      ResolvedBindings resolvedBindings) {
+    checkArgument(!resolvedBindings.bindingType().equals(MEMBERS_INJECTION));
+    ContributionBinding binding = resolvedBindings.contributionBinding();
+    switch (binding.kind()) {
+      case COMPONENT:
+        // The cast can be removed when we drop java 7 source support
+        return new InstanceFactoryCreationExpression(
+            () -> CodeBlock.of("($T) this", binding.key().type()));
+
+      case BOUND_INSTANCE:
+        return instanceFactoryCreationExpression(
+            binding, ComponentRequirement.forBoundInstance(binding));
+
+      case COMPONENT_DEPENDENCY:
+        return instanceFactoryCreationExpression(
+            binding, ComponentRequirement.forDependency(binding.key().type()));
+
+      case COMPONENT_PROVISION:
+        return new DependencyMethodProviderCreationExpression(
+            binding,
+            componentImplementation,
+            componentRequirementExpressions,
+            compilerOptions,
+            graph);
+
+      case SUBCOMPONENT_CREATOR:
+        return new AnonymousProviderCreationExpression(
+            binding, this, componentImplementation.name());
+
+      case INJECTION:
+      case PROVISION:
+        return new InjectionOrProvisionProviderCreationExpression(binding, this);
+
+      case COMPONENT_PRODUCTION:
+        return new DependencyMethodProducerCreationExpression(
+            binding, componentImplementation, componentRequirementExpressions, graph);
+
+      case PRODUCTION:
+        return new ProducerCreationExpression(binding, this);
+
+      case MULTIBOUND_SET:
+        return new SetFactoryCreationExpression(binding, componentImplementation, this, graph);
+
+      case MULTIBOUND_MAP:
+        return new MapFactoryCreationExpression(
+            binding, componentImplementation, this, graph, elements);
+
+      case DELEGATE:
+        return new DelegatingFrameworkInstanceCreationExpression(
+            binding, componentImplementation, this);
+
+      case OPTIONAL:
+        return new OptionalFactoryInstanceCreationExpression(
+            optionalFactories, binding, componentImplementation, this);
+
+      case MEMBERS_INJECTOR:
+        return new MembersInjectorProviderCreationExpression((ProvisionBinding) binding, this);
+
+      default:
+        throw new AssertionError(binding);
+    }
+  }
+
+  private InstanceFactoryCreationExpression instanceFactoryCreationExpression(
+      ContributionBinding binding, ComponentRequirement componentRequirement) {
+    return new InstanceFactoryCreationExpression(
+        binding.nullableType().isPresent(),
+        () ->
+            componentRequirementExpressions.getExpressionDuringInitialization(
+                componentRequirement, componentImplementation.name()));
+  }
+
+  /** Returns a binding expression for a provision binding. */
+  private BindingExpression provisionBindingExpression(
+      ResolvedBindings resolvedBindings, BindingRequest request) {
+    if (!request.requestKind().isPresent()) {
+      verify(
+          request.frameworkType().get().equals(FrameworkType.PRODUCER_NODE),
+          "expected a PRODUCER_NODE: %s",
+          request);
+      return producerFromProviderBindingExpression(resolvedBindings);
+    }
+    RequestKind requestKind = request.requestKind().get();
+    switch (requestKind) {
+      case INSTANCE:
+        return instanceBindingExpression(resolvedBindings);
+
+      case PROVIDER:
+        return providerBindingExpression(resolvedBindings);
+
+      case LAZY:
+      case PRODUCED:
+      case PROVIDER_OF_LAZY:
+        return new DerivedFromFrameworkInstanceBindingExpression(
+            resolvedBindings.key(), FrameworkType.PROVIDER, requestKind, this, types);
+
+      case PRODUCER:
+        return producerFromProviderBindingExpression(resolvedBindings);
+
+      case FUTURE:
+        return new ImmediateFutureBindingExpression(resolvedBindings, this, types, sourceVersion);
+
+      case MEMBERS_INJECTION:
+        throw new IllegalArgumentException();
+    }
+
+    throw new AssertionError();
+  }
+
+  /** Returns a binding expression for a production binding. */
+  private BindingExpression productionBindingExpression(
+      ResolvedBindings resolvedBindings, BindingRequest request) {
+    if (request.frameworkType().isPresent()) {
+      return frameworkInstanceBindingExpression(resolvedBindings);
+    } else {
+      // If no FrameworkType is present, a RequestKind is guaranteed to be present.
+      RequestKind requestKind = request.requestKind().get();
+      return new DerivedFromFrameworkInstanceBindingExpression(
+          resolvedBindings.key(), FrameworkType.PRODUCER_NODE, requestKind, this, types);
+    }
+  }
+
+  /**
+   * Returns a binding expression for {@link RequestKind#PROVIDER} requests.
+   *
+   * <p>{@code @Binds} bindings that don't {@linkplain #needsCaching(ResolvedBindings) need to be
+   * cached} can use a {@link DelegateBindingExpression}.
+   *
+   * <p>In fastInit mode, use an {@link InnerSwitchingProviders inner switching provider} unless
+   * that provider's case statement will simply call {@code get()} on another {@link Provider} (in
+   * which case, just use that Provider directly).
+   *
+   * <p>Otherwise, return a {@link FrameworkInstanceBindingExpression}.
+   */
+  private BindingExpression providerBindingExpression(ResolvedBindings resolvedBindings) {
+    if (resolvedBindings.contributionBinding().kind().equals(DELEGATE)
+        && !needsCaching(resolvedBindings)) {
+      return new DelegateBindingExpression(
+          resolvedBindings, RequestKind.PROVIDER, this, types, elements);
+    } else if (compilerOptions.fastInit()
+        && frameworkInstanceCreationExpression(resolvedBindings).useInnerSwitchingProvider()
+        && !(instanceBindingExpression(resolvedBindings)
+            instanceof DerivedFromFrameworkInstanceBindingExpression)) {
+      return wrapInMethod(
+          resolvedBindings,
+          bindingRequest(resolvedBindings.key(), RequestKind.PROVIDER),
+          innerSwitchingProviders.newBindingExpression(resolvedBindings.contributionBinding()));
+    }
+    return frameworkInstanceBindingExpression(resolvedBindings);
+  }
+
+  /**
+   * Returns a binding expression that uses a {@link dagger.producers.Producer} field for a
+   * provision binding.
+   */
+  private FrameworkInstanceBindingExpression producerFromProviderBindingExpression(
+      ResolvedBindings resolvedBindings) {
+    checkArgument(resolvedBindings.bindingType().equals(BindingType.PROVISION));
+    return new ProducerNodeInstanceBindingExpression(
+        resolvedBindings,
+        new FrameworkFieldInitializer(
+            componentImplementation,
+            resolvedBindings,
+            new ProducerFromProviderCreationExpression(
+                resolvedBindings.contributionBinding(), componentImplementation, this)),
+        types,
+        elements,
+        componentImplementation);
+  }
+
+  /**
+   * Returns a binding expression for {@link RequestKind#INSTANCE} requests.
+   *
+   * <p>If there is a direct expression (not calling {@link Provider#get()}) we can use for an
+   * instance of this binding, return it, wrapped in a method if the binding {@linkplain
+   * #needsCaching(ResolvedBindings) needs to be cached} or the expression has dependencies.
+   *
+   * <p>In fastInit mode, we can use direct expressions unless the binding needs to be cached.
+   */
+  private BindingExpression instanceBindingExpression(ResolvedBindings resolvedBindings) {
+    Optional<BindingExpression> maybeDirectInstanceExpression =
+        unscopedDirectInstanceExpression(resolvedBindings);
+    if (canUseDirectInstanceExpression(resolvedBindings)
+        && maybeDirectInstanceExpression.isPresent()) {
+      BindingExpression directInstanceExpression = maybeDirectInstanceExpression.get();
+      return directInstanceExpression.requiresMethodEncapsulation()
+              || needsCaching(resolvedBindings)
+          ? wrapInMethod(
+              resolvedBindings,
+              bindingRequest(resolvedBindings.key(), RequestKind.INSTANCE),
+              directInstanceExpression)
+          : directInstanceExpression;
+    }
+    return new DerivedFromFrameworkInstanceBindingExpression(
+        resolvedBindings.key(), FrameworkType.PROVIDER, RequestKind.INSTANCE, this, types);
+  }
+
+  /**
+   * Returns an unscoped binding expression for an {@link RequestKind#INSTANCE} that does not call
+   * {@code get()} on its provider, if there is one.
+   */
+  private Optional<BindingExpression> unscopedDirectInstanceExpression(
+      ResolvedBindings resolvedBindings) {
+    switch (resolvedBindings.contributionBinding().kind()) {
+      case DELEGATE:
+        return Optional.of(
+            new DelegateBindingExpression(
+                resolvedBindings, RequestKind.INSTANCE, this, types, elements));
+
+      case COMPONENT:
+        return Optional.of(
+            new ComponentInstanceBindingExpression(
+                resolvedBindings, componentImplementation.name()));
+
+      case COMPONENT_DEPENDENCY:
+        return Optional.of(
+            new ComponentRequirementBindingExpression(
+                resolvedBindings,
+                ComponentRequirement.forDependency(resolvedBindings.key().type()),
+                componentRequirementExpressions));
+
+      case COMPONENT_PROVISION:
+        return Optional.of(
+            new ComponentProvisionBindingExpression(
+                resolvedBindings, graph, componentRequirementExpressions, compilerOptions));
+
+      case SUBCOMPONENT_CREATOR:
+        return Optional.of(
+            new SubcomponentCreatorBindingExpression(
+                resolvedBindings,
+                componentImplementation.getSubcomponentCreatorSimpleName(resolvedBindings.key())));
+
+      case MULTIBOUND_SET:
+        return Optional.of(
+            new SetBindingExpression(
+                resolvedBindings, componentImplementation, graph, this, types, elements));
+
+      case MULTIBOUND_MAP:
+        return Optional.of(
+            new MapBindingExpression(
+                resolvedBindings, componentImplementation, graph, this, types, elements));
+
+      case OPTIONAL:
+        return Optional.of(
+            new OptionalBindingExpression(resolvedBindings, this, types, sourceVersion));
+
+      case BOUND_INSTANCE:
+        return Optional.of(
+            new ComponentRequirementBindingExpression(
+                resolvedBindings,
+                ComponentRequirement.forBoundInstance(resolvedBindings.contributionBinding()),
+                componentRequirementExpressions));
+
+      case INJECTION:
+      case PROVISION:
+        return Optional.of(
+            new SimpleMethodBindingExpression(
+                resolvedBindings,
+                compilerOptions,
+                this,
+                membersInjectionMethods,
+                componentRequirementExpressions,
+                types,
+                elements,
+                sourceVersion));
+
+      case MEMBERS_INJECTOR:
+        return Optional.empty();
+
+      case MEMBERS_INJECTION:
+      case COMPONENT_PRODUCTION:
+      case PRODUCTION:
+        throw new IllegalArgumentException(
+            resolvedBindings.contributionBinding().kind().toString());
+    }
+    throw new AssertionError();
+  }
+
+  /**
+   * Returns {@code true} if the binding should use the static factory creation strategy.
+   *
+   * <p>In default mode, we always use the static factory creation strategy. In fastInit mode, we
+   * prefer to use a SwitchingProvider instead of static factories in order to reduce class loading;
+   * however, we allow static factories that can reused across multiple bindings, e.g. {@code
+   * MapFactory} or {@code SetFactory}.
+   */
+  private boolean useStaticFactoryCreation(ContributionBinding binding) {
+    return !compilerOptions.fastInit()
+        || binding.kind().equals(MULTIBOUND_MAP)
+        || binding.kind().equals(MULTIBOUND_SET);
+  }
+
+  /**
+   * Returns {@code true} if we can use a direct (not {@code Provider.get()}) expression for this
+   * binding. If the binding doesn't {@linkplain #needsCaching(ResolvedBindings) need to be cached},
+   * we can.
+   *
+   * <p>In fastInit mode, we can use a direct expression even if the binding {@linkplain
+   * #needsCaching(ResolvedBindings) needs to be cached}.
+   */
+  private boolean canUseDirectInstanceExpression(ResolvedBindings resolvedBindings) {
+    return !needsCaching(resolvedBindings) || compilerOptions.fastInit();
+  }
+
+  /**
+   * Returns a binding expression that uses a given one as the body of a method that users call. If
+   * a component provision method matches it, it will be the method implemented. If it does not
+   * match a component provision method and the binding is modifiable, then a new public modifiable
+   * binding method will be written. If the binding doesn't match a component method and is not
+   * modifiable, then a new private method will be written.
+   */
+  BindingExpression wrapInMethod(
+      ResolvedBindings resolvedBindings,
+      BindingRequest request,
+      BindingExpression bindingExpression) {
+    // If we've already wrapped the expression, then use the delegate.
+    if (bindingExpression instanceof MethodBindingExpression) {
+      return bindingExpression;
+    }
+
+    MethodImplementationStrategy methodImplementationStrategy =
+        methodImplementationStrategy(resolvedBindings, request);
+    Optional<ComponentMethodDescriptor> matchingComponentMethod =
+        graph.componentDescriptor().firstMatchingComponentMethod(request);
+
+    if (modifiableBindingExpressions.getModifiableBindingType(request).isModifiable()
+        && (componentImplementation.superclassImplementation().isPresent()
+            || !matchingComponentMethod.isPresent())) {
+      return modifiableBindingExpressions.wrapInModifiableMethodBindingExpression(
+          request, resolvedBindings, methodImplementationStrategy, bindingExpression);
+    } else if (matchingComponentMethod.isPresent()) {
+      ComponentMethodDescriptor componentMethod = matchingComponentMethod.get();
+      return new ComponentMethodBindingExpression(
+          request,
+          resolvedBindings,
+          methodImplementationStrategy,
+          bindingExpression,
+          componentImplementation,
+          componentMethod,
+          types);
+    } else {
+      return new PrivateMethodBindingExpression(
+          request,
+          resolvedBindings,
+          methodImplementationStrategy,
+          bindingExpression,
+          componentImplementation,
+          types);
+    }
+  }
+
+  private MethodImplementationStrategy methodImplementationStrategy(
+      ResolvedBindings resolvedBindings, BindingRequest request) {
+    if (compilerOptions.fastInit()) {
+      if (request.isRequestKind(RequestKind.PROVIDER)) {
+        return MethodImplementationStrategy.SINGLE_CHECK;
+      } else if (request.isRequestKind(RequestKind.INSTANCE) && needsCaching(resolvedBindings)) {
+        return resolvedBindings.scope().get().isReusable()
+            ? MethodImplementationStrategy.SINGLE_CHECK
+            : MethodImplementationStrategy.DOUBLE_CHECK;
+      }
+    }
+    return MethodImplementationStrategy.SIMPLE;
+  }
+
+  /**
+   * Returns {@code true} if the component needs to make sure the provided value is cached.
+   *
+   * <p>The component needs to cache the value for scoped bindings except for {@code @Binds}
+   * bindings whose scope is no stronger than their delegate's.
+   */
+  private boolean needsCaching(ResolvedBindings resolvedBindings) {
+    if (!resolvedBindings.scope().isPresent()) {
+      return false;
+    }
+    if (resolvedBindings.contributionBinding().kind().equals(DELEGATE)) {
+      return isBindsScopeStrongerThanDependencyScope(resolvedBindings, graph);
+    }
+    return true;
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentCreatorAnnotation.java b/java/dagger/internal/codegen/ComponentCreatorAnnotation.java
new file mode 100644
index 0000000..31bbfab
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentCreatorAnnotation.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2019 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.MoreElements.isAnnotationPresent;
+import static com.google.common.base.Ascii.toUpperCase;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.DaggerStreams.valuesOf;
+import static java.util.stream.Collectors.mapping;
+
+import com.google.common.collect.ImmutableSet;
+import dagger.Component;
+import dagger.Subcomponent;
+import dagger.producers.ProductionComponent;
+import dagger.producers.ProductionSubcomponent;
+import java.lang.annotation.Annotation;
+import java.util.stream.Collector;
+import java.util.stream.Stream;
+import javax.lang.model.element.TypeElement;
+
+/** Simple representation of a component creator annotation type. */
+enum ComponentCreatorAnnotation {
+  COMPONENT_BUILDER(Component.Builder.class),
+  COMPONENT_FACTORY(Component.Factory.class),
+  SUBCOMPONENT_BUILDER(Subcomponent.Builder.class),
+  SUBCOMPONENT_FACTORY(Subcomponent.Factory.class),
+  PRODUCTION_COMPONENT_BUILDER(ProductionComponent.Builder.class),
+  PRODUCTION_COMPONENT_FACTORY(ProductionComponent.Factory.class),
+  PRODUCTION_SUBCOMPONENT_BUILDER(ProductionSubcomponent.Builder.class),
+  PRODUCTION_SUBCOMPONENT_FACTORY(ProductionSubcomponent.Factory.class),
+  ;
+
+  private final Class<? extends Annotation> annotation;
+  private final ComponentCreatorKind creatorKind;
+  private final Class<? extends Annotation> componentAnnotation;
+
+  ComponentCreatorAnnotation(Class<? extends Annotation> annotation) {
+    this.annotation = annotation;
+    this.creatorKind = ComponentCreatorKind.valueOf(toUpperCase(annotation.getSimpleName()));
+    this.componentAnnotation = (Class<? extends Annotation>) annotation.getEnclosingClass();
+  }
+
+  /** The actual annotation type. */
+  Class<? extends Annotation> annotation() {
+    return annotation;
+  }
+
+  /** The component annotation type that encloses this creator annotation type. */
+  final Class<? extends Annotation> componentAnnotation() {
+    return componentAnnotation;
+  }
+
+  /** Returns {@code true} if the creator annotation is for a subcomponent. */
+  final boolean isSubcomponentCreatorAnnotation() {
+    return componentAnnotation().getSimpleName().endsWith("Subcomponent");
+  }
+
+  /**
+   * Returns {@code true} if the creator annotation is for a production component or subcomponent.
+   */
+  final boolean isProductionCreatorAnnotation() {
+    return componentAnnotation().getSimpleName().startsWith("Production");
+  }
+
+  /** The creator kind the annotation is associated with. */
+  // TODO(dpb): Remove ComponentCreatorKind.
+  ComponentCreatorKind creatorKind() {
+    return creatorKind;
+  }
+
+  @Override
+  public final String toString() {
+    return annotation().getName();
+  }
+
+  /** Returns all component creator annotations. */
+  static ImmutableSet<Class<? extends Annotation>> allCreatorAnnotations() {
+    return stream().collect(toAnnotationClasses());
+  }
+
+  /** Returns all root component creator annotations. */
+  static ImmutableSet<Class<? extends Annotation>> rootComponentCreatorAnnotations() {
+    return stream()
+        .filter(
+            componentCreatorAnnotation ->
+                !componentCreatorAnnotation.isSubcomponentCreatorAnnotation())
+        .collect(toAnnotationClasses());
+  }
+
+  /** Returns all subcomponent creator annotations. */
+  static ImmutableSet<Class<? extends Annotation>> subcomponentCreatorAnnotations() {
+    return stream()
+        .filter(
+            componentCreatorAnnotation ->
+                componentCreatorAnnotation.isSubcomponentCreatorAnnotation())
+        .collect(toAnnotationClasses());
+  }
+
+  /** Returns all production component creator annotations. */
+  static ImmutableSet<Class<? extends Annotation>> productionCreatorAnnotations() {
+    return stream()
+        .filter(
+            componentCreatorAnnotation ->
+                componentCreatorAnnotation.isProductionCreatorAnnotation())
+        .collect(toAnnotationClasses());
+  }
+
+  /** Returns the legal creator annotations for the given {@code componentAnnotation}. */
+  static ImmutableSet<Class<? extends Annotation>> creatorAnnotationsFor(
+      ComponentAnnotation componentAnnotation) {
+    return stream()
+        .filter(
+            creatorAnnotation ->
+                creatorAnnotation
+                    .componentAnnotation()
+                    .getSimpleName()
+                    .equals(componentAnnotation.simpleName()))
+        .collect(toAnnotationClasses());
+  }
+
+  /** Returns all creator annotations present on the given {@code type}. */
+  static ImmutableSet<ComponentCreatorAnnotation> getCreatorAnnotations(TypeElement type) {
+    return stream()
+        .filter(cca -> isAnnotationPresent(type, cca.annotation()))
+        .collect(toImmutableSet());
+  }
+
+  private static Stream<ComponentCreatorAnnotation> stream() {
+    return valuesOf(ComponentCreatorAnnotation.class);
+  }
+
+  private static Collector<ComponentCreatorAnnotation, ?, ImmutableSet<Class<? extends Annotation>>>
+      toAnnotationClasses() {
+    return mapping(ComponentCreatorAnnotation::annotation, toImmutableSet());
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentCreatorDescriptor.java b/java/dagger/internal/codegen/ComponentCreatorDescriptor.java
new file mode 100644
index 0000000..f6ec7a2
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentCreatorDescriptor.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2014 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.MoreElements.isAnnotationPresent;
+import static com.google.auto.common.MoreTypes.asTypeElement;
+import static com.google.common.base.Verify.verify;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.getCreatorAnnotations;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import dagger.BindsInstance;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import java.util.List;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A descriptor for a component <i>creator</i> type: that is, a type annotated with
+ * {@code @Component.Builder} (or one of the corresponding production or subcomponent versions).
+ */
+@AutoValue
+abstract class ComponentCreatorDescriptor {
+
+  /** Returns the annotation marking this creator. */
+  abstract ComponentCreatorAnnotation annotation();
+
+  /** The kind of this creator. */
+  final ComponentCreatorKind kind() {
+    return annotation().creatorKind();
+  }
+
+  /** The annotated creator type. */
+  abstract TypeElement typeElement();
+
+  /** The method that creates and returns a component instance. */
+  abstract ExecutableElement factoryMethod();
+
+  /**
+   * Multimap of component requirements to setter methods that set that requirement.
+   *
+   * <p>In a valid creator, there will be exactly one element per component requirement, so this
+   * method should only be called when validating the descriptor.
+   */
+  abstract ImmutableSetMultimap<ComponentRequirement, ExecutableElement> unvalidatedSetterMethods();
+
+  /**
+   * Multimap of component requirements to factory method parameters that set that requirement.
+   *
+   * <p>In a valid creator, there will be exactly one element per component requirement, so this
+   * method should only be called when validating the descriptor.
+   */
+  abstract ImmutableSetMultimap<ComponentRequirement, VariableElement>
+      unvalidatedFactoryParameters();
+
+  /**
+   * Multimap of component requirements to elements (methods or parameters) that set that
+   * requirement.
+   *
+   * <p>In a valid creator, there will be exactly one element per component requirement, so this
+   * method should only be called when validating the descriptor.
+   */
+  final ImmutableSetMultimap<ComponentRequirement, Element> unvalidatedRequirementElements() {
+    // ComponentCreatorValidator ensures that there are either setter methods or factory method
+    // parameters, but not both, so we can cheat a little here since we know that only one of
+    // the two multimaps will be non-empty.
+    return ImmutableSetMultimap.copyOf( // no actual copy
+        unvalidatedSetterMethods().isEmpty()
+            ? unvalidatedFactoryParameters()
+            : unvalidatedSetterMethods());
+  }
+
+  /**
+   * Map of component requirements to elements (setter methods or factory method parameters) that
+   * set them.
+   */
+  @Memoized
+  ImmutableMap<ComponentRequirement, Element> requirementElements() {
+    return flatten(unvalidatedRequirementElements());
+  }
+
+  /** Map of component requirements to setter methods for those requirements. */
+  @Memoized
+  ImmutableMap<ComponentRequirement, ExecutableElement> setterMethods() {
+    return flatten(unvalidatedSetterMethods());
+  }
+
+  /** Map of component requirements to factory method parameters for those requirements. */
+  @Memoized
+  ImmutableMap<ComponentRequirement, VariableElement> factoryParameters() {
+    return flatten(unvalidatedFactoryParameters());
+  }
+
+  private static <K, V> ImmutableMap<K, V> flatten(Multimap<K, V> multimap) {
+    return ImmutableMap.copyOf(
+        Maps.transformValues(multimap.asMap(), values -> getOnlyElement(values)));
+  }
+
+  /** Returns the set of component requirements this creator allows the user to set. */
+  final ImmutableSet<ComponentRequirement> userSettableRequirements() {
+    // Note: they should have been validated at the point this is used, so this set is valid.
+    return unvalidatedRequirementElements().keySet();
+  }
+
+  /** Returns the set of requirements for modules and component dependencies for this creator. */
+  final ImmutableSet<ComponentRequirement> moduleAndDependencyRequirements() {
+    return userSettableRequirements().stream()
+        .filter(requirement -> !requirement.isBoundInstance())
+        .collect(toImmutableSet());
+  }
+
+  /** Returns the set of bound instance requirements for this creator. */
+  final ImmutableSet<ComponentRequirement> boundInstanceRequirements() {
+    return userSettableRequirements().stream()
+        .filter(ComponentRequirement::isBoundInstance)
+        .collect(toImmutableSet());
+  }
+
+  /** Returns the element in this creator that sets the given {@code requirement}. */
+  final Element elementForRequirement(ComponentRequirement requirement) {
+    return requirementElements().get(requirement);
+  }
+
+  /** Creates a new {@link ComponentCreatorDescriptor} for the given creator {@code type}. */
+  static ComponentCreatorDescriptor create(
+      DeclaredType type,
+      DaggerElements elements,
+      DaggerTypes types,
+      DependencyRequestFactory dependencyRequestFactory) {
+    TypeElement typeElement = asTypeElement(type);
+    TypeMirror componentType = typeElement.getEnclosingElement().asType();
+
+    ImmutableSetMultimap.Builder<ComponentRequirement, ExecutableElement> setterMethods =
+        ImmutableSetMultimap.builder();
+
+    ExecutableElement factoryMethod = null;
+    for (ExecutableElement method : elements.getUnimplementedMethods(typeElement)) {
+      ExecutableType resolvedMethodType = MoreTypes.asExecutable(types.asMemberOf(type, method));
+
+      if (types.isSubtype(componentType, resolvedMethodType.getReturnType())) {
+        factoryMethod = method;
+      } else {
+        VariableElement parameter = getOnlyElement(method.getParameters());
+        TypeMirror parameterType = getOnlyElement(resolvedMethodType.getParameterTypes());
+        setterMethods.put(
+            requirement(method, parameter, parameterType, dependencyRequestFactory, method),
+            method);
+      }
+    }
+    verify(factoryMethod != null); // validation should have ensured this.
+
+    ImmutableSetMultimap.Builder<ComponentRequirement, VariableElement> factoryParameters =
+        ImmutableSetMultimap.builder();
+
+    ExecutableType resolvedFactoryMethodType =
+        MoreTypes.asExecutable(types.asMemberOf(type, factoryMethod));
+    List<? extends VariableElement> parameters = factoryMethod.getParameters();
+    List<? extends TypeMirror> parameterTypes = resolvedFactoryMethodType.getParameterTypes();
+    for (int i = 0; i < parameters.size(); i++) {
+      VariableElement parameter = parameters.get(i);
+      TypeMirror parameterType = parameterTypes.get(i);
+      factoryParameters.put(
+          requirement(factoryMethod, parameter, parameterType, dependencyRequestFactory, parameter),
+          parameter);
+    }
+
+    // Validation should have ensured exactly one creator annotation is present on the type.
+    ComponentCreatorAnnotation annotation = getOnlyElement(getCreatorAnnotations(typeElement));
+    return new AutoValue_ComponentCreatorDescriptor(
+        annotation, typeElement, factoryMethod, setterMethods.build(), factoryParameters.build());
+  }
+
+  private static ComponentRequirement requirement(
+      ExecutableElement method,
+      VariableElement parameter,
+      TypeMirror type,
+      DependencyRequestFactory dependencyRequestFactory,
+      Element elementForVariableName) {
+    if (isAnnotationPresent(method, BindsInstance.class)
+        || isAnnotationPresent(parameter, BindsInstance.class)) {
+      DependencyRequest request =
+          dependencyRequestFactory.forRequiredResolvedVariable(parameter, type);
+      String variableName = elementForVariableName.getSimpleName().toString();
+      return ComponentRequirement.forBoundInstance(
+          request.key(), request.isNullable(), variableName);
+    }
+
+    return moduleAnnotation(asTypeElement(type)).isPresent()
+        ? ComponentRequirement.forModule(type)
+        : ComponentRequirement.forDependency(type);
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentCreatorImplementation.java b/java/dagger/internal/codegen/ComponentCreatorImplementation.java
new file mode 100644
index 0000000..a5eb680
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentCreatorImplementation.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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.ImmutableMap;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.TypeSpec;
+
+/** The implementation of a component creator type. */
+@AutoValue
+abstract class ComponentCreatorImplementation {
+
+  /** Creates a new {@link ComponentCreatorImplementation}. */
+  static ComponentCreatorImplementation create(
+      TypeSpec spec,
+      ClassName name,
+      ImmutableMap<ComponentRequirement, FieldSpec> fields) {
+    return new AutoValue_ComponentCreatorImplementation(spec, name, fields);
+  }
+
+  /** The type spec for the creator implementation. */
+  abstract TypeSpec spec();
+
+  /** The name of the creator implementation class. */
+  abstract ClassName name();
+
+  /**
+   * All fields that are present in this implementation or its supertype.
+   *
+   * <p>In the case of ahead-of-time subcomponents, not all fields will necessarily be passed to
+   * the component's constructor (because, for example, it turns out that a particular module that
+   * the creator can set is actually inherited from an ancestor module).
+   */
+  abstract ImmutableMap<ComponentRequirement, FieldSpec> fields();
+}
diff --git a/java/dagger/internal/codegen/ComponentCreatorImplementationFactory.java b/java/dagger/internal/codegen/ComponentCreatorImplementationFactory.java
new file mode 100644
index 0000000..4f06b90
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentCreatorImplementationFactory.java
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.SourceFiles.simpleVariableName;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeSpecs.addSupertype;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PROTECTED;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.Preconditions;
+import dagger.internal.codegen.ComponentRequirement.NullPolicy;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+
+/** Factory for creating {@link ComponentCreatorImplementation} instances. */
+final class ComponentCreatorImplementationFactory {
+
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+
+  @Inject
+  ComponentCreatorImplementationFactory(DaggerElements elements, DaggerTypes types) {
+    this.elements = elements;
+    this.types = types;
+  }
+
+  /** Returns a new creator implementation for the given component, if necessary. */
+  Optional<ComponentCreatorImplementation> create(
+      ComponentImplementation componentImplementation, Optional<BindingGraph> graph) {
+    if (!componentImplementation.componentDescriptor().hasCreator()) {
+      return Optional.empty();
+    }
+
+    Optional<ComponentCreatorDescriptor> creatorDescriptor =
+        componentImplementation.componentDescriptor().creatorDescriptor();
+
+    if (componentImplementation.isAbstract()
+        && (hasNoSetterMethods(creatorDescriptor)
+            || componentImplementation.superclassImplementation().isPresent())) {
+      // 1. Factory-like creators (those with no setter methods) are only generated in concrete
+      //    components, because they only have a factory method and the factory method must call
+      //    a concrete component's constructor.
+      // 2. The component builder in ahead-of-time mode is generated with the base subcomponent
+      //    implementation, with the exception of the build method since that requires invoking the
+      //    constructor of a concrete component implementation. Intermediate component
+      //    implementations, because they still can't invoke the eventual constructor and have no
+      //    additional extensions to the builder, can ignore generating a builder implementation.
+      return Optional.empty();
+    }
+
+    Builder builder =
+        creatorDescriptor.isPresent()
+            ? new BuilderForCreatorDescriptor(
+                componentImplementation, creatorDescriptor.get(), graph)
+            : new BuilderForGeneratedRootComponentBuilder(componentImplementation);
+    return Optional.of(builder.build());
+  }
+
+  private static boolean hasNoSetterMethods(
+      Optional<ComponentCreatorDescriptor> creatorDescriptor) {
+    return creatorDescriptor.filter(descriptor -> descriptor.setterMethods().isEmpty()).isPresent();
+  }
+
+  /** Base class for building a creator implementation. */
+  private abstract class Builder {
+    final ComponentImplementation componentImplementation;
+    final ClassName className;
+    final TypeSpec.Builder classBuilder;
+
+    private ImmutableMap<ComponentRequirement, FieldSpec> fields;
+
+    Builder(ComponentImplementation componentImplementation) {
+      this.componentImplementation = componentImplementation;
+      this.className = componentImplementation.getCreatorName();
+      this.classBuilder = classBuilder(className);
+    }
+
+    /** Builds the {@link ComponentCreatorImplementation}. */
+    ComponentCreatorImplementation build() {
+      setModifiers();
+      setSupertype();
+      this.fields = getOrAddFields();
+      addConstructor();
+      addSetterMethods();
+      addFactoryMethod();
+      return ComponentCreatorImplementation.create(classBuilder.build(), className, fields);
+    }
+
+    /** Returns the descriptor for the component. */
+    final ComponentDescriptor componentDescriptor() {
+      return componentImplementation.componentDescriptor();
+    }
+
+    /**
+     * The set of requirements that must be passed to the component's constructor in the order
+     * they must be passed.
+     */
+    final ImmutableSet<ComponentRequirement> componentConstructorRequirements() {
+      return componentImplementation.requirements();
+    }
+
+    /** Returns the requirements that have setter methods on the creator type. */
+    abstract ImmutableSet<ComponentRequirement> setterMethods();
+
+    /**
+     * Returns the component requirements that have factory method parameters, mapped to the name
+     * for that parameter.
+     */
+    abstract ImmutableMap<ComponentRequirement, String> factoryMethodParameters();
+
+    /**
+     * The {@link ComponentRequirement}s that this creator allows users to set. Values are a status
+     * for each requirement indicating what's needed for that requirement in the implementation
+     * class currently being generated.
+     */
+    abstract ImmutableMap<ComponentRequirement, RequirementStatus> userSettableRequirements();
+
+    /**
+     * Component requirements that are both settable by the creator and needed to construct the
+     * component.
+     */
+    private Set<ComponentRequirement> neededUserSettableRequirements() {
+      return Sets.intersection(
+          userSettableRequirements().keySet(), componentConstructorRequirements());
+    }
+
+    private void setModifiers() {
+      visibility().ifPresent(classBuilder::addModifiers);
+      if (!componentImplementation.isNested()) {
+        classBuilder.addModifiers(STATIC);
+      }
+      classBuilder.addModifiers(componentImplementation.isAbstract() ? ABSTRACT : FINAL);
+    }
+
+    /** Returns the visibility modifier the generated class should have, if any. */
+    protected abstract Optional<Modifier> visibility();
+
+    /** Sets the superclass being extended or interface being implemented for this creator. */
+    protected abstract void setSupertype();
+
+    /** Adds a constructor for the creator type, if needed. */
+    protected abstract void addConstructor();
+
+    private ImmutableMap<ComponentRequirement, FieldSpec> getOrAddFields() {
+      // If a base implementation is present, any fields are already defined there and don't need to
+      // be created in this implementation.
+      return componentImplementation
+          .baseCreatorImplementation()
+          .map(ComponentCreatorImplementation::fields)
+          .orElseGet(this::addFields);
+    }
+
+    private ImmutableMap<ComponentRequirement, FieldSpec> addFields() {
+      // Fields in an abstract creator class need to be visible from subclasses.
+      Modifier modifier = componentImplementation.isAbstract() ? PROTECTED : PRIVATE;
+      UniqueNameSet fieldNames = new UniqueNameSet();
+      ImmutableMap<ComponentRequirement, FieldSpec> result =
+          Maps.toMap(
+              Sets.intersection(neededUserSettableRequirements(), setterMethods()),
+              requirement ->
+                  FieldSpec.builder(
+                          TypeName.get(requirement.type()),
+                          fieldNames.getUniqueName(requirement.variableName()),
+                          modifier)
+                      .build());
+      classBuilder.addFields(result.values());
+      return result;
+    }
+
+    private void addSetterMethods() {
+      Maps.filterKeys(userSettableRequirements(), setterMethods()::contains)
+          .forEach(
+              (requirement, status) ->
+                  createSetterMethod(requirement, status).ifPresent(classBuilder::addMethod));
+    }
+
+    /** Creates a new setter method builder, with no method body, for the given requirement. */
+    protected abstract MethodSpec.Builder setterMethodBuilder(ComponentRequirement requirement);
+
+    private Optional<MethodSpec> createSetterMethod(
+        ComponentRequirement requirement, RequirementStatus status) {
+      switch (status) {
+        case NEEDED:
+          return Optional.of(normalSetterMethod(requirement));
+        case UNNEEDED:
+          return Optional.of(noopSetterMethod(requirement));
+        case UNSETTABLE_REPEATED_MODULE:
+          return Optional.of(repeatedModuleSetterMethod(requirement));
+        case IMPLEMENTED_IN_SUPERTYPE:
+          return Optional.empty();
+      }
+      throw new AssertionError();
+    }
+
+    private MethodSpec normalSetterMethod(ComponentRequirement requirement) {
+      MethodSpec.Builder method = setterMethodBuilder(requirement);
+      ParameterSpec parameter = parameter(method.build());
+      method.addStatement(
+          "this.$N = $L",
+          fields.get(requirement),
+          requirement.nullPolicy(elements, types).equals(NullPolicy.ALLOW)
+              ? CodeBlock.of("$N", parameter)
+              : CodeBlock.of("$T.checkNotNull($N)", Preconditions.class, parameter));
+      return maybeReturnThis(method);
+    }
+
+    private MethodSpec noopSetterMethod(ComponentRequirement requirement) {
+      MethodSpec.Builder method = setterMethodBuilder(requirement);
+      ParameterSpec parameter = parameter(method.build());
+      method
+          .addAnnotation(Deprecated.class)
+          .addJavadoc(
+              "@deprecated This module is declared, but an instance is not used in the component. "
+                  + "This method is a no-op. For more, see https://dagger.dev/unused-modules.\n")
+          .addStatement("$T.checkNotNull($N)", Preconditions.class, parameter);
+      return maybeReturnThis(method);
+    }
+
+    private MethodSpec repeatedModuleSetterMethod(ComponentRequirement requirement) {
+      return setterMethodBuilder(requirement)
+          .addStatement(
+              "throw new $T($T.format($S, $T.class.getCanonicalName()))",
+              UnsupportedOperationException.class,
+              String.class,
+              "%s cannot be set because it is inherited from the enclosing component",
+              TypeNames.rawTypeName(TypeName.get(requirement.type())))
+          .build();
+    }
+
+    private ParameterSpec parameter(MethodSpec method) {
+      return getOnlyElement(method.parameters);
+    }
+
+    private MethodSpec maybeReturnThis(MethodSpec.Builder method) {
+      MethodSpec built = method.build();
+      return built.returnType.equals(TypeName.VOID)
+          ? built
+          : method.addStatement("return this").build();
+    }
+
+    private void addFactoryMethod() {
+      if (!componentImplementation.isAbstract()) {
+        classBuilder.addMethod(factoryMethod());
+      }
+    }
+
+    MethodSpec factoryMethod() {
+      MethodSpec.Builder factoryMethod = factoryMethodBuilder();
+      factoryMethod
+          .returns(ClassName.get(componentDescriptor().typeElement()))
+          .addModifiers(PUBLIC);
+
+      ImmutableMap<ComponentRequirement, String> factoryMethodParameters =
+          factoryMethodParameters();
+      userSettableRequirements()
+          .keySet()
+          .forEach(
+              requirement -> {
+                if (fields.containsKey(requirement)
+                    && componentConstructorRequirements().contains(requirement)) {
+                  // In AOT mode, there can be a field for a requirement even if the component's
+                  // constructor doesn't need it, because the base class for the creator was created
+                  // before the final graph for the component was known.
+                  FieldSpec field = fields.get(requirement);
+                  addNullHandlingForField(requirement, field, factoryMethod);
+                } else if (factoryMethodParameters.containsKey(requirement)) {
+                  String parameterName = factoryMethodParameters.get(requirement);
+                  addNullHandlingForParameter(requirement, parameterName, factoryMethod);
+                }
+              });
+      factoryMethod.addStatement(
+          "return new $T($L)",
+          componentImplementation.name(),
+          componentConstructorArgs(factoryMethodParameters));
+      return factoryMethod.build();
+    }
+
+    private void addNullHandlingForField(
+        ComponentRequirement requirement, FieldSpec field, MethodSpec.Builder factoryMethod) {
+      switch (requirement.nullPolicy(elements, types)) {
+        case NEW:
+          checkState(requirement.kind().isModule());
+          factoryMethod
+              .beginControlFlow("if ($N == null)", field)
+              .addStatement("this.$N = $L", field, newModuleInstance(requirement))
+              .endControlFlow();
+          break;
+        case THROW:
+          // TODO(cgdecker,ronshapiro): ideally this should use the key instead of a class for
+          // @BindsInstance requirements, but that's not easily proguardable.
+          factoryMethod.addStatement(
+              "$T.checkBuilderRequirement($N, $T.class)",
+              Preconditions.class,
+              field,
+              TypeNames.rawTypeName(field.type));
+          break;
+        case ALLOW:
+          break;
+      }
+    }
+
+    private void addNullHandlingForParameter(
+        ComponentRequirement requirement, String parameter, MethodSpec.Builder factoryMethod) {
+      if (!requirement.nullPolicy(elements, types).equals(NullPolicy.ALLOW)) {
+        // Factory method parameters are always required unless they are a nullable
+        // binds-instance (i.e. ALLOW)
+        factoryMethod.addStatement("$T.checkNotNull($L)", Preconditions.class, parameter);
+      }
+    }
+
+    /** Returns a builder for the creator's factory method. */
+    protected abstract MethodSpec.Builder factoryMethodBuilder();
+
+    private CodeBlock componentConstructorArgs(
+        ImmutableMap<ComponentRequirement, String> factoryMethodParameters) {
+      return componentConstructorRequirements().stream()
+          .map(
+              requirement -> {
+                if (fields.containsKey(requirement)) {
+                  return CodeBlock.of("$N", fields.get(requirement));
+                } else if (factoryMethodParameters.containsKey(requirement)) {
+                  return CodeBlock.of("$L", factoryMethodParameters.get(requirement));
+                } else {
+                  return newModuleInstance(requirement);
+                }
+              })
+          .collect(toParametersCodeBlock());
+    }
+
+    private CodeBlock newModuleInstance(ComponentRequirement requirement) {
+      checkArgument(requirement.kind().isModule()); // this should be guaranteed to be true here
+      return ModuleProxies.newModuleInstance(requirement.typeElement(), className, elements);
+    }
+  }
+
+  /** Builder for a creator type defined by a {@code ComponentCreatorDescriptor}. */
+  private final class BuilderForCreatorDescriptor extends Builder {
+    final ComponentCreatorDescriptor creatorDescriptor;
+    private final Optional<BindingGraph> graph;
+
+    BuilderForCreatorDescriptor(
+        ComponentImplementation componentImplementation,
+        ComponentCreatorDescriptor creatorDescriptor,
+        Optional<BindingGraph> graph) {
+      super(componentImplementation);
+      this.creatorDescriptor = creatorDescriptor;
+      this.graph = graph;
+    }
+
+    @Override
+    protected ImmutableMap<ComponentRequirement, RequirementStatus> userSettableRequirements() {
+      return Maps.toMap(creatorDescriptor.userSettableRequirements(), this::requirementStatus);
+    }
+
+    @Override
+    protected Optional<Modifier> visibility() {
+      if (componentImplementation.isAbstract()) {
+        // The component creator class of a top-level component implementation in ahead-of-time
+        // subcomponents mode must be public, not protected, because the creator's subclass will
+        // be a sibling of the component subclass implementation, not nested.
+        return Optional.of(componentImplementation.isNested() ? PROTECTED : PUBLIC);
+      }
+      return Optional.of(PRIVATE);
+    }
+
+    @Override
+    protected void setSupertype() {
+      if (componentImplementation.baseCreatorImplementation().isPresent()) {
+        // If an abstract base implementation for this creator exists, extend that class.
+        classBuilder.superclass(componentImplementation.baseCreatorImplementation().get().name());
+      } else {
+        addSupertype(classBuilder, creatorDescriptor.typeElement());
+      }
+    }
+
+    @Override
+    protected void addConstructor() {
+      // Just use the implicit no-arg public constructor.
+    }
+
+    @Override
+    protected ImmutableSet<ComponentRequirement> setterMethods() {
+      return ImmutableSet.copyOf(creatorDescriptor.setterMethods().keySet());
+    }
+
+    @Override
+    protected ImmutableMap<ComponentRequirement, String> factoryMethodParameters() {
+      return ImmutableMap.copyOf(
+          Maps.transformValues(
+              creatorDescriptor.factoryParameters(),
+              element -> element.getSimpleName().toString()));
+    }
+
+    private DeclaredType creatorType() {
+      return asDeclared(creatorDescriptor.typeElement().asType());
+    }
+
+    @Override
+    protected MethodSpec.Builder factoryMethodBuilder() {
+      return MethodSpec.overriding(creatorDescriptor.factoryMethod(), creatorType(), types);
+    }
+
+    private RequirementStatus requirementStatus(ComponentRequirement requirement) {
+      // In ahead-of-time subcomponents mode, all builder methods are defined at the base
+      // implementation. The only case where a method needs to be overridden is for a repeated
+      // module, which is unknown at the point when a base implementation is generated. We do this
+      // at the root for simplicity (and as an aside, repeated modules are never used in google
+      // as of 11/28/18, and thus the additional cost of including these methods at the root is
+      // negligible).
+      if (isRepeatedModule(requirement)) {
+        return RequirementStatus.UNSETTABLE_REPEATED_MODULE;
+      }
+
+      if (hasBaseCreatorImplementation()) {
+        return RequirementStatus.IMPLEMENTED_IN_SUPERTYPE;
+      }
+
+      return componentConstructorRequirements().contains(requirement)
+          ? RequirementStatus.NEEDED
+          : RequirementStatus.UNNEEDED;
+    }
+
+    /**
+     * Returns whether the given requirement is for a repeat of a module inherited from an ancestor
+     * component. This creator is not allowed to set such a module.
+     */
+    final boolean isRepeatedModule(ComponentRequirement requirement) {
+      return !componentConstructorRequirements().contains(requirement)
+          && !isOwnedModule(requirement);
+    }
+
+    /**
+     * Returns whether the given {@code requirement} is for a module type owned by the component.
+     */
+    private boolean isOwnedModule(ComponentRequirement requirement) {
+      return graph.map(g -> g.ownedModuleTypes().contains(requirement.typeElement())).orElse(true);
+    }
+
+    private boolean hasBaseCreatorImplementation() {
+      return !componentImplementation.isAbstract()
+          && componentImplementation.baseImplementation().isPresent();
+    }
+
+    @Override
+    protected MethodSpec.Builder setterMethodBuilder(ComponentRequirement requirement) {
+      ExecutableElement supertypeMethod = creatorDescriptor.setterMethods().get(requirement);
+      MethodSpec.Builder method = MethodSpec.overriding(supertypeMethod, creatorType(), types);
+      if (!supertypeMethod.getReturnType().getKind().equals(TypeKind.VOID)) {
+        // Take advantage of covariant returns so that we don't have to worry about type variables
+        method.returns(className);
+      }
+      return method;
+    }
+  }
+
+  /**
+   * Builder for a component builder class that is automatically generated for a root component that
+   * does not have its own user-defined creator type (i.e. a {@code ComponentCreatorDescriptor}).
+   */
+  private final class BuilderForGeneratedRootComponentBuilder extends Builder {
+    BuilderForGeneratedRootComponentBuilder(ComponentImplementation componentImplementation) {
+      super(componentImplementation);
+    }
+
+    @Override
+    protected ImmutableMap<ComponentRequirement, RequirementStatus> userSettableRequirements() {
+      return Maps.toMap(
+          setterMethods(),
+          requirement ->
+              componentConstructorRequirements().contains(requirement)
+                  ? RequirementStatus.NEEDED
+                  : RequirementStatus.UNNEEDED);
+    }
+
+    @Override
+    protected Optional<Modifier> visibility() {
+      return componentImplementation
+          .componentDescriptor()
+          .typeElement()
+          .getModifiers()
+          .contains(PUBLIC) ? Optional.of(PUBLIC) : Optional.empty();
+    }
+
+    @Override
+    protected void setSupertype() {
+      // There's never a supertype for a root component auto-generated builder type.
+    }
+
+    @Override
+    protected void addConstructor() {
+      classBuilder.addMethod(constructorBuilder().addModifiers(PRIVATE).build());
+    }
+
+    @Override
+    protected ImmutableSet<ComponentRequirement> setterMethods() {
+      return componentDescriptor().dependenciesAndConcreteModules();
+    }
+
+    @Override
+    protected ImmutableMap<ComponentRequirement, String> factoryMethodParameters() {
+      return ImmutableMap.of();
+    }
+
+    @Override
+    protected MethodSpec.Builder factoryMethodBuilder() {
+      return methodBuilder("build");
+    }
+
+    @Override
+    protected MethodSpec.Builder setterMethodBuilder(ComponentRequirement requirement) {
+      String name = simpleVariableName(requirement.typeElement());
+      return methodBuilder(name)
+          .addModifiers(PUBLIC)
+          .addParameter(TypeName.get(requirement.type()), name)
+          .returns(className);
+    }
+  }
+
+  /** Enumeration of statuses a component requirement may have in a creator. */
+  enum RequirementStatus {
+    /** An instance is needed to create the component. */
+    NEEDED,
+
+    /**
+     * An instance is not needed to create the component, but the requirement is for a module owned
+     * by the component. Setting the requirement is a no-op and any setter method should be marked
+     * deprecated on the generated type as a warning to the user.
+     */
+    UNNEEDED,
+
+    /**
+     * The requirement may not be set in this creator because the module it is for is already
+     * inherited from an ancestor component. Any setter method for it should throw an exception.
+     */
+    UNSETTABLE_REPEATED_MODULE,
+
+    /**
+     * The requirement is settable by the creator, but the setter method implementation already
+     * exists in a supertype.
+     */
+    IMPLEMENTED_IN_SUPERTYPE,
+    ;
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentCreatorKind.java b/java/dagger/internal/codegen/ComponentCreatorKind.java
new file mode 100644
index 0000000..dc203de
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentCreatorKind.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 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.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+
+import com.google.common.base.Ascii;
+
+/** Enumeration of the different kinds of component creators. */
+enum ComponentCreatorKind {
+  /** {@code @Component.Builder} or one of its subcomponent/production variants. */
+  BUILDER,
+
+  /** {@code @Component.Factory} or one of its subcomponent/production variants. */
+  FACTORY,
+  ;
+
+  /** Name to use as (or as part of) a type name for a creator of this kind. */
+  String typeName() {
+    return UPPER_UNDERSCORE.to(UPPER_CAMEL, name());
+  }
+
+  /** Name to use for a component's static method returning a creator of this kind. */
+  String methodName() {
+    return Ascii.toLowerCase(name());
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentCreatorValidator.java b/java/dagger/internal/codegen/ComponentCreatorValidator.java
new file mode 100644
index 0000000..c55dadd
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentCreatorValidator.java
@@ -0,0 +1,390 @@
+/*
+ * 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.MoreElements.isAnnotationPresent;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.getCreatorAnnotations;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ObjectArrays;
+import dagger.BindsInstance;
+import dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.List;
+import java.util.Set;
+import javax.inject.Inject;
+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.element.VariableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+
+/** Validates types annotated with component creator annotations. */
+final class ComponentCreatorValidator {
+
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+
+  @Inject
+  ComponentCreatorValidator(DaggerElements elements, DaggerTypes types) {
+    this.elements = elements;
+    this.types = types;
+  }
+
+  /** Validates that the given {@code type} is potentially a valid component creator type. */
+  public ValidationReport<TypeElement> validate(TypeElement type) {
+    ValidationReport.Builder<TypeElement> report = ValidationReport.about(type);
+
+    ImmutableSet<ComponentCreatorAnnotation> creatorAnnotations = getCreatorAnnotations(type);
+    if (!validateOnlyOneCreatorAnnotation(creatorAnnotations, report)) {
+      return report.build();
+    }
+
+    // Note: there's more validation in ComponentDescriptorValidator:
+    // - to make sure the setter methods/factory parameters mirror the deps
+    // - to make sure each type or key is set by only one method or parameter
+    ElementValidator validator =
+        new ElementValidator(type, report, getOnlyElement(creatorAnnotations));
+    return validator.validate();
+  }
+
+  private boolean validateOnlyOneCreatorAnnotation(
+      ImmutableSet<ComponentCreatorAnnotation> creatorAnnotations,
+      ValidationReport.Builder<?> report) {
+    // creatorAnnotations should never be empty because this should only ever be called for
+    // types that have been found to have some creator annotation
+    if (creatorAnnotations.size() > 1) {
+      String error =
+          "May not have more than one component Factory or Builder annotation on a type"
+              + ": found "
+              + creatorAnnotations;
+      report.addError(error);
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Validator for a single {@link TypeElement} that is annotated with a {@code Builder} or {@code
+   * Factory} annotation.
+   */
+  private final class ElementValidator {
+    private final TypeElement type;
+    private final Element component;
+    private final ValidationReport.Builder<TypeElement> report;
+    private final ComponentCreatorAnnotation annotation;
+    private final ComponentCreatorMessages messages;
+
+    private ElementValidator(
+        TypeElement type,
+        ValidationReport.Builder<TypeElement> report,
+        ComponentCreatorAnnotation annotation) {
+      this.type = type;
+      this.component = type.getEnclosingElement();
+      this.report = report;
+      this.annotation = annotation;
+      this.messages = ErrorMessages.creatorMessagesFor(annotation);
+    }
+
+    /** Validates the creator type. */
+    final ValidationReport<TypeElement> validate() {
+      if (!isAnnotationPresent(component, annotation.componentAnnotation())) {
+        report.addError(messages.mustBeInComponent());
+      }
+
+      // If the type isn't a class or interface, don't validate anything else since the rest of the
+      // messages will be bogus.
+      if (!validateIsClassOrInterface()) {
+        return report.build();
+      }
+
+      validateTypeRequirements();
+      switch (annotation.creatorKind()) {
+        case FACTORY:
+          validateFactory();
+          break;
+        case BUILDER:
+          validateBuilder();
+      }
+
+      return report.build();
+    }
+
+    /** Validates that the type is a class or interface type and returns true if it is. */
+    private boolean validateIsClassOrInterface() {
+      switch (type.getKind()) {
+        case CLASS:
+          validateConstructor();
+          return true;
+        case INTERFACE:
+          return true;
+        default:
+          report.addError(messages.mustBeClassOrInterface());
+      }
+      return false;
+    }
+
+    private void validateConstructor() {
+      List<? extends Element> allElements = type.getEnclosedElements();
+      List<ExecutableElement> constructors = ElementFilter.constructorsIn(allElements);
+
+      boolean valid = true;
+      if (constructors.size() != 1) {
+        valid = false;
+      } else {
+        ExecutableElement constructor = getOnlyElement(constructors);
+        valid =
+            constructor.getParameters().isEmpty() && !constructor.getModifiers().contains(PRIVATE);
+      }
+
+      if (!valid) {
+        report.addError(messages.invalidConstructor());
+      }
+    }
+
+    /** Validates basic requirements about the type that are common to both creator kinds. */
+    private void validateTypeRequirements() {
+      if (!type.getTypeParameters().isEmpty()) {
+        report.addError(messages.generics());
+      }
+
+      Set<Modifier> modifiers = type.getModifiers();
+      if (modifiers.contains(PRIVATE)) {
+        report.addError(messages.isPrivate());
+      }
+      if (!modifiers.contains(STATIC)) {
+        report.addError(messages.mustBeStatic());
+      }
+      // Note: Must be abstract, so no need to check for final.
+      if (!modifiers.contains(ABSTRACT)) {
+        report.addError(messages.mustBeAbstract());
+      }
+    }
+
+    private void validateBuilder() {
+      ExecutableElement buildMethod = null;
+      for (ExecutableElement method : elements.getUnimplementedMethods(type)) {
+        switch (method.getParameters().size()) {
+          case 0: // If this is potentially a build() method, validate it returns the correct type.
+            if (validateFactoryMethodReturnType(method)) {
+              if (buildMethod != null) {
+                // If we found more than one build-like method, fail.
+                error(
+                    method,
+                    messages.twoFactoryMethods(),
+                    messages.inheritedTwoFactoryMethods(),
+                    buildMethod);
+              }
+            }
+            // We set the buildMethod regardless of the return type to reduce error spam.
+            buildMethod = method;
+            break;
+
+          case 1: // If this correctly had one parameter, make sure the return types are valid.
+            validateSetterMethod(method);
+            break;
+
+          default: // more than one parameter
+            error(
+                method,
+                messages.setterMethodsMustTakeOneArg(),
+                messages.inheritedSetterMethodsMustTakeOneArg());
+            break;
+        }
+      }
+
+      if (buildMethod == null) {
+        report.addError(messages.missingFactoryMethod());
+      } else {
+        validateNotGeneric(buildMethod);
+      }
+    }
+
+    private void validateSetterMethod(ExecutableElement method) {
+      TypeMirror returnType = types.resolveExecutableType(method, type.asType()).getReturnType();
+      if (returnType.getKind() != TypeKind.VOID && !types.isSubtype(type.asType(), returnType)) {
+        error(
+            method,
+            messages.setterMethodsMustReturnVoidOrBuilder(),
+            messages.inheritedSetterMethodsMustReturnVoidOrBuilder());
+      }
+
+      validateNotGeneric(method);
+
+      VariableElement parameter = method.getParameters().get(0);
+
+      boolean methodIsBindsInstance = isAnnotationPresent(method, BindsInstance.class);
+      boolean parameterIsBindsInstance = isAnnotationPresent(parameter, BindsInstance.class);
+      boolean bindsInstance = methodIsBindsInstance || parameterIsBindsInstance;
+
+      if (methodIsBindsInstance && parameterIsBindsInstance) {
+        error(
+            method,
+            messages.bindsInstanceNotAllowedOnBothSetterMethodAndParameter(),
+            messages.inheritedBindsInstanceNotAllowedOnBothSetterMethodAndParameter());
+      }
+
+      if (!bindsInstance && parameter.asType().getKind().isPrimitive()) {
+        error(
+            method,
+            messages.nonBindsInstanceParametersMayNotBePrimitives(),
+            messages.inheritedNonBindsInstanceParametersMayNotBePrimitives());
+      }
+    }
+
+    private void validateFactory() {
+      ImmutableList<ExecutableElement> abstractMethods =
+          elements.getUnimplementedMethods(type).asList();
+      switch (abstractMethods.size()) {
+        case 0:
+          report.addError(messages.missingFactoryMethod());
+          return;
+        case 1:
+          break; // good
+        default:
+          error(
+              abstractMethods.get(1),
+              messages.twoFactoryMethods(),
+              messages.inheritedTwoFactoryMethods(),
+              abstractMethods.get(0));
+          return;
+      }
+
+      validateFactoryMethod(getOnlyElement(abstractMethods));
+    }
+
+    /** Validates that the given {@code method} is a valid component factory method. */
+    private void validateFactoryMethod(ExecutableElement method) {
+      validateNotGeneric(method);
+
+      if (!validateFactoryMethodReturnType(method)) {
+        // If we can't determine that the single method is a valid factory method, don't bother
+        // validating its parameters.
+        return;
+      }
+
+      for (VariableElement parameter : method.getParameters()) {
+        if (!isAnnotationPresent(parameter, BindsInstance.class)
+            && parameter.asType().getKind().isPrimitive()) {
+          error(
+              method,
+              messages.nonBindsInstanceParametersMayNotBePrimitives(),
+              messages.inheritedNonBindsInstanceParametersMayNotBePrimitives());
+        }
+      }
+    }
+
+    /**
+     * Validates that the factory method that actually returns a new component instance. Returns
+     * true if the return type was valid.
+     */
+    private boolean validateFactoryMethodReturnType(ExecutableElement method) {
+      TypeMirror returnType = types.resolveExecutableType(method, type.asType()).getReturnType();
+
+      if (!types.isSubtype(component.asType(), returnType)) {
+        error(
+            method,
+            messages.factoryMethodMustReturnComponentType(),
+            messages.inheritedFactoryMethodMustReturnComponentType());
+        return false;
+      }
+
+      if (isAnnotationPresent(method, BindsInstance.class)) {
+        error(
+            method,
+            messages.factoryMethodMayNotBeAnnotatedWithBindsInstance(),
+            messages.inheritedFactoryMethodMayNotBeAnnotatedWithBindsInstance());
+        return false;
+      }
+
+      TypeElement componentType = MoreElements.asType(component);
+      if (!types.isSameType(componentType.asType(), returnType)) {
+        ImmutableSet<ExecutableElement> methodsOnlyInComponent =
+            methodsOnlyInComponent(componentType);
+        if (!methodsOnlyInComponent.isEmpty()) {
+          report.addWarning(
+              messages.factoryMethodReturnsSupertypeWithMissingMethods(
+                  componentType, type, returnType, method, methodsOnlyInComponent),
+              method);
+        }
+      }
+      return true;
+    }
+
+    /**
+     * Generates one of two error messages. If the method is enclosed in the subject, we target the
+     * error to the method itself. Otherwise we target the error to the subject and list the method
+     * as an argument. (Otherwise we have no way of knowing if the method is being compiled in this
+     * pass too, so javac might not be able to pinpoint it's line of code.)
+     */
+    /*
+     * For Component.Builder, the prototypical example would be if someone had:
+     *    libfoo: interface SharedBuilder { void badSetter(A a, B b); }
+     *    libbar: BarComponent { BarBuilder extends SharedBuilder } }
+     * ... the compiler only validates BarBuilder when compiling libbar, but it fails because
+     * of libfoo's SharedBuilder (which could have been compiled in a previous pass).
+     * So we can't point to SharedBuilder#badSetter as the subject of the BarBuilder validation
+     * failure.
+     *
+     * This check is a little more strict than necessary -- ideally we'd check if method's enclosing
+     * class was included in this compile run.  But that's hard, and this is close enough.
+     */
+    private void error(
+        ExecutableElement method,
+        String enclosedError,
+        String inheritedError,
+        Object... extraArgs) {
+      if (method.getEnclosingElement().equals(type)) {
+        report.addError(String.format(enclosedError, extraArgs), method);
+      } else {
+        report.addError(String.format(inheritedError, ObjectArrays.concat(extraArgs, method)));
+      }
+    }
+
+    /** Validates that the given {@code method} is not generic. * */
+    private void validateNotGeneric(ExecutableElement method) {
+      if (!method.getTypeParameters().isEmpty()) {
+        error(
+            method,
+            messages.methodsMayNotHaveTypeParameters(),
+            messages.inheritedMethodsMayNotHaveTypeParameters());
+      }
+    }
+
+    /**
+     * Returns all methods defind in {@code componentType} which are not inherited from a supertype.
+     */
+    private ImmutableSet<ExecutableElement> methodsOnlyInComponent(TypeElement componentType) {
+      // TODO(ronshapiro): Ideally this shouldn't return methods which are redeclared from a
+      // supertype, but do not change the return type. We don't have a good/simple way of checking
+      // that, and it doesn't seem likely, so the warning won't be too bad.
+      return ImmutableSet.copyOf(methodsIn(componentType.getEnclosedElements()));
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentDescriptor.java b/java/dagger/internal/codegen/ComponentDescriptor.java
new file mode 100644
index 0000000..769cc4c
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentDescriptor.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.DaggerStreams.toImmutableMap;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.type.TypeKind.VOID;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.errorprone.annotations.CheckReturnValue;
+import dagger.Component;
+import dagger.Module;
+import dagger.Subcomponent;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import dagger.model.Scope;
+import dagger.producers.CancellationPolicy;
+import dagger.producers.ProductionComponent;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Stream;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A component declaration.
+ *
+ * <p>Represents one type annotated with {@code @Component}, {@code Subcomponent},
+ * {@code @ProductionComponent}, or {@code @ProductionSubcomponent}.
+ *
+ * <p>When validating bindings installed in modules, a {@link ComponentDescriptor} can also
+ * represent a synthetic component for the module, where there is an entry point for each binding in
+ * the module.
+ */
+@AutoValue
+abstract class ComponentDescriptor {
+  /** The annotation that specifies that {@link #typeElement()} is a component. */
+  abstract ComponentAnnotation annotation();
+
+  /** Returns {@code true} if this is a subcomponent. */
+  final boolean isSubcomponent() {
+    return annotation().isSubcomponent();
+  }
+
+  /**
+   * Returns {@code true} if this is a production component or subcomponent, or a
+   * {@code @ProducerModule} when doing module binding validation.
+   */
+  final boolean isProduction() {
+    return annotation().isProduction();
+  }
+
+  /**
+   * Returns {@code true} if this is a real component, and not a fictional one used to validate
+   * module bindings.
+   */
+  final boolean isRealComponent() {
+    return annotation().isRealComponent();
+  }
+
+  /**
+   * The element that defines the component. This is the element to which the {@link #annotation()}
+   * was applied.
+   */
+  abstract TypeElement typeElement();
+
+  /**
+   * The set of component dependencies listed in {@link Component#dependencies} or {@link
+   * ProductionComponent#dependencies()}.
+   */
+  abstract ImmutableSet<ComponentRequirement> dependencies();
+
+  /** The non-abstract {@link #modules()} and the {@link #dependencies()}. */
+  final ImmutableSet<ComponentRequirement> dependenciesAndConcreteModules() {
+    return Stream.concat(
+            moduleTypes().stream()
+                .filter(dep -> !dep.getModifiers().contains(ABSTRACT))
+                .map(module -> ComponentRequirement.forModule(module.asType())),
+            dependencies().stream())
+        .collect(toImmutableSet());
+  }
+
+  /**
+   * The {@link ModuleDescriptor modules} declared in {@link Component#modules()} and reachable by
+   * traversing {@link Module#includes()}.
+   */
+  abstract ImmutableSet<ModuleDescriptor> modules();
+
+  /** The types of the {@link #modules()}. */
+  final ImmutableSet<TypeElement> moduleTypes() {
+    return modules().stream().map(ModuleDescriptor::moduleElement).collect(toImmutableSet());
+  }
+
+  /**
+   * The types for which the component will need instances if all of its bindings are used. For the
+   * types the component will need in a given binding graph, use {@link
+   * BindingGraph#componentRequirements()}.
+   *
+   * <ul>
+   *   <li>{@linkplain #modules()} modules} with concrete instance bindings
+   *   <li>Bound instances
+   *   <li>{@linkplain #dependencies() dependencies}
+   * </ul>
+   */
+  @Memoized
+  ImmutableSet<ComponentRequirement> requirements() {
+    ImmutableSet.Builder<ComponentRequirement> requirements = ImmutableSet.builder();
+    modules().stream()
+        .filter(
+            module ->
+                module.bindings().stream().anyMatch(ContributionBinding::requiresModuleInstance))
+        .map(module -> ComponentRequirement.forModule(module.moduleElement().asType()))
+        .forEach(requirements::add);
+    requirements.addAll(dependencies());
+    requirements.addAll(
+        creatorDescriptor()
+            .map(ComponentCreatorDescriptor::boundInstanceRequirements)
+            .orElse(ImmutableSet.of()));
+    return requirements.build();
+  }
+
+  /**
+   * This component's {@linkplain #dependencies() dependencies} keyed by each provision or
+   * production method defined by that dependency. Note that the dependencies' types are not simply
+   * the enclosing type of the method; a method may be declared by a supertype of the actual
+   * dependency.
+   */
+  abstract ImmutableMap<ExecutableElement, ComponentRequirement> dependenciesByDependencyMethod();
+
+  /** The {@linkplain #dependencies() component dependency} that defines a method. */
+  final ComponentRequirement getDependencyThatDefinesMethod(Element method) {
+    checkArgument(
+        method instanceof ExecutableElement, "method must be an executable element: %s", method);
+    return checkNotNull(
+        dependenciesByDependencyMethod().get(method), "no dependency implements %s", method);
+  }
+
+  /**
+   * The scopes of the component.
+   */
+  abstract ImmutableSet<Scope> scopes();
+
+  /**
+   * All {@link Subcomponent}s which are direct children of this component. This includes
+   * subcomponents installed from {@link Module#subcomponents()} as well as subcomponent {@linkplain
+   * #childComponentsDeclaredByFactoryMethods() factory methods} and {@linkplain
+   * #childComponentsDeclaredByBuilderEntryPoints() builder methods}.
+   */
+  final ImmutableSet<ComponentDescriptor> childComponents() {
+    return ImmutableSet.<ComponentDescriptor>builder()
+        .addAll(childComponentsDeclaredByFactoryMethods().values())
+        .addAll(childComponentsDeclaredByBuilderEntryPoints().values())
+        .addAll(childComponentsDeclaredByModules())
+        .build();
+  }
+
+  /**
+   * All {@linkplain Subcomponent direct child} components that are declared by a {@linkplain
+   * Module#subcomponents() module's subcomponents}.
+   */
+  abstract ImmutableSet<ComponentDescriptor> childComponentsDeclaredByModules();
+
+  /**
+   * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
+   * factory method.
+   */
+  abstract ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor>
+      childComponentsDeclaredByFactoryMethods();
+
+  /** Returns a map of {@link #childComponents()} indexed by {@link #typeElement()}. */
+  @Memoized
+  ImmutableMap<TypeElement, ComponentDescriptor> childComponentsByElement() {
+    return Maps.uniqueIndex(childComponents(), ComponentDescriptor::typeElement);
+  }
+
+  /** Returns the factory method that declares a child component. */
+  final Optional<ComponentMethodDescriptor> getFactoryMethodForChildComponent(
+      ComponentDescriptor childComponent) {
+    return Optional.ofNullable(
+        childComponentsDeclaredByFactoryMethods().inverse().get(childComponent));
+  }
+
+  /**
+   * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
+   * builder method.
+   */
+  abstract ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor>
+      childComponentsDeclaredByBuilderEntryPoints();
+
+  private final Supplier<ImmutableMap<TypeElement, ComponentDescriptor>>
+      childComponentsByBuilderType =
+          Suppliers.memoize(
+              () ->
+                  childComponents().stream()
+                      .filter(child -> child.creatorDescriptor().isPresent())
+                      .collect(
+                          toImmutableMap(
+                              child -> child.creatorDescriptor().get().typeElement(),
+                              child -> child)));
+
+  /** Returns the child component with the given builder type. */
+  final ComponentDescriptor getChildComponentWithBuilderType(TypeElement builderType) {
+    return checkNotNull(
+        childComponentsByBuilderType.get().get(builderType),
+        "no child component found for builder type %s",
+        builderType.getQualifiedName());
+  }
+
+  abstract ImmutableSet<ComponentMethodDescriptor> componentMethods();
+
+  /** Returns the first component method associated with this binding request, if one exists. */
+  Optional<ComponentMethodDescriptor> firstMatchingComponentMethod(BindingRequest request) {
+    return componentMethods().stream()
+        .filter(method -> doesComponentMethodMatch(method, request))
+        .findFirst();
+  }
+
+  /** Returns true if the component method matches the binding request. */
+  private static boolean doesComponentMethodMatch(
+      ComponentMethodDescriptor componentMethod, BindingRequest request) {
+    return componentMethod
+        .dependencyRequest()
+        .map(BindingRequest::bindingRequest)
+        .filter(request::equals)
+        .isPresent();
+  }
+
+  /** The entry point methods on the component type. Each has a {@link DependencyRequest}. */
+  final ImmutableSet<ComponentMethodDescriptor> entryPointMethods() {
+    return componentMethods()
+        .stream()
+        .filter(method -> method.dependencyRequest().isPresent())
+        .collect(toImmutableSet());
+  }
+
+  // TODO(gak): Consider making this non-optional and revising the
+  // interaction between the spec & generation
+  /** Returns a descriptor for the creator type for this component type, if the user defined one. */
+  abstract Optional<ComponentCreatorDescriptor> creatorDescriptor();
+
+  /**
+   * Returns {@code true} for components that have a creator, either because the user {@linkplain
+   * #creatorDescriptor() specified one} or because it's a top-level component with an implicit
+   * builder.
+   */
+  final boolean hasCreator() {
+    return !isSubcomponent() || creatorDescriptor().isPresent();
+  }
+
+  /**
+   * Returns the {@link CancellationPolicy} for this component, or an empty optional if either the
+   * component is not a production component or no {@code CancellationPolicy} annotation is present.
+   */
+  final Optional<CancellationPolicy> cancellationPolicy() {
+    return isProduction()
+        ? Optional.ofNullable(typeElement().getAnnotation(CancellationPolicy.class))
+        : Optional.empty();
+  }
+
+  @Memoized
+  @Override
+  public int hashCode() {
+    // TODO(b/122962745): Only use typeElement().hashCode()
+    return Objects.hash(typeElement(), annotation());
+  }
+
+  // TODO(ronshapiro): simplify the equality semantics
+  @Override
+  public abstract boolean equals(Object obj);
+
+  /** A component method. */
+  @AutoValue
+  abstract static class ComponentMethodDescriptor {
+    /** The method itself. Note that this may be declared on a supertype of the component. */
+    abstract ExecutableElement methodElement();
+
+    /**
+     * The dependency request for production, provision, and subcomponent creator methods. Absent
+     * for subcomponent factory methods.
+     */
+    abstract Optional<DependencyRequest> dependencyRequest();
+
+    /** The subcomponent for subcomponent factory methods and subcomponent creator methods. */
+    abstract Optional<ComponentDescriptor> subcomponent();
+
+    /**
+     * Returns the return type of {@link #methodElement()} as resolved in the {@link
+     * ComponentDescriptor#typeElement() component type}. If there are no type variables in the
+     * return type, this is the equivalent of {@code methodElement().getReturnType()}.
+     */
+    TypeMirror resolvedReturnType(DaggerTypes types) {
+      checkState(dependencyRequest().isPresent());
+
+      TypeMirror returnType = methodElement().getReturnType();
+      if (returnType.getKind().isPrimitive() || returnType.getKind().equals(VOID)) {
+        return returnType;
+      }
+      return BindingRequest.bindingRequest(dependencyRequest().get())
+          .requestedType(dependencyRequest().get().key().type(), types);
+    }
+
+    /** A {@link ComponentMethodDescriptor}builder for a method. */
+    static Builder builder(ExecutableElement method) {
+      return new AutoValue_ComponentDescriptor_ComponentMethodDescriptor.Builder()
+          .methodElement(method);
+    }
+
+    /** A builder of {@link ComponentMethodDescriptor}s. */
+    @AutoValue.Builder
+    @CanIgnoreReturnValue
+    interface Builder {
+      /** @see ComponentMethodDescriptor#methodElement() */
+      Builder methodElement(ExecutableElement methodElement);
+
+      /** @see ComponentMethodDescriptor#dependencyRequest() */
+      Builder dependencyRequest(DependencyRequest dependencyRequest);
+
+      /** @see ComponentMethodDescriptor#subcomponent() */
+      Builder subcomponent(ComponentDescriptor subcomponent);
+
+      /** Builds the descriptor. */
+      @CheckReturnValue
+      ComponentMethodDescriptor build();
+    }
+  }
+
+  /** No-argument methods defined on {@link Object} that are ignored for contribution. */
+  private static final ImmutableSet<String> NON_CONTRIBUTING_OBJECT_METHOD_NAMES =
+      ImmutableSet.of("toString", "hashCode", "clone", "getClass");
+
+  /**
+   * Returns {@code true} if a method could be a component entry point but not a members-injection
+   * method.
+   */
+  static boolean isComponentContributionMethod(DaggerElements elements, ExecutableElement method) {
+    return method.getParameters().isEmpty()
+        && !method.getReturnType().getKind().equals(VOID)
+        && !elements.getTypeElement(Object.class).equals(method.getEnclosingElement())
+        && !NON_CONTRIBUTING_OBJECT_METHOD_NAMES.contains(method.getSimpleName().toString());
+  }
+
+  /** Returns {@code true} if a method could be a component production entry point. */
+  static boolean isComponentProductionMethod(DaggerElements elements, ExecutableElement method) {
+    return isComponentContributionMethod(elements, method) && isFutureType(method.getReturnType());
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentDescriptorFactory.java b/java/dagger/internal/codegen/ComponentDescriptorFactory.java
new file mode 100644
index 0000000..7d87eac
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentDescriptorFactory.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2014 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.MoreElements.asType;
+import static com.google.auto.common.MoreTypes.asTypeElement;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.ComponentAnnotation.subcomponentAnnotation;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.creatorAnnotationsFor;
+import static dagger.internal.codegen.ComponentDescriptor.isComponentContributionMethod;
+import static dagger.internal.codegen.ConfigurationAnnotations.enclosedAnnotatedTypes;
+import static dagger.internal.codegen.ConfigurationAnnotations.isSubcomponentCreator;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifier;
+import static dagger.internal.codegen.Scopes.productionScope;
+import static dagger.internal.codegen.Scopes.scopesOf;
+import static javax.lang.model.type.TypeKind.DECLARED;
+import static javax.lang.model.type.TypeKind.VOID;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Scope;
+import java.util.Optional;
+import java.util.function.Function;
+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;
+import javax.lang.model.type.TypeMirror;
+
+/** A factory for {@link ComponentDescriptor}s. */
+final class ComponentDescriptorFactory {
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+  private final DependencyRequestFactory dependencyRequestFactory;
+  private final ModuleDescriptor.Factory moduleDescriptorFactory;
+
+  @Inject
+  ComponentDescriptorFactory(
+      DaggerElements elements,
+      DaggerTypes types,
+      DependencyRequestFactory dependencyRequestFactory,
+      ModuleDescriptor.Factory moduleDescriptorFactory) {
+    this.elements = elements;
+    this.types = types;
+    this.dependencyRequestFactory = dependencyRequestFactory;
+    this.moduleDescriptorFactory = moduleDescriptorFactory;
+  }
+
+  /** Returns a descriptor for a root component type. */
+  ComponentDescriptor rootComponentDescriptor(TypeElement typeElement) {
+    return create(
+        typeElement,
+        checkAnnotation(
+            typeElement,
+            ComponentAnnotation::rootComponentAnnotation,
+            "must have a component annotation"));
+  }
+
+  /** Returns a descriptor for a subcomponent type. */
+  ComponentDescriptor subcomponentDescriptor(TypeElement typeElement) {
+    return create(
+        typeElement,
+        checkAnnotation(
+            typeElement,
+            ComponentAnnotation::subcomponentAnnotation,
+            "must have a subcomponent annotation"));
+  }
+
+  /**
+   * Returns a descriptor for a fictional component based on a module type in order to validate its
+   * bindings.
+   */
+  ComponentDescriptor moduleComponentDescriptor(TypeElement typeElement) {
+    return create(
+        typeElement,
+        ComponentAnnotation.fromModuleAnnotation(
+            checkAnnotation(
+                typeElement, ModuleAnnotation::moduleAnnotation, "must have a module annotation")));
+  }
+
+  private static <A> A checkAnnotation(
+      TypeElement typeElement,
+      Function<TypeElement, Optional<A>> annotationFunction,
+      String message) {
+    return annotationFunction
+        .apply(typeElement)
+        .orElseThrow(() -> new IllegalArgumentException(typeElement + " " + message));
+  }
+
+  private ComponentDescriptor create(
+      TypeElement typeElement, ComponentAnnotation componentAnnotation) {
+    ImmutableSet<ComponentRequirement> componentDependencies =
+        componentAnnotation.dependencyTypes().stream()
+            .map(ComponentRequirement::forDependency)
+            .collect(toImmutableSet());
+
+    ImmutableMap.Builder<ExecutableElement, ComponentRequirement> dependenciesByDependencyMethod =
+        ImmutableMap.builder();
+
+    for (ComponentRequirement componentDependency : componentDependencies) {
+      for (ExecutableElement dependencyMethod :
+          methodsIn(elements.getAllMembers(componentDependency.typeElement()))) {
+        if (isComponentContributionMethod(elements, dependencyMethod)) {
+          dependenciesByDependencyMethod.put(dependencyMethod, componentDependency);
+        }
+      }
+    }
+
+    // Start with the component's modules. For fictional components built from a module, start with
+    // that module.
+    ImmutableSet<TypeElement> modules =
+        componentAnnotation.isRealComponent()
+            ? componentAnnotation.modules()
+            : ImmutableSet.of(typeElement);
+
+    ImmutableSet<ModuleDescriptor> transitiveModules =
+        moduleDescriptorFactory.transitiveModules(modules);
+
+    ImmutableSet.Builder<ComponentDescriptor> subcomponentsFromModules = ImmutableSet.builder();
+    for (ModuleDescriptor module : transitiveModules) {
+      for (SubcomponentDeclaration subcomponentDeclaration : module.subcomponentDeclarations()) {
+        TypeElement subcomponent = subcomponentDeclaration.subcomponentType();
+        subcomponentsFromModules.add(subcomponentDescriptor(subcomponent));
+      }
+    }
+
+    ImmutableSet.Builder<ComponentMethodDescriptor> componentMethodsBuilder =
+        ImmutableSet.builder();
+    ImmutableBiMap.Builder<ComponentMethodDescriptor, ComponentDescriptor>
+        subcomponentsByFactoryMethod = ImmutableBiMap.builder();
+    ImmutableBiMap.Builder<ComponentMethodDescriptor, ComponentDescriptor>
+        subcomponentsByBuilderMethod = ImmutableBiMap.builder();
+    if (componentAnnotation.isRealComponent()) {
+      ImmutableSet<ExecutableElement> unimplementedMethods =
+          elements.getUnimplementedMethods(typeElement);
+      for (ExecutableElement componentMethod : unimplementedMethods) {
+        ComponentMethodDescriptor componentMethodDescriptor =
+            getDescriptorForComponentMethod(typeElement, componentAnnotation, componentMethod);
+        componentMethodsBuilder.add(componentMethodDescriptor);
+        componentMethodDescriptor
+            .subcomponent()
+            .ifPresent(
+                subcomponent -> {
+                  // If the dependency request is present, that means the method returns the
+                  // subcomponent factory.
+                  if (componentMethodDescriptor.dependencyRequest().isPresent()) {
+                    subcomponentsByBuilderMethod.put(componentMethodDescriptor, subcomponent);
+                  } else {
+                    subcomponentsByFactoryMethod.put(componentMethodDescriptor, subcomponent);
+                  }
+                });
+      }
+    }
+
+    // Validation should have ensured that this set will have at most one element.
+    ImmutableSet<DeclaredType> enclosedCreators =
+        creatorAnnotationsFor(componentAnnotation).stream()
+            .flatMap(
+                creatorAnnotation ->
+                    enclosedAnnotatedTypes(typeElement, creatorAnnotation).stream())
+            .collect(toImmutableSet());
+    Optional<ComponentCreatorDescriptor> creatorDescriptor =
+        enclosedCreators.isEmpty()
+            ? Optional.empty()
+            : Optional.of(
+                ComponentCreatorDescriptor.create(
+                    getOnlyElement(enclosedCreators), elements, types, dependencyRequestFactory));
+
+    ImmutableSet<Scope> scopes = scopesOf(typeElement);
+    if (componentAnnotation.isProduction()) {
+      scopes = ImmutableSet.<Scope>builder().addAll(scopes).add(productionScope(elements)).build();
+    }
+
+    return new AutoValue_ComponentDescriptor(
+        componentAnnotation,
+        typeElement,
+        componentDependencies,
+        transitiveModules,
+        dependenciesByDependencyMethod.build(),
+        scopes,
+        subcomponentsFromModules.build(),
+        subcomponentsByFactoryMethod.build(),
+        subcomponentsByBuilderMethod.build(),
+        componentMethodsBuilder.build(),
+        creatorDescriptor);
+  }
+
+  private ComponentMethodDescriptor getDescriptorForComponentMethod(
+      TypeElement componentElement,
+      ComponentAnnotation componentAnnotation,
+      ExecutableElement componentMethod) {
+    ComponentMethodDescriptor.Builder descriptor =
+        ComponentMethodDescriptor.builder(componentMethod);
+
+    ExecutableType resolvedComponentMethod =
+        MoreTypes.asExecutable(
+            types.asMemberOf(MoreTypes.asDeclared(componentElement.asType()), componentMethod));
+    TypeMirror returnType = resolvedComponentMethod.getReturnType();
+    if (returnType.getKind().equals(DECLARED) && !getQualifier(componentMethod).isPresent()) {
+      TypeElement returnTypeElement = asTypeElement(returnType);
+      if (subcomponentAnnotation(returnTypeElement).isPresent()) {
+        // It's a subcomponent factory method. There is no dependency request, and there could be
+        // any number of parameters. Just return the descriptor.
+        return descriptor.subcomponent(subcomponentDescriptor(returnTypeElement)).build();
+      }
+      if (isSubcomponentCreator(returnTypeElement)) {
+        descriptor.subcomponent(
+            subcomponentDescriptor(asType(returnTypeElement.getEnclosingElement())));
+      }
+    }
+
+    switch (componentMethod.getParameters().size()) {
+      case 0:
+        checkArgument(
+            !returnType.getKind().equals(VOID),
+            "component method cannot be void: %s",
+            componentMethod);
+        descriptor.dependencyRequest(
+            componentAnnotation.isProduction()
+                ? dependencyRequestFactory.forComponentProductionMethod(
+                    componentMethod, resolvedComponentMethod)
+                : dependencyRequestFactory.forComponentProvisionMethod(
+                    componentMethod, resolvedComponentMethod));
+        break;
+
+      case 1:
+        checkArgument(
+            returnType.getKind().equals(VOID)
+                || MoreTypes.equivalence()
+                    .equivalent(returnType, resolvedComponentMethod.getParameterTypes().get(0)),
+            "members injection method must return void or parameter type: %s",
+            componentMethod);
+        descriptor.dependencyRequest(
+            dependencyRequestFactory.forComponentMembersInjectionMethod(
+                componentMethod, resolvedComponentMethod));
+        break;
+
+      default:
+        throw new IllegalArgumentException(
+            "component method has too many parameters: " + componentMethod);
+    }
+
+    return descriptor.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentDescriptorValidator.java b/java/dagger/internal/codegen/ComponentDescriptorValidator.java
new file mode 100644
index 0000000..8f85b3a
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentDescriptorValidator.java
@@ -0,0 +1,484 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.in;
+import static com.google.common.collect.Collections2.transform;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.ComponentAnnotation.rootComponentAnnotation;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSetMultimap;
+import static dagger.internal.codegen.DiagnosticFormatting.stripCommonTypePrefixes;
+import static dagger.internal.codegen.Formatter.INDENT;
+import static dagger.internal.codegen.Scopes.getReadableSource;
+import static dagger.internal.codegen.Scopes.scopesOf;
+import static dagger.internal.codegen.Scopes.singletonScope;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.base.Equivalence.Wrapper;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.Sets;
+import dagger.internal.codegen.ComponentRequirement.NullPolicy;
+import dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Scope;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.StringJoiner;
+import javax.inject.Inject;
+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.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+
+/**
+ * Reports errors in the component hierarchy.
+ *
+ * <ul>
+ *   <li>Validates scope hierarchy of component dependencies and subcomponents.
+ *   <li>Reports errors if there are component dependency cycles.
+ *   <li>Reports errors if any abstract modules have non-abstract instance binding methods.
+ *   <li>Validates component creator types.
+ * </ul>
+ */
+// TODO(dpb): Combine with ComponentHierarchyValidator.
+final class ComponentDescriptorValidator {
+
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+  private final CompilerOptions compilerOptions;
+  private final MethodSignatureFormatter methodSignatureFormatter;
+  private final ComponentHierarchyValidator componentHierarchyValidator;
+
+  @Inject
+  ComponentDescriptorValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      CompilerOptions compilerOptions,
+      MethodSignatureFormatter methodSignatureFormatter,
+      ComponentHierarchyValidator componentHierarchyValidator) {
+    this.elements = elements;
+    this.types = types;
+    this.compilerOptions = compilerOptions;
+    this.methodSignatureFormatter = methodSignatureFormatter;
+    this.componentHierarchyValidator = componentHierarchyValidator;
+  }
+
+  ValidationReport<TypeElement> validate(ComponentDescriptor component) {
+    ComponentValidation validation = new ComponentValidation(component);
+    validation.visitComponent(component);
+    validation.report(component).addSubreport(componentHierarchyValidator.validate(component));
+    return validation.buildReport();
+  }
+
+  private final class ComponentValidation {
+    final ComponentDescriptor rootComponent;
+    final Map<ComponentDescriptor, ValidationReport.Builder<TypeElement>> reports =
+        new LinkedHashMap<>();
+
+    ComponentValidation(ComponentDescriptor rootComponent) {
+      this.rootComponent = checkNotNull(rootComponent);
+    }
+
+    /** Returns a report that contains all validation messages found during traversal. */
+    ValidationReport<TypeElement> buildReport() {
+      ValidationReport.Builder<TypeElement> report =
+          ValidationReport.about(rootComponent.typeElement());
+      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.typeElement()));
+    }
+
+    private void reportComponentItem(
+        Diagnostic.Kind kind, ComponentDescriptor component, String message) {
+      report(component)
+          .addItem(message, kind, component.typeElement(), component.annotation().annotation());
+    }
+
+    private void reportComponentError(ComponentDescriptor component, String error) {
+      reportComponentItem(ERROR, component, error);
+    }
+
+    void visitComponent(ComponentDescriptor component) {
+      validateDependencyScopes(component);
+      validateComponentDependencyHierarchy(component);
+      validateModules(component);
+      validateCreators(component);
+      component.childComponents().forEach(this::visitComponent);
+    }
+
+    /** Validates that component dependencies do not form a cycle. */
+    private void validateComponentDependencyHierarchy(ComponentDescriptor component) {
+      validateComponentDependencyHierarchy(component, component.typeElement(), new ArrayDeque<>());
+    }
+
+    /** Recursive method to validate that component dependencies do not form a cycle. */
+    private void validateComponentDependencyHierarchy(
+        ComponentDescriptor component, TypeElement dependency, Deque<TypeElement> dependencyStack) {
+      if (dependencyStack.contains(dependency)) {
+        // Current component has already appeared in the component chain.
+        StringBuilder message = new StringBuilder();
+        message.append(component.typeElement().getQualifiedName());
+        message.append(" contains a cycle in its component dependencies:\n");
+        dependencyStack.push(dependency);
+        appendIndentedComponentsList(message, dependencyStack);
+        dependencyStack.pop();
+        reportComponentItem(
+            compilerOptions.scopeCycleValidationType().diagnosticKind().get(),
+            component,
+            message.toString());
+      } else {
+        rootComponentAnnotation(dependency)
+            .ifPresent(
+                componentAnnotation -> {
+                  dependencyStack.push(dependency);
+
+                  for (TypeElement nextDependency : componentAnnotation.dependencies()) {
+                    validateComponentDependencyHierarchy(
+                        component, nextDependency, dependencyStack);
+                  }
+
+                  dependencyStack.pop();
+                });
+      }
+    }
+
+    /**
+     * Validates that among the dependencies are at most one scoped dependency, that there are no
+     * cycles within the scoping chain, and that singleton components have no scoped dependencies.
+     */
+    private void validateDependencyScopes(ComponentDescriptor component) {
+      ImmutableSet<Scope> scopes = component.scopes();
+      ImmutableSet<TypeElement> scopedDependencies =
+          scopedTypesIn(
+              component
+                  .dependencies()
+                  .stream()
+                  .map(ComponentRequirement::typeElement)
+                  .collect(toImmutableSet()));
+      if (!scopes.isEmpty()) {
+        Scope singletonScope = singletonScope(elements);
+        // Dagger 1.x scope compatibility requires this be suppress-able.
+        if (compilerOptions.scopeCycleValidationType().diagnosticKind().isPresent()
+            && scopes.contains(singletonScope)) {
+          // Singleton is a special-case representing the longest lifetime, and therefore
+          // @Singleton components may not depend on scoped components
+          if (!scopedDependencies.isEmpty()) {
+            StringBuilder message =
+                new StringBuilder(
+                    "This @Singleton component cannot depend on scoped components:\n");
+            appendIndentedComponentsList(message, scopedDependencies);
+            reportComponentItem(
+                compilerOptions.scopeCycleValidationType().diagnosticKind().get(),
+                component,
+                message.toString());
+          }
+        } else if (scopedDependencies.size() > 1) {
+          // Scoped components may depend on at most one scoped component.
+          StringBuilder message = new StringBuilder();
+          for (Scope scope : scopes) {
+            message.append(getReadableSource(scope)).append(' ');
+          }
+          message
+              .append(component.typeElement().getQualifiedName())
+              .append(" depends on more than one scoped component:\n");
+          appendIndentedComponentsList(message, scopedDependencies);
+          reportComponentError(component, message.toString());
+        } else {
+          // Dagger 1.x scope compatibility requires this be suppress-able.
+          if (!compilerOptions.scopeCycleValidationType().equals(ValidationType.NONE)) {
+            validateDependencyScopeHierarchy(
+                component, component.typeElement(), new ArrayDeque<>(), new ArrayDeque<>());
+          }
+        }
+      } else {
+        // Scopeless components may not depend on scoped components.
+        if (!scopedDependencies.isEmpty()) {
+          StringBuilder message =
+              new StringBuilder(component.typeElement().getQualifiedName())
+                  .append(" (unscoped) cannot depend on scoped components:\n");
+          appendIndentedComponentsList(message, scopedDependencies);
+          reportComponentError(component, message.toString());
+        }
+      }
+    }
+
+    private void validateModules(ComponentDescriptor component) {
+      for (ModuleDescriptor module : component.modules()) {
+        if (module.moduleElement().getModifiers().contains(Modifier.ABSTRACT)) {
+          for (ContributionBinding binding : module.bindings()) {
+            if (binding.requiresModuleInstance()) {
+              report(component).addError(abstractModuleHasInstanceBindingMethodsError(module));
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    private String abstractModuleHasInstanceBindingMethodsError(ModuleDescriptor module) {
+      String methodAnnotations;
+      switch (module.kind()) {
+        case MODULE:
+          methodAnnotations = "@Provides";
+          break;
+        case PRODUCER_MODULE:
+          methodAnnotations = "@Provides or @Produces";
+          break;
+        default:
+          throw new AssertionError(module.kind());
+      }
+      return String.format(
+          "%s is abstract and has instance %s methods. Consider making the methods static or "
+              + "including a non-abstract subclass of the module instead.",
+          module.moduleElement(), methodAnnotations);
+    }
+
+    private void validateCreators(ComponentDescriptor component) {
+      if (!component.creatorDescriptor().isPresent()) {
+        // If no builder, nothing to validate.
+        return;
+      }
+
+      ComponentCreatorDescriptor creator = component.creatorDescriptor().get();
+      ComponentCreatorMessages messages = ErrorMessages.creatorMessagesFor(creator.annotation());
+
+      // Requirements for modules and dependencies that the creator can set
+      Set<ComponentRequirement> creatorModuleAndDependencyRequirements =
+          creator.moduleAndDependencyRequirements();
+      // Modules and dependencies the component requires
+      Set<ComponentRequirement> componentModuleAndDependencyRequirements =
+          component.dependenciesAndConcreteModules();
+
+      // Requirements that the creator can set that don't match any requirements that the component
+      // actually has.
+      Set<ComponentRequirement> inapplicableRequirementsOnCreator =
+          Sets.difference(
+              creatorModuleAndDependencyRequirements, componentModuleAndDependencyRequirements);
+
+      DeclaredType container = asDeclared(creator.typeElement().asType());
+      if (!inapplicableRequirementsOnCreator.isEmpty()) {
+        Collection<Element> excessElements =
+            Multimaps.filterKeys(
+                    creator.unvalidatedRequirementElements(), in(inapplicableRequirementsOnCreator))
+                .values();
+        String formatted =
+            excessElements.stream()
+                .map(element -> formatElement(element, container))
+                .collect(joining(", ", "[", "]"));
+        report(component)
+            .addError(String.format(messages.extraSetters(), formatted), creator.typeElement());
+      }
+
+      // Component requirements that the creator must be able to set
+      Set<ComponentRequirement> mustBePassed =
+          Sets.filter(
+              componentModuleAndDependencyRequirements,
+              input -> input.nullPolicy(elements, types).equals(NullPolicy.THROW));
+      // Component requirements that the creator must be able to set, but can't
+      Set<ComponentRequirement> missingRequirements =
+          Sets.difference(mustBePassed, creatorModuleAndDependencyRequirements);
+
+      if (!missingRequirements.isEmpty()) {
+        report(component)
+            .addError(
+                String.format(
+                    messages.missingSetters(),
+                    missingRequirements.stream().map(ComponentRequirement::type).collect(toList())),
+                creator.typeElement());
+      }
+
+      // Validate that declared creator requirements (modules, dependencies) have unique types.
+      ImmutableSetMultimap<Wrapper<TypeMirror>, Element> declaredRequirementsByType =
+          Multimaps.filterKeys(
+                  creator.unvalidatedRequirementElements(),
+                  creatorModuleAndDependencyRequirements::contains)
+              .entries().stream()
+              .collect(
+                  toImmutableSetMultimap(entry -> entry.getKey().wrappedType(), Entry::getValue));
+      declaredRequirementsByType
+          .asMap()
+          .forEach(
+              (typeWrapper, elementsForType) -> {
+                if (elementsForType.size() > 1) {
+                  TypeMirror type = typeWrapper.get();
+                  // TODO(cgdecker): Attach this error message to the factory method rather than
+                  // the component type if the elements are factory method parameters AND the
+                  // factory method is defined by the factory type itself and not by a supertype.
+                  report(component)
+                      .addError(
+                          String.format(
+                              messages.multipleSettersForModuleOrDependencyType(),
+                              type,
+                              transform(
+                                  elementsForType, element -> formatElement(element, container))),
+                          creator.typeElement());
+                }
+              });
+
+      // TODO(cgdecker): Duplicate binding validation should handle the case of multiple elements
+      // that set the same bound-instance Key, but validating that here would make it fail faster
+      // for subcomponents.
+    }
+
+    private String formatElement(Element element, DeclaredType container) {
+      // TODO(cgdecker): Extract some or all of this to another class?
+      // But note that it does different formatting for parameters than
+      // DaggerElements.elementToString(Element).
+      switch (element.getKind()) {
+        case METHOD:
+          return methodSignatureFormatter.format(
+              MoreElements.asExecutable(element), Optional.of(container));
+        case PARAMETER:
+          return formatParameter(MoreElements.asVariable(element), container);
+        default:
+          // This method shouldn't be called with any other type of element.
+          throw new AssertionError();
+      }
+    }
+
+    private String formatParameter(VariableElement parameter, DeclaredType container) {
+      // TODO(cgdecker): Possibly leave the type (and annotations?) off of the parameters here and
+      // just use their names, since the type will be redundant in the context of the error message.
+      StringJoiner joiner = new StringJoiner(" ");
+      parameter.getAnnotationMirrors().stream().map(Object::toString).forEach(joiner::add);
+      TypeMirror parameterType = resolveParameterType(parameter, container);
+      return joiner
+          .add(stripCommonTypePrefixes(parameterType.toString()))
+          .add(parameter.getSimpleName())
+          .toString();
+    }
+
+    private TypeMirror resolveParameterType(VariableElement parameter, DeclaredType container) {
+      ExecutableElement method =
+          MoreElements.asExecutable(parameter.getEnclosingElement());
+      int parameterIndex = method.getParameters().indexOf(parameter);
+
+      ExecutableType methodType = MoreTypes.asExecutable(types.asMemberOf(container, method));
+      return methodType.getParameterTypes().get(parameterIndex);
+    }
+
+    /**
+     * Validates that scopes do not participate in a scoping cycle - that is to say, scoped
+     * components are in a hierarchical relationship terminating with Singleton.
+     *
+     * <p>As a side-effect, this means scoped components cannot have a dependency cycle between
+     * themselves, since a component's presence within its own dependency path implies a cyclical
+     * relationship between scopes. However, cycles in component dependencies are explicitly checked
+     * in {@link #validateComponentDependencyHierarchy(ComponentDescriptor)}.
+     */
+    private void validateDependencyScopeHierarchy(
+        ComponentDescriptor component,
+        TypeElement dependency,
+        Deque<ImmutableSet<Scope>> scopeStack,
+        Deque<TypeElement> scopedDependencyStack) {
+      ImmutableSet<Scope> scopes = scopesOf(dependency);
+      if (stackOverlaps(scopeStack, scopes)) {
+        scopedDependencyStack.push(dependency);
+        // Current scope has already appeared in the component chain.
+        StringBuilder message = new StringBuilder();
+        message.append(component.typeElement().getQualifiedName());
+        message.append(" depends on scoped components in a non-hierarchical scope ordering:\n");
+        appendIndentedComponentsList(message, scopedDependencyStack);
+        if (compilerOptions.scopeCycleValidationType().diagnosticKind().isPresent()) {
+          reportComponentItem(
+              compilerOptions.scopeCycleValidationType().diagnosticKind().get(),
+              component,
+              message.toString());
+        }
+        scopedDependencyStack.pop();
+      } else {
+        // TODO(beder): transitively check scopes of production components too.
+        rootComponentAnnotation(dependency)
+            .filter(componentAnnotation -> !componentAnnotation.isProduction())
+            .ifPresent(
+                componentAnnotation -> {
+                  ImmutableSet<TypeElement> scopedDependencies =
+                      scopedTypesIn(componentAnnotation.dependencies());
+                  if (scopedDependencies.size() == 1) {
+                    // empty can be ignored (base-case), and > 1 is a separately-reported error.
+                    scopeStack.push(scopes);
+                    scopedDependencyStack.push(dependency);
+                    validateDependencyScopeHierarchy(
+                        component,
+                        getOnlyElement(scopedDependencies),
+                        scopeStack,
+                        scopedDependencyStack);
+                    scopedDependencyStack.pop();
+                    scopeStack.pop();
+                  }
+                }); // else: we skip component dependencies which are not components
+      }
+    }
+
+    private <T> boolean stackOverlaps(Deque<ImmutableSet<T>> stack, ImmutableSet<T> set) {
+      for (ImmutableSet<T> entry : stack) {
+        if (!Sets.intersection(entry, set).isEmpty()) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    /** Appends and formats a list of indented component types (with their scope annotations). */
+    private void appendIndentedComponentsList(StringBuilder message, Iterable<TypeElement> types) {
+      for (TypeElement scopedComponent : types) {
+        message.append(INDENT);
+        for (Scope scope : scopesOf(scopedComponent)) {
+          message.append(getReadableSource(scope)).append(' ');
+        }
+        message
+            .append(stripCommonTypePrefixes(scopedComponent.getQualifiedName().toString()))
+            .append('\n');
+      }
+    }
+
+    /**
+     * Returns a set of type elements containing only those found in the input set that have a
+     * scoping annotation.
+     */
+    private ImmutableSet<TypeElement> scopedTypesIn(Collection<TypeElement> types) {
+      return types.stream().filter(type -> !scopesOf(type).isEmpty()).collect(toImmutableSet());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentGenerator.java b/java/dagger/internal/codegen/ComponentGenerator.java
new file mode 100644
index 0000000..330ec2d
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentGenerator.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2014 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.common.base.Verify.verify;
+import static dagger.internal.codegen.SourceFiles.classFileName;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.Component;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.Optional;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Generates the implementation of the abstract types annotated with {@link Component}.
+ */
+final class ComponentGenerator extends SourceFileGenerator<BindingGraph> {
+  private final ComponentImplementationFactory componentImplementationFactory;
+
+  @Inject
+  ComponentGenerator(
+      Filer filer,
+      DaggerElements elements,
+      SourceVersion sourceVersion,
+      ComponentImplementationFactory componentImplementationFactory) {
+    super(filer, elements, sourceVersion);
+    this.componentImplementationFactory = componentImplementationFactory;
+  }
+
+  @Override
+  ClassName nameGeneratedType(BindingGraph input) {
+    return componentName(input.componentTypeElement());
+  }
+
+  static ClassName componentName(TypeElement componentDefinitionType) {
+    ClassName componentName = ClassName.get(componentDefinitionType);
+    return ClassName.get(componentName.packageName(), "Dagger" + classFileName(componentName));
+  }
+
+  @Override
+  Element originatingElement(BindingGraph input) {
+    return input.componentTypeElement();
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName componentName, BindingGraph bindingGraph) {
+    ComponentImplementation componentImplementation =
+        componentImplementationFactory.createComponentImplementation(bindingGraph);
+    verify(componentImplementation.name().equals(componentName));
+    return Optional.of(componentImplementation.generate());
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentHierarchyValidator.java b/java/dagger/internal/codegen/ComponentHierarchyValidator.java
new file mode 100644
index 0000000..d1e5333
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentHierarchyValidator.java
@@ -0,0 +1,268 @@
+/*
+ * 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.common.base.Functions.constant;
+import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.in;
+import static com.google.common.base.Predicates.not;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.Scopes.getReadableSource;
+import static dagger.internal.codegen.Scopes.uniqueScopeOf;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.model.Scope;
+import java.util.Collection;
+import java.util.Formatter;
+import java.util.Map;
+import javax.inject.Inject;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+
+/** Validates the relationships between parent components and subcomponents. */
+final class ComponentHierarchyValidator {
+  private static final Joiner COMMA_SEPARATED_JOINER = Joiner.on(", ");
+  private final CompilerOptions compilerOptions;
+
+  @Inject
+  ComponentHierarchyValidator(CompilerOptions compilerOptions) {
+    this.compilerOptions = compilerOptions;
+  }
+
+  ValidationReport<TypeElement> validate(ComponentDescriptor componentDescriptor) {
+    ValidationReport.Builder<TypeElement> report =
+        ValidationReport.about(componentDescriptor.typeElement());
+    validateSubcomponentMethods(
+        report,
+        componentDescriptor,
+        Maps.toMap(componentDescriptor.moduleTypes(), constant(componentDescriptor.typeElement())));
+    validateRepeatedScopedDeclarations(report, componentDescriptor, LinkedHashMultimap.create());
+
+    if (compilerOptions.scopeCycleValidationType().diagnosticKind().isPresent()) {
+      validateScopeHierarchy(
+          report, componentDescriptor, LinkedHashMultimap.<ComponentDescriptor, Scope>create());
+    }
+    validateProductionModuleUniqueness(report, componentDescriptor, LinkedHashMultimap.create());
+    return report.build();
+  }
+
+  private void validateSubcomponentMethods(
+      ValidationReport.Builder<?> report,
+      ComponentDescriptor componentDescriptor,
+      ImmutableMap<TypeElement, TypeElement> existingModuleToOwners) {
+    componentDescriptor
+        .childComponentsDeclaredByFactoryMethods()
+        .forEach(
+            (method, childComponent) -> {
+              if (childComponent.hasCreator()) {
+                report.addError(
+                    "Components may not have factory methods for subcomponents that define a "
+                        + "builder.",
+                    method.methodElement());
+              } else {
+                validateFactoryMethodParameters(report, method, existingModuleToOwners);
+              }
+
+              validateSubcomponentMethods(
+                  report,
+                  childComponent,
+                  new ImmutableMap.Builder<TypeElement, TypeElement>()
+                      .putAll(existingModuleToOwners)
+                      .putAll(
+                          Maps.toMap(
+                              Sets.difference(
+                                  childComponent.moduleTypes(), existingModuleToOwners.keySet()),
+                              constant(childComponent.typeElement())))
+                      .build());
+            });
+  }
+
+  private void validateFactoryMethodParameters(
+      ValidationReport.Builder<?> report,
+      ComponentMethodDescriptor subcomponentMethodDescriptor,
+      ImmutableMap<TypeElement, TypeElement> existingModuleToOwners) {
+    for (VariableElement factoryMethodParameter :
+        subcomponentMethodDescriptor.methodElement().getParameters()) {
+      TypeElement moduleType = MoreTypes.asTypeElement(factoryMethodParameter.asType());
+      TypeElement originatingComponent = existingModuleToOwners.get(moduleType);
+      if (originatingComponent != null) {
+        /* Factory method tries to pass a module that is already present in the parent.
+         * This is an error. */
+        report.addError(
+            String.format(
+                "%s is present in %s. A subcomponent cannot use an instance of a "
+                    + "module that differs from its parent.",
+                moduleType.getSimpleName(), originatingComponent.getQualifiedName()),
+            factoryMethodParameter);
+      }
+    }
+  }
+
+  /**
+   * Checks that components do not have any scopes that are also applied on any of their ancestors.
+   */
+  private void validateScopeHierarchy(
+      ValidationReport.Builder<TypeElement> report,
+      ComponentDescriptor subject,
+      SetMultimap<ComponentDescriptor, Scope> scopesByComponent) {
+    scopesByComponent.putAll(subject, subject.scopes());
+
+    for (ComponentDescriptor childComponent : subject.childComponents()) {
+      validateScopeHierarchy(report, childComponent, scopesByComponent);
+    }
+
+    scopesByComponent.removeAll(subject);
+
+    Predicate<Scope> subjectScopes =
+        subject.isProduction()
+            // TODO(beder): validate that @ProductionScope is only applied on production components
+            ? and(in(subject.scopes()), not(Scope::isProductionScope))
+            : in(subject.scopes());
+    SetMultimap<ComponentDescriptor, Scope> overlappingScopes =
+        Multimaps.filterValues(scopesByComponent, subjectScopes);
+    if (!overlappingScopes.isEmpty()) {
+      StringBuilder error =
+          new StringBuilder()
+              .append(subject.typeElement().getQualifiedName())
+              .append(" has conflicting scopes:");
+      for (Map.Entry<ComponentDescriptor, Scope> entry : overlappingScopes.entries()) {
+        Scope scope = entry.getValue();
+        error
+            .append("\n  ")
+            .append(entry.getKey().typeElement().getQualifiedName())
+            .append(" also has ")
+            .append(getReadableSource(scope));
+      }
+      report.addItem(
+          error.toString(),
+          compilerOptions.scopeCycleValidationType().diagnosticKind().get(),
+          subject.typeElement());
+    }
+  }
+
+  private void validateProductionModuleUniqueness(
+      ValidationReport.Builder<TypeElement> report,
+      ComponentDescriptor componentDescriptor,
+      SetMultimap<ComponentDescriptor, ModuleDescriptor> producerModulesByComponent) {
+    ImmutableSet<ModuleDescriptor> producerModules =
+        componentDescriptor.modules().stream()
+            .filter(module -> module.kind().equals(ModuleKind.PRODUCER_MODULE))
+            .collect(toImmutableSet());
+
+    producerModulesByComponent.putAll(componentDescriptor, producerModules);
+    for (ComponentDescriptor childComponent : componentDescriptor.childComponents()) {
+      validateProductionModuleUniqueness(report, childComponent, producerModulesByComponent);
+    }
+    producerModulesByComponent.removeAll(componentDescriptor);
+
+    SetMultimap<ComponentDescriptor, ModuleDescriptor> repeatedModules =
+        Multimaps.filterValues(producerModulesByComponent, producerModules::contains);
+    if (repeatedModules.isEmpty()) {
+      return;
+    }
+
+    StringBuilder error = new StringBuilder();
+    Formatter formatter = new Formatter(error);
+
+    formatter.format("%s repeats @ProducerModules:", componentDescriptor.typeElement());
+
+    for (Map.Entry<ComponentDescriptor, Collection<ModuleDescriptor>> entry :
+        repeatedModules.asMap().entrySet()) {
+      formatter.format("\n  %s also installs: ", entry.getKey().typeElement());
+      COMMA_SEPARATED_JOINER
+          .appendTo(error, Iterables.transform(entry.getValue(), m -> m.moduleElement()));
+    }
+
+    report.addError(error.toString());
+  }
+
+  private void validateRepeatedScopedDeclarations(
+      ValidationReport.Builder<TypeElement> report,
+      ComponentDescriptor component,
+      // TODO(ronshapiro): optimize ModuleDescriptor.hashCode()/equals. Otherwise this could be
+      // quite costly
+      SetMultimap<ComponentDescriptor, ModuleDescriptor> modulesWithScopes) {
+    ImmutableSet<ModuleDescriptor> modules =
+        component.modules().stream().filter(this::hasScopedDeclarations).collect(toImmutableSet());
+    modulesWithScopes.putAll(component, modules);
+    for (ComponentDescriptor childComponent : component.childComponents()) {
+      validateRepeatedScopedDeclarations(report, childComponent, modulesWithScopes);
+    }
+    modulesWithScopes.removeAll(component);
+
+    SetMultimap<ComponentDescriptor, ModuleDescriptor> repeatedModules =
+        Multimaps.filterValues(modulesWithScopes, modules::contains);
+    if (repeatedModules.isEmpty()) {
+      return;
+    }
+
+    report.addError(
+        repeatedModulesWithScopeError(component, ImmutableSetMultimap.copyOf(repeatedModules)));
+  }
+
+  private boolean hasScopedDeclarations(ModuleDescriptor module) {
+    return !moduleScopes(module).isEmpty();
+  }
+
+  private String repeatedModulesWithScopeError(
+      ComponentDescriptor component,
+      ImmutableSetMultimap<ComponentDescriptor, ModuleDescriptor> repeatedModules) {
+    StringBuilder error =
+        new StringBuilder()
+            .append(component.typeElement().getQualifiedName())
+            .append(" repeats modules with scoped bindings or declarations:");
+
+    repeatedModules
+        .asMap()
+        .forEach(
+            (conflictingComponent, conflictingModules) -> {
+              error
+                  .append("\n  - ")
+                  .append(conflictingComponent.typeElement().getQualifiedName())
+                  .append(" also includes:");
+              for (ModuleDescriptor conflictingModule : conflictingModules) {
+                error
+                    .append("\n    - ")
+                    .append(conflictingModule.moduleElement().getQualifiedName())
+                    .append(" with scopes: ")
+                    .append(COMMA_SEPARATED_JOINER.join(moduleScopes(conflictingModule)));
+              }
+            });
+    return error.toString();
+  }
+
+  private ImmutableSet<Scope> moduleScopes(ModuleDescriptor module) {
+    return FluentIterable.concat(module.allBindingDeclarations())
+        .transform(declaration -> uniqueScopeOf(declaration.bindingElement().get()))
+        .filter(scope -> scope.isPresent() && !scope.get().isReusable())
+        .transform(scope -> scope.get())
+        .toSet();
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentHjarProcessingStep.java b/java/dagger/internal/codegen/ComponentHjarProcessingStep.java
index 260f65a..47857ca 100644
--- a/java/dagger/internal/codegen/ComponentHjarProcessingStep.java
+++ b/java/dagger/internal/codegen/ComponentHjarProcessingStep.java
@@ -16,27 +16,47 @@
 
 package dagger.internal.codegen;
 
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.common.collect.Sets.union;
-import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotations;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.rootComponentCreatorAnnotations;
-import static java.util.Collections.disjoint;
+import static com.google.auto.common.MoreElements.isAnnotationPresent;
+import static com.google.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static dagger.internal.codegen.ComponentAnnotation.rootComponentAnnotations;
+import static dagger.internal.codegen.ComponentCreatorKind.BUILDER;
+import static dagger.internal.codegen.ComponentGenerator.componentName;
+import static dagger.internal.codegen.javapoet.TypeSpecs.addSupertype;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
 
 import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.base.Ascii;
 import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
-import dagger.internal.codegen.validation.ComponentCreatorValidator;
-import dagger.internal.codegen.validation.ComponentValidator;
-import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
-import dagger.internal.codegen.validation.ValidationReport;
+import com.google.common.collect.Sets;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.BindsInstance;
+import dagger.internal.codegen.ComponentValidator.ComponentValidationReport;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.producers.internal.CancellationListener;
 import java.lang.annotation.Annotation;
+import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Stream;
+import javax.annotation.processing.Filer;
 import javax.annotation.processing.Messager;
 import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
 
 /**
  * A processing step that emits the API of a generated component, without any actual implementation.
@@ -52,57 +72,228 @@
  * normal step. Method bodies are omitted as Turbine ignores them entirely.
  */
 final class ComponentHjarProcessingStep extends TypeCheckingProcessingStep<TypeElement> {
+  private final SourceVersion sourceVersion;
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+  private final Filer filer;
   private final Messager messager;
   private final ComponentValidator componentValidator;
-  private final ComponentCreatorValidator creatorValidator;
   private final ComponentDescriptorFactory componentDescriptorFactory;
-  private final SourceFileGenerator<ComponentDescriptor> componentGenerator;
 
   @Inject
   ComponentHjarProcessingStep(
+      SourceVersion sourceVersion,
+      DaggerElements elements,
+      DaggerTypes types,
+      Filer filer,
       Messager messager,
       ComponentValidator componentValidator,
-      ComponentCreatorValidator creatorValidator,
-      ComponentDescriptorFactory componentDescriptorFactory,
-      SourceFileGenerator<ComponentDescriptor> componentGenerator) {
+      ComponentDescriptorFactory componentDescriptorFactory) {
     super(MoreElements::asType);
+    this.sourceVersion = sourceVersion;
+    this.elements = elements;
+    this.types = types;
+    this.filer = filer;
     this.messager = messager;
     this.componentValidator = componentValidator;
-    this.creatorValidator = creatorValidator;
     this.componentDescriptorFactory = componentDescriptorFactory;
-    this.componentGenerator = componentGenerator;
   }
 
   @Override
   public Set<Class<? extends Annotation>> annotations() {
-    return union(rootComponentAnnotations(), rootComponentCreatorAnnotations());
+    return rootComponentAnnotations();
   }
 
-  // TODO(ronshapiro): Validation might not even be necessary. We should measure it and figure out
-  // if it's worth seeing if removing it will still work. We could potentially add a new catch
-  // clause for any exception that's not TypeNotPresentException and ignore the component entirely
-  // in that case.
   @Override
   protected void process(
-      TypeElement element, ImmutableSet<Class<? extends Annotation>> annotations) {
-    if (!disjoint(annotations, rootComponentAnnotations())) {
-      processRootComponent(element);
-    }
-    if (!disjoint(annotations, rootComponentCreatorAnnotations())) {
-      processRootCreator(element);
+      TypeElement componentTypeElement, ImmutableSet<Class<? extends Annotation>> annotations) {
+    // TODO(ronshapiro): component validation might not be necessary. We should measure it and
+    // figure out if it's worth seeing if removing it will still work. We could potentially add a
+    // new catch clause for any exception that's not TypeNotPresentException and ignore the
+    // component entirely in that case.
+    ComponentValidationReport validationReport =
+        componentValidator.validate(componentTypeElement, ImmutableSet.of(), ImmutableSet.of());
+    validationReport.report().printMessagesTo(messager);
+    if (validationReport.report().isClean()) {
+      new EmptyComponentGenerator(filer, elements, sourceVersion)
+          .generate(
+              componentDescriptorFactory.rootComponentDescriptor(componentTypeElement), messager);
     }
   }
 
-  private void processRootComponent(TypeElement element) {
-    ValidationReport<TypeElement> validationReport = componentValidator.validate(element);
-    validationReport.printMessagesTo(messager);
-    if (validationReport.isClean()) {
-      componentGenerator.generate(
-          componentDescriptorFactory.rootComponentDescriptor(element), messager);
+  private final class EmptyComponentGenerator extends SourceFileGenerator<ComponentDescriptor> {
+    EmptyComponentGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
+      super(filer, elements, sourceVersion);
+    }
+
+    @Override
+    ClassName nameGeneratedType(ComponentDescriptor input) {
+      return componentName(input.typeElement());
+    }
+
+    @Override
+    Element originatingElement(ComponentDescriptor input) {
+      return input.typeElement();
+    }
+
+    @Override
+    Optional<TypeSpec.Builder> write(
+        ClassName generatedTypeName, ComponentDescriptor componentDescriptor) {
+      TypeSpec.Builder generatedComponent =
+          TypeSpec.classBuilder(generatedTypeName)
+              .addModifiers(FINAL)
+              .addMethod(privateConstructor());
+      if (componentDescriptor.typeElement().getModifiers().contains(PUBLIC)) {
+        generatedComponent.addModifiers(PUBLIC);
+      }
+
+      TypeElement componentElement = componentDescriptor.typeElement();
+      addSupertype(generatedComponent, componentElement);
+
+      TypeName builderMethodReturnType;
+      ComponentCreatorKind creatorKind;
+      boolean noArgFactoryMethod;
+      if (componentDescriptor.creatorDescriptor().isPresent()) {
+        ComponentCreatorDescriptor creatorDescriptor =
+            componentDescriptor.creatorDescriptor().get();
+        builderMethodReturnType = ClassName.get(creatorDescriptor.typeElement());
+        creatorKind = creatorDescriptor.kind();
+        noArgFactoryMethod = creatorDescriptor.factoryParameters().isEmpty();
+      } else {
+        TypeSpec.Builder builder =
+            TypeSpec.classBuilder("Builder")
+                .addModifiers(STATIC, FINAL)
+                .addMethod(privateConstructor());
+        if (componentDescriptor.typeElement().getModifiers().contains(PUBLIC)) {
+          builder.addModifiers(PUBLIC);
+        }
+
+        ClassName builderClassName = generatedTypeName.nestedClass("Builder");
+        builderMethodReturnType = builderClassName;
+        creatorKind = BUILDER;
+        noArgFactoryMethod = true;
+        componentRequirements(componentDescriptor)
+            .map(requirement -> builderSetterMethod(requirement.typeElement(), builderClassName))
+            .forEach(builder::addMethod);
+        builder.addMethod(builderBuildMethod(componentDescriptor));
+        generatedComponent.addType(builder.build());
+      }
+
+      generatedComponent.addMethod(staticCreatorMethod(builderMethodReturnType, creatorKind));
+
+      if (noArgFactoryMethod
+          && !hasBindsInstanceMethods(componentDescriptor)
+          && componentRequirements(componentDescriptor)
+              .noneMatch(requirement -> requirement.requiresAPassedInstance(elements, types))) {
+        generatedComponent.addMethod(createMethod(componentDescriptor));
+      }
+
+      DeclaredType componentType = MoreTypes.asDeclared(componentElement.asType());
+      // TODO(ronshapiro): unify with ComponentImplementationBuilder
+      Set<MethodSignature> methodSignatures =
+          Sets.newHashSetWithExpectedSize(componentDescriptor.componentMethods().size());
+      componentDescriptor
+          .componentMethods()
+          .stream()
+          .filter(
+              method -> {
+                return methodSignatures.add(
+                    MethodSignature.forComponentMethod(method, componentType, types));
+              })
+          .forEach(
+              method ->
+                  generatedComponent.addMethod(
+                      emptyComponentMethod(componentElement, method.methodElement())));
+
+      if (componentDescriptor.isProduction()) {
+        generatedComponent
+            .addSuperinterface(ClassName.get(CancellationListener.class))
+            .addMethod(onProducerFutureCancelledMethod());
+      }
+
+      return Optional.of(generatedComponent);
     }
   }
 
-  private void processRootCreator(TypeElement creator) {
-    creatorValidator.validate(asType(creator)).printMessagesTo(messager);
+  private MethodSpec emptyComponentMethod(TypeElement typeElement, ExecutableElement baseMethod) {
+    return MethodSpec.overriding(baseMethod, MoreTypes.asDeclared(typeElement.asType()), types)
+        .build();
+  }
+
+  private MethodSpec privateConstructor() {
+    return constructorBuilder().addModifiers(PRIVATE).build();
+  }
+
+  /**
+   * Returns the {@link ComponentRequirement}s for a component that does not have a {@link
+   * ComponentDescriptor#creatorDescriptor()}.
+   */
+  private Stream<ComponentRequirement> componentRequirements(ComponentDescriptor component) {
+    checkArgument(!component.isSubcomponent());
+    return Stream.concat(
+        component.dependencies().stream(),
+        component.modules().stream()
+            .filter(module -> !module.moduleElement().getModifiers().contains(ABSTRACT))
+            .map(module -> ComponentRequirement.forModule(module.moduleElement().asType())));
+  }
+
+  private boolean hasBindsInstanceMethods(ComponentDescriptor componentDescriptor) {
+    return componentDescriptor.creatorDescriptor().isPresent()
+        && elements
+            .getUnimplementedMethods(componentDescriptor.creatorDescriptor().get().typeElement())
+            .stream()
+            .anyMatch(method -> isBindsInstance(method));
+  }
+
+  private static boolean isBindsInstance(ExecutableElement method) {
+    if (isAnnotationPresent(method, BindsInstance.class)) {
+      return true;
+    }
+
+    if (method.getParameters().size() == 1) {
+      return isAnnotationPresent(method.getParameters().get(0), BindsInstance.class);
+    }
+
+    return false;
+  }
+
+  private MethodSpec builderSetterMethod(
+      TypeElement componentRequirement, ClassName builderClass) {
+    String simpleName =
+        UPPER_CAMEL.to(LOWER_CAMEL, componentRequirement.getSimpleName().toString());
+    return MethodSpec.methodBuilder(simpleName)
+        .addModifiers(PUBLIC)
+        .addParameter(ClassName.get(componentRequirement), simpleName)
+        .returns(builderClass)
+        .build();
+  }
+
+  private MethodSpec builderBuildMethod(ComponentDescriptor component) {
+    return MethodSpec.methodBuilder("build")
+        .addModifiers(PUBLIC)
+        .returns(ClassName.get(component.typeElement()))
+        .build();
+  }
+
+  private MethodSpec staticCreatorMethod(
+      TypeName creatorMethodReturnType, ComponentCreatorKind creatorKind) {
+    return MethodSpec.methodBuilder(Ascii.toLowerCase(creatorKind.typeName()))
+        .addModifiers(PUBLIC, STATIC)
+        .returns(creatorMethodReturnType)
+        .build();
+  }
+
+  private MethodSpec createMethod(ComponentDescriptor componentDescriptor) {
+    return MethodSpec.methodBuilder("create")
+        .addModifiers(PUBLIC, STATIC)
+        .returns(ClassName.get(componentDescriptor.typeElement()))
+        .build();
+  }
+
+  private MethodSpec onProducerFutureCancelledMethod() {
+    return MethodSpec.methodBuilder("onProducerFutureCancelled")
+        .addModifiers(PUBLIC)
+        .addParameter(TypeName.BOOLEAN, "mayInterruptIfRunning")
+        .build();
   }
 }
diff --git a/java/dagger/internal/codegen/ComponentImplementation.java b/java/dagger/internal/codegen/ComponentImplementation.java
new file mode 100644
index 0000000..340da14
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentImplementation.java
@@ -0,0 +1,929 @@
+/*
+ * Copyright (C) 2016 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.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.ComponentCreatorKind.BUILDER;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.serialization.ProtoSerialization.toAnnotationValue;
+import static java.util.stream.Collectors.toList;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PUBLIC;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.ConfigureInitializationParameters;
+import dagger.internal.ModifiableBinding;
+import dagger.internal.ModifiableModule;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.TypeSpecs;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/** The implementation of a component type. */
+final class ComponentImplementation {
+  /** A type of field that this component can contain. */
+  enum FieldSpecKind {
+
+    /** A field required by the component, e.g. module instances. */
+    COMPONENT_REQUIREMENT_FIELD,
+
+    /**
+     * A field for the lock and cached value for {@linkplain PrivateMethodBindingExpression
+     * private-method scoped bindings}.
+     */
+    PRIVATE_METHOD_SCOPED_FIELD,
+
+    /** A framework field for type T, e.g. {@code Provider<T>}. */
+    FRAMEWORK_FIELD,
+
+    /** A static field that always returns an absent {@code Optional} value for the binding. */
+    ABSENT_OPTIONAL_FIELD
+  }
+
+  /** A type of method that this component can contain. */
+  // TODO(user, dpb): Change the oder to constructor, initialize, component, then private
+  // (including MIM and AOM—why treat those separately?).
+  enum MethodSpecKind {
+    /** The component constructor. */
+    CONSTRUCTOR,
+
+    /**
+     * In ahead-of-time subcomponents, this method coordinates the invocation of {@link
+     * #INITIALIZE_METHOD initialization methods} instead of constructors.
+     */
+    // TODO(b/117833324): try to merge this with other initialize() methods so it looks more natural
+    CONFIGURE_INITIALIZATION_METHOD,
+
+    /** A builder method for the component. (Only used by the root component.) */
+    BUILDER_METHOD,
+
+    /** A private method that wraps dependency expressions. */
+    PRIVATE_METHOD,
+
+    /** An initialization method that initializes component requirements and framework types. */
+    INITIALIZE_METHOD,
+
+    /** An implementation of a component interface method. */
+    COMPONENT_METHOD,
+
+    /** A private method that encapsulates members injection logic for a binding. */
+    MEMBERS_INJECTION_METHOD,
+
+    /** A static method that always returns an absent {@code Optional} value for the binding. */
+    ABSENT_OPTIONAL_METHOD,
+
+    /**
+     * A method that encapsulates a modifiable binding. A binding is modifiable if it can change
+     * across implementations of a subcomponent. This is only relevant for ahead-of-time
+     * subcomponents.
+     */
+    MODIFIABLE_BINDING_METHOD,
+
+    /**
+     * The {@link dagger.producers.internal.CancellationListener#onProducerFutureCancelled(boolean)}
+     * method for a production component.
+     */
+    CANCELLATION_LISTENER_METHOD,
+    ;
+  }
+
+  /** A type of nested class that this component can contain. */
+  enum TypeSpecKind {
+    /** A factory class for a present optional binding. */
+    PRESENT_FACTORY,
+
+    /** A class for the component creator (only used by the root component.) */
+    COMPONENT_CREATOR,
+
+    /** A provider class for a component provision. */
+    COMPONENT_PROVISION_FACTORY,
+
+    /** A class for the subcomponent or subcomponent builder. */
+    SUBCOMPONENT
+  }
+
+  /**
+   * The method spec for a {@code configureInitialization} method plus details on the component
+   * requirements that its parameters are associated with.
+   */
+  @AutoValue
+  abstract static class ConfigureInitializationMethod {
+    /** Creates a new {@link ConfigureInitializationMethod}. */
+    static ConfigureInitializationMethod create(
+        MethodSpec spec, ImmutableSet<ComponentRequirement> parameters) {
+      return new AutoValue_ComponentImplementation_ConfigureInitializationMethod(spec, parameters);
+    }
+
+    /** The spec for the method. */
+    abstract MethodSpec spec();
+
+    /**
+     * The component requirements associated with the method's parameters, in the same order as the
+     * parameters.
+     */
+    abstract ImmutableSet<ComponentRequirement> parameters();
+  }
+
+  private final CompilerOptions compilerOptions;
+  private final ComponentDescriptor componentDescriptor;
+  private final Optional<BindingGraph> graph;
+  private final ClassName name;
+  private final NestingKind nestingKind;
+  private final boolean isAbstract;
+  private final Optional<ComponentImplementation> superclassImplementation;
+  private Optional<ComponentCreatorImplementation> creatorImplementation;
+  private final Map<TypeElement, ComponentImplementation> childImplementations = new HashMap<>();
+  private final TypeSpec.Builder component;
+  private final Optional<SubcomponentNames> subcomponentNames;
+  private final UniqueNameSet componentFieldNames = new UniqueNameSet();
+  private final UniqueNameSet componentMethodNames = new UniqueNameSet();
+  private final List<CodeBlock> initializations = new ArrayList<>();
+  private final Set<ComponentRequirement> componentRequirementParameters = new HashSet<>();
+  private final List<CodeBlock> componentRequirementInitializations = new ArrayList<>();
+  private final Map<ComponentRequirement, String> componentRequirementParameterNames =
+      new HashMap<>();
+  private final Set<Key> cancellableProducerKeys = new LinkedHashSet<>();
+  private final ListMultimap<FieldSpecKind, FieldSpec> fieldSpecsMap =
+      MultimapBuilder.enumKeys(FieldSpecKind.class).arrayListValues().build();
+  private final ListMultimap<MethodSpecKind, MethodSpec> methodSpecsMap =
+      MultimapBuilder.enumKeys(MethodSpecKind.class).arrayListValues().build();
+  private final ListMultimap<TypeSpecKind, TypeSpec> typeSpecsMap =
+      MultimapBuilder.enumKeys(TypeSpecKind.class).arrayListValues().build();
+  private final List<Supplier<TypeSpec>> switchingProviderSupplier = new ArrayList<>();
+  private final ModifiableBindingMethods modifiableBindingMethods = new ModifiableBindingMethods();
+  private final SetMultimap<BindingRequest, Key> multibindingContributionsMade =
+      LinkedHashMultimap.create();
+  private Optional<ConfigureInitializationMethod> configureInitializationMethod = Optional.empty();
+  private final Map<ComponentRequirement, String> modifiableModuleMethods = new LinkedHashMap<>();
+
+  private ComponentImplementation(
+      ComponentDescriptor componentDescriptor,
+      Optional<BindingGraph> graph,
+      ClassName name,
+      NestingKind nestingKind,
+      Optional<ComponentImplementation> superclassImplementation,
+      Optional<SubcomponentNames> subcomponentNames,
+      CompilerOptions compilerOptions,
+      ImmutableSet<Modifier> modifiers) {
+    checkName(name, nestingKind);
+    this.compilerOptions = compilerOptions;
+    this.componentDescriptor = componentDescriptor;
+    this.graph = graph;
+    this.name = name;
+    this.nestingKind = nestingKind;
+    this.isAbstract = modifiers.contains(ABSTRACT);
+    this.superclassImplementation = superclassImplementation;
+    this.component = classBuilder(name);
+    modifiers.forEach(component::addModifiers);
+    this.subcomponentNames = subcomponentNames;
+  }
+
+  /** Returns a component implementation for a top-level component. */
+  static ComponentImplementation topLevelComponentImplementation(
+      BindingGraph graph,
+      ClassName name,
+      SubcomponentNames subcomponentNames,
+      CompilerOptions compilerOptions) {
+    return new ComponentImplementation(
+        graph.componentDescriptor(),
+        Optional.of(graph),
+        name,
+        NestingKind.TOP_LEVEL,
+        Optional.empty(), // superclass implementation
+        Optional.of(subcomponentNames),
+        compilerOptions,
+        topLevelComponentImplementationModifiers(graph));
+  }
+
+  private static ImmutableSet<Modifier> topLevelComponentImplementationModifiers(
+      BindingGraph graph) {
+    ImmutableSet.Builder<Modifier> modifiers = ImmutableSet.builder();
+    if (graph.componentTypeElement().getModifiers().contains(PUBLIC)
+        || graph.componentDescriptor().isSubcomponent()) {
+      // TODO(ronshapiro): perhaps all generated components should be non-public?
+      modifiers.add(PUBLIC);
+    }
+    return modifiers.add(graph.componentDescriptor().isSubcomponent() ? ABSTRACT : FINAL).build();
+  }
+
+  /** Returns a component implementation that is a child of the current implementation. */
+  ComponentImplementation childComponentImplementation(
+      BindingGraph graph,
+      Optional<ComponentImplementation> superclassImplementation,
+      Modifier... modifiers) {
+    return new ComponentImplementation(
+        graph.componentDescriptor(),
+        Optional.of(graph),
+        getSubcomponentName(graph.componentDescriptor()),
+        NestingKind.MEMBER,
+        superclassImplementation,
+        subcomponentNames,
+        compilerOptions,
+        ImmutableSet.copyOf(modifiers));
+  }
+
+  /**
+   * Returns a component implementation that models a previously compiled class. This {@link
+   * ComponentImplementation} is not used for code generation itself; it is used to determine what
+   * methods need to be implemented in a subclass implementation.
+   */
+  static ComponentImplementation forDeserializedComponent(
+      ComponentDescriptor componentDescriptor,
+      ClassName name,
+      NestingKind nestingKind,
+      Optional<ComponentImplementation> superclassImplementation,
+      CompilerOptions compilerOptions) {
+    return new ComponentImplementation(
+        componentDescriptor,
+        Optional.empty(),
+        name,
+        nestingKind,
+        superclassImplementation,
+        Optional.empty(),
+        compilerOptions,
+        ImmutableSet.of(PUBLIC, ABSTRACT));
+  }
+
+  // TODO(dpb): Just determine the nesting kind from the name.
+  private static void checkName(ClassName name, NestingKind nestingKind) {
+    switch (nestingKind) {
+      case TOP_LEVEL:
+        checkArgument(
+            name.enclosingClassName() == null, "must be a top-level class name: %s", name);
+        break;
+
+      case MEMBER:
+        checkNotNull(name.enclosingClassName(), "must not be a top-level class name: %s", name);
+        break;
+
+      default:
+        throw new IllegalArgumentException(
+            "nestingKind must be TOP_LEVEL or MEMBER: " + nestingKind);
+    }
+  }
+
+  /**
+   * Returns {@code true} if this component implementation represents a component that has already
+   * been compiled. If this returns true, the implementation will have no {@link #graph
+   * BindingGraph}.
+   */
+  boolean isDeserializedImplementation() {
+    return !graph.isPresent();
+  }
+
+  // TODO(ronshapiro): see if we can remove this method and instead inject it in the objects that
+  // need it.
+  /** Returns the binding graph for the component being generated. */
+  BindingGraph graph() {
+    checkState(!isDeserializedImplementation(),
+        "A BindingGraph is not available for deserialized component implementations.");
+    return graph.get();
+  }
+
+  /** Returns the descriptor for the component being generated. */
+  ComponentDescriptor componentDescriptor() {
+    return componentDescriptor;
+  }
+
+  /** Returns the name of the component. */
+  ClassName name() {
+    return name;
+  }
+
+  /** Returns whether or not the implementation is nested within another class. */
+  boolean isNested() {
+    return nestingKind.isNested();
+  }
+
+  /** Returns whether or not the implementation is abstract. */
+  boolean isAbstract() {
+    return isAbstract;
+  }
+
+  /** Returns the superclass implementation. */
+  Optional<ComponentImplementation> superclassImplementation() {
+    return superclassImplementation;
+  }
+
+  /**
+   * Returns the base implementation of this component in ahead-of-time subcomponents mode. If this
+   * is the base implementation, this returns {@link Optional#empty()}.
+   */
+  Optional<ComponentImplementation> baseImplementation() {
+    return superclassImplementation.isPresent()
+        ? Optional.of(Optionals.rootmostValue(this, c -> c.superclassImplementation))
+        : Optional.empty();
+  }
+
+  /**
+   * Returns the {@link #configureInitializationMethod()} of the nearest supertype that defines one,
+   * if any.
+   *
+   * <p>Only returns a present value in {@link CompilerOptions#aheadOfTimeSubcomponents()}.
+   */
+  Optional<ConfigureInitializationMethod> superConfigureInitializationMethod() {
+    for (Optional<ComponentImplementation> currentSuper = superclassImplementation;
+        currentSuper.isPresent();
+        currentSuper = currentSuper.get().superclassImplementation) {
+      if (currentSuper.get().configureInitializationMethod.isPresent()) {
+        return currentSuper.get().configureInitializationMethod;
+      }
+    }
+    return Optional.empty();
+  }
+
+  /**
+   * The requirements for creating an instance of this component implementation type.
+   *
+   * <p>If this component implementation is concrete, these requirements will be in the order that
+   * the implementation's constructor takes them as parameters.
+   */
+  ImmutableSet<ComponentRequirement> requirements() {
+    // If the base implementation's creator is being generated in ahead-of-time-subcomponents
+    // mode, this uses the ComponentDescriptor's requirements() since Dagger doesn't know what
+    // modules may end being unused or owned by an ancestor component. Otherwise, we use the
+    // necessary component requirements.
+    // TODO(ronshapiro): can we remove the second condition here? Or, is it never going to be
+    // called, so we should enforce that invariant?
+    return isAbstract() && !superclassImplementation().isPresent()
+        ? componentDescriptor().requirements()
+        : graph().componentRequirements();
+  }
+
+  /**
+   * Returns the {@link MethodSpecKind#CONFIGURE_INITIALIZATION_METHOD} of this implementation if
+   * there is one.
+   *
+   * <p>Only returns a present value in {@link CompilerOptions#aheadOfTimeSubcomponents()}.
+   */
+  Optional<ConfigureInitializationMethod> configureInitializationMethod() {
+    return configureInitializationMethod;
+  }
+
+  /**
+   * Set's this component implementation's {@code configureInitialization()} method and {@linkplain
+   * #addMethod(MethodSpecKind, MethodSpec) adds the method}.
+   */
+  void setConfigureInitializationMethod(ConfigureInitializationMethod method) {
+    configureInitializationMethod = Optional.of(method);
+    addMethod(
+        MethodSpecKind.CONFIGURE_INITIALIZATION_METHOD,
+        addConfigureInitializationMetadata(method));
+  }
+
+  private MethodSpec addConfigureInitializationMetadata(ConfigureInitializationMethod method) {
+    if (!shouldEmitModifiableMetadataAnnotations()) {
+      return method.spec();
+    }
+    AnnotationSpec.Builder annotation =
+        AnnotationSpec.builder(ConfigureInitializationParameters.class);
+    for (ComponentRequirement parameter : method.parameters()) {
+      annotation.addMember("value", toAnnotationValue(parameter.toProto()));
+    }
+
+    return method.spec().toBuilder().addAnnotation(annotation.build()).build();
+  }
+
+  void setCreatorImplementation(Optional<ComponentCreatorImplementation> creatorImplementation) {
+    checkState(
+        this.creatorImplementation == null, "setCreatorImplementation has already been called");
+    this.creatorImplementation = creatorImplementation;
+  }
+
+  Optional<ComponentCreatorImplementation> creatorImplementation() {
+    checkState(creatorImplementation != null, "setCreatorImplementation has not been called yet");
+    return creatorImplementation;
+  }
+
+  /**
+   * Returns the {@link ComponentCreatorImplementation} defined in the base implementation for this
+   * component, if one exists.
+   */
+  Optional<ComponentCreatorImplementation> baseCreatorImplementation() {
+    return baseImplementation().flatMap(baseImpl -> baseImpl.creatorImplementation());
+  }
+
+  /**
+   * Returns the kind of this component's creator.
+   *
+   * @throws IllegalStateException if the component has no creator
+   */
+  private ComponentCreatorKind creatorKind() {
+    checkState(componentDescriptor().hasCreator());
+    return componentDescriptor()
+        .creatorDescriptor()
+        .map(ComponentCreatorDescriptor::kind)
+        .orElse(BUILDER);
+  }
+
+  /**
+   * Returns the name of the creator class for this component. It will be a sibling of this
+   * generated class unless this is a top-level component, in which case it will be nested.
+   */
+  ClassName getCreatorName() {
+    return isNested()
+        ? name.peerClass(subcomponentNames().getCreatorName(componentDescriptor()))
+        : name.nestedClass(creatorKind().typeName());
+  }
+
+  /** Returns the name of the nested implementation class for a child component. */
+  ClassName getSubcomponentName(ComponentDescriptor childDescriptor) {
+    checkArgument(
+        componentDescriptor().childComponents().contains(childDescriptor),
+        "%s is not a child component of %s",
+        childDescriptor.typeElement(),
+        componentDescriptor().typeElement());
+    return name.nestedClass(subcomponentNames().get(childDescriptor) + "Impl");
+  }
+
+  /**
+   * Returns the simple name of the creator implementation class for the given subcomponent creator
+   * {@link Key}.
+   */
+  String getSubcomponentCreatorSimpleName(Key key) {
+    return subcomponentNames().getCreatorName(key);
+  }
+
+  private SubcomponentNames subcomponentNames() {
+    checkState(
+        subcomponentNames.isPresent(),
+        "SubcomponentNames is not available for deserialized component implementations.");
+    return subcomponentNames.get();
+  }
+
+  /** Returns the child implementation. */
+  Optional<ComponentImplementation> childImplementation(ComponentDescriptor child) {
+    return Optional.ofNullable(childImplementations.get(child.typeElement()));
+  }
+
+  /** Returns {@code true} if {@code type} is accessible from the generated component. */
+  boolean isTypeAccessible(TypeMirror type) {
+    return isTypeAccessibleFrom(type, name.packageName());
+  }
+
+  /** Adds the given super type to the component. */
+  void addSupertype(TypeElement supertype) {
+    TypeSpecs.addSupertype(component, supertype);
+  }
+
+  /** Adds the given super class to the subcomponent. */
+  void addSuperclass(ClassName className) {
+    checkState(
+        superclassImplementation.isPresent(),
+        "Setting the superclass for component [%s] when there is no superclass implementation.",
+        name);
+    component.superclass(className);
+  }
+
+  // TODO(dpb): Consider taking FieldSpec, and returning identical FieldSpec with unique name?
+  /** Adds the given field to the component. */
+  void addField(FieldSpecKind fieldKind, FieldSpec fieldSpec) {
+    fieldSpecsMap.put(fieldKind, fieldSpec);
+  }
+
+  /** Adds the given fields to the component. */
+  void addFields(FieldSpecKind fieldKind, Iterable<FieldSpec> fieldSpecs) {
+    fieldSpecsMap.putAll(fieldKind, fieldSpecs);
+  }
+
+  // TODO(dpb): Consider taking MethodSpec, and returning identical MethodSpec with unique name?
+  /** Adds the given method to the component. */
+  void addMethod(MethodSpecKind methodKind, MethodSpec methodSpec) {
+    methodSpecsMap.put(methodKind, methodSpec);
+  }
+
+  /** Adds the given annotation to the component. */
+  void addAnnotation(AnnotationSpec annotation) {
+    component.addAnnotation(annotation);
+  }
+
+  /**
+   * Adds the given method to the component. In this case, the method represents an encapsulation of
+   * a modifiable binding between implementations of a subcomponent. This is only relevant for
+   * ahead-of-time subcomponents.
+   */
+  void addModifiableBindingMethod(
+      ModifiableBindingType type,
+      BindingRequest request,
+      TypeMirror returnType,
+      MethodSpec methodSpec,
+      boolean finalized) {
+    addModifiableMethod(
+        MethodSpecKind.MODIFIABLE_BINDING_METHOD, type, request, returnType, methodSpec, finalized);
+  }
+
+  /**
+   * Adds a component method that is modifiable to the component. In this case, the method
+   * represents an encapsulation of a modifiable binding between implementations of a subcomponent.
+   * This is only relevant for ahead-of-time subcomponents.
+   */
+  void addModifiableComponentMethod(
+      ModifiableBindingType type,
+      BindingRequest request,
+      TypeMirror returnType,
+      MethodSpec methodSpec,
+      boolean finalized) {
+    addModifiableMethod(
+        MethodSpecKind.COMPONENT_METHOD, type, request, returnType, methodSpec, finalized);
+  }
+
+  private void addModifiableMethod(
+      MethodSpecKind methodKind,
+      ModifiableBindingType type,
+      BindingRequest request,
+      TypeMirror returnType,
+      MethodSpec methodSpec,
+      boolean finalized) {
+    modifiableBindingMethods.addModifiableMethod(
+        type, request, returnType, methodSpec, finalized);
+    methodSpecsMap.put(methodKind, withModifiableBindingMetadata(methodSpec, type, request));
+  }
+
+  /** Adds the implementation for the given {@link ModifiableBindingMethod} to the component. */
+  void addImplementedModifiableBindingMethod(ModifiableBindingMethod method) {
+    modifiableBindingMethods.addReimplementedMethod(method);
+    methodSpecsMap.put(
+        MethodSpecKind.MODIFIABLE_BINDING_METHOD,
+        withModifiableBindingMetadata(method.methodSpec(), method.type(), method.request()));
+  }
+
+  private MethodSpec withModifiableBindingMetadata(
+      MethodSpec method, ModifiableBindingType type, BindingRequest request) {
+    if (!shouldEmitModifiableMetadataAnnotations()) {
+      return method;
+    }
+    AnnotationSpec.Builder metadata =
+        AnnotationSpec.builder(ModifiableBinding.class)
+            .addMember("modifiableBindingType", "$S", type.name())
+            .addMember("bindingRequest", toAnnotationValue(request.toProto()));
+    for (Key multibindingContribution : multibindingContributionsMade.get(request)) {
+      metadata.addMember(
+          "multibindingContributions",
+          toAnnotationValue(KeyFactory.toProto(multibindingContribution)));
+    }
+    return method.toBuilder().addAnnotation(metadata.build()).build();
+  }
+
+  /** Add's a modifiable module method to this implementation. */
+  void addModifiableModuleMethod(ComponentRequirement module, MethodSpec method) {
+    registerModifiableModuleMethod(module, method.name);
+    methodSpecsMap.put(
+        MethodSpecKind.MODIFIABLE_BINDING_METHOD, withModifiableModuleMetadata(module, method));
+  }
+
+  /** Registers a modifiable module method with {@code name} for {@code module}. */
+  void registerModifiableModuleMethod(ComponentRequirement module, String name) {
+    checkArgument(module.kind().isModule());
+    checkState(modifiableModuleMethods.put(module, name) == null);
+  }
+
+  private MethodSpec withModifiableModuleMetadata(ComponentRequirement module, MethodSpec method) {
+    if (!shouldEmitModifiableMetadataAnnotations()) {
+      return method;
+    }
+    return method
+        .toBuilder()
+        .addAnnotation(
+            AnnotationSpec.builder(ModifiableModule.class)
+                .addMember("value", toAnnotationValue(module.toProto()))
+                .build())
+        .build();
+  }
+
+  /**
+   * Returns {@code true} if the generated component should include metadata annotations with
+   * information to deserialize this {@link ComponentImplementation} in future compilations.
+   */
+  boolean shouldEmitModifiableMetadataAnnotations() {
+    return isAbstract && compilerOptions.emitModifiableMetadataAnnotations();
+  }
+
+  /** Adds the given type to the component. */
+  void addType(TypeSpecKind typeKind, TypeSpec typeSpec) {
+    typeSpecsMap.put(typeKind, typeSpec);
+  }
+
+  /** Adds the type generated from the given child implementation. */
+  void addChild(ComponentDescriptor child, ComponentImplementation childImplementation) {
+    childImplementations.put(child.typeElement(), childImplementation);
+    addType(TypeSpecKind.SUBCOMPONENT, childImplementation.generate().build());
+  }
+
+  /** Adds a {@link Supplier} for the SwitchingProvider for the component. */
+  void addSwitchingProvider(Supplier<TypeSpec> typeSpecSupplier) {
+    switchingProviderSupplier.add(typeSpecSupplier);
+  }
+
+  /** Adds the given code block to the initialize methods of the component. */
+  void addInitialization(CodeBlock codeBlock) {
+    initializations.add(codeBlock);
+  }
+
+  /**
+   * Adds the given component requirement as one that should have a parameter in the component's
+   * initialization methods.
+   */
+  void addComponentRequirementParameter(ComponentRequirement requirement) {
+    componentRequirementParameters.add(requirement);
+  }
+
+  /**
+   * The set of component requirements that have parameters in the component's initialization
+   * methods.
+   */
+  ImmutableSet<ComponentRequirement> getComponentRequirementParameters() {
+    return ImmutableSet.copyOf(componentRequirementParameters);
+  }
+
+  /** Adds the given code block that initializes a {@link ComponentRequirement}. */
+  void addComponentRequirementInitialization(CodeBlock codeBlock) {
+    componentRequirementInitializations.add(codeBlock);
+  }
+
+  /**
+   * Marks the given key of a producer as one that should have a cancellation statement in the
+   * cancellation listener method of the component.
+   */
+  void addCancellableProducerKey(Key key) {
+    cancellableProducerKeys.add(key);
+  }
+
+  /** Returns a new, unique field name for the component based on the given name. */
+  String getUniqueFieldName(String name) {
+    return componentFieldNames.getUniqueName(name);
+  }
+
+  /** Returns a new, unique method name for the component based on the given name. */
+  String getUniqueMethodName(String name) {
+    return componentMethodNames.getUniqueName(name);
+  }
+
+  /** Returns a new, unique method name for a getter method for the given request. */
+  String getUniqueMethodName(BindingRequest request) {
+    return uniqueMethodName(request, KeyVariableNamer.name(request.key()));
+  }
+
+  private String uniqueMethodName(BindingRequest request, String bindingName) {
+    String baseMethodName =
+        "get"
+            + LOWER_CAMEL.to(UPPER_CAMEL, bindingName)
+            + (request.isRequestKind(RequestKind.INSTANCE)
+                ? ""
+                : UPPER_UNDERSCORE.to(UPPER_CAMEL, request.kindName()));
+    return getUniqueMethodName(baseMethodName);
+  }
+
+  /** Gets the parameter name to use for the given requirement for this component. */
+  String getParameterName(ComponentRequirement requirement) {
+    return getParameterName(requirement, requirement.variableName());
+  }
+
+  /**
+   * Gets the parameter name to use for the given requirement for this component, starting with the
+   * given base name if no parameter name has already been selected for the requirement.
+   */
+  String getParameterName(ComponentRequirement requirement, String baseName) {
+    return componentRequirementParameterNames.computeIfAbsent(
+        requirement, r -> getUniqueFieldName(baseName));
+  }
+
+  /** Claims a new method name for the component. Does nothing if method name already exists. */
+  void claimMethodName(CharSequence name) {
+    componentMethodNames.claim(name);
+  }
+
+  /** Returns the list of {@link CodeBlock}s that need to go in the initialize method. */
+  ImmutableList<CodeBlock> getInitializations() {
+    return ImmutableList.copyOf(initializations);
+  }
+
+  /**
+   * Returns a list of {@link CodeBlock}s for initializing {@link ComponentRequirement}s.
+   *
+   * <p>These initializations are kept separate from {@link #getInitializations()} because they must
+   * be executed before the initializations of any framework instance initializations in a
+   * superclass implementation that may depend on the instances. We cannot use the same strategy
+   * that we use for framework instances (i.e. wrap in a {@link dagger.internal.DelegateFactory} or
+   * {@link dagger.producers.internal.DelegateProducer} since the types of these initialized fields
+   * have no interface type that we can write a proxy for.
+   */
+  ImmutableList<CodeBlock> getComponentRequirementInitializations() {
+    return ImmutableList.copyOf(componentRequirementInitializations);
+  }
+
+  /**
+   * Returns whether or not this component has any {@linkplain #getInitializations() initilizations}
+   * or {@linkplain #getComponentRequirementInitializations() component requirement
+   * initializations}.
+   */
+  boolean hasInitializations() {
+    return !initializations.isEmpty() || !componentRequirementInitializations.isEmpty();
+  }
+
+  /**
+   * Returns the list of producer {@link Key}s that need cancellation statements in the cancellation
+   * listener method.
+   */
+  ImmutableList<Key> getCancellableProducerKeys() {
+    Optional<ComponentImplementation> currentSuperImplementation = superclassImplementation;
+    Set<Key> cancelledKeysFromSuperclass = new HashSet<>();
+    while (currentSuperImplementation.isPresent()) {
+      cancelledKeysFromSuperclass.addAll(currentSuperImplementation.get().cancellableProducerKeys);
+      currentSuperImplementation = currentSuperImplementation.get().superclassImplementation;
+    }
+    return Sets.difference(cancellableProducerKeys, cancelledKeysFromSuperclass)
+        .immutableCopy()
+        .asList();
+  }
+
+  /**
+   * Returns the {@link ModifiableBindingMethod}s for this subcomponent implementation and its
+   * superclasses.
+   */
+  ImmutableMap<BindingRequest, ModifiableBindingMethod> getModifiableBindingMethods() {
+    Map<BindingRequest, ModifiableBindingMethod> modifiableBindingMethodsBuilder =
+        new LinkedHashMap<>();
+    if (superclassImplementation.isPresent()) {
+      modifiableBindingMethodsBuilder.putAll(
+          Maps.filterValues(
+              superclassImplementation.get().getModifiableBindingMethods(),
+              // filters the modifiable methods of a superclass that are finalized in this component
+              method -> !modifiableBindingMethods.finalized(method)));
+    }
+    // replace superclass modifiable binding methods with any that are defined in this component
+    // implementation
+    modifiableBindingMethodsBuilder.putAll(modifiableBindingMethods.getNonFinalizedMethods());
+    return ImmutableMap.copyOf(modifiableBindingMethodsBuilder);
+  }
+
+  /**
+   * Returns the names of every modifiable method of this implementation and any superclass
+   * implementations.
+   */
+  ImmutableSet<String> getAllModifiableMethodNames() {
+    ImmutableSet.Builder<String> names = ImmutableSet.builder();
+    modifiableBindingMethods.allMethods().forEach(method -> names.add(method.methodSpec().name));
+    names.addAll(modifiableModuleMethods.values());
+    superclassImplementation.ifPresent(
+        superclass -> names.addAll(superclass.getAllModifiableMethodNames()));
+    return names.build();
+  }
+
+  /**
+   * Returns the {@link ModifiableBindingMethod} for this subcomponent for the given binding, if it
+   * exists.
+   */
+  Optional<ModifiableBindingMethod> getModifiableBindingMethod(BindingRequest request) {
+    Optional<ModifiableBindingMethod> method = modifiableBindingMethods.getMethod(request);
+    if (!method.isPresent() && superclassImplementation.isPresent()) {
+      return superclassImplementation.get().getModifiableBindingMethod(request);
+    }
+    return method;
+  }
+
+  /**
+   * Returns the {@link ModifiableBindingMethod} of a supertype for this method's {@code request},
+   * if one exists.
+   */
+  Optional<ModifiableBindingMethod> supertypeModifiableBindingMethod(BindingRequest request) {
+    return superclassImplementation()
+        .flatMap(superImplementation -> superImplementation.getModifiableBindingMethod(request));
+  }
+
+  /**
+   * Returns the names of modifiable module methods for this implementation and all inherited
+   * implementations, keyed by the corresponding module's {@link ComponentRequirement}.
+   */
+  ImmutableMap<ComponentRequirement, String> getAllModifiableModuleMethods() {
+    ImmutableMap.Builder<ComponentRequirement, String> methods = ImmutableMap.builder();
+    methods.putAll(modifiableModuleMethods);
+    superclassImplementation.ifPresent(
+        superclass -> methods.putAll(superclass.getAllModifiableModuleMethods()));
+    return methods.build();
+  }
+
+  /**
+   * Returns the name of the modifiable module method for {@code module} that is inherited in this
+   * implementation, or empty if none has been defined.
+   */
+  Optional<String> supertypeModifiableModuleMethodName(ComponentRequirement module) {
+    checkArgument(module.kind().isModule());
+    if (!superclassImplementation.isPresent()) {
+      return Optional.empty();
+    }
+    String methodName = superclassImplementation.get().modifiableModuleMethods.get(module);
+    if (methodName == null) {
+      return superclassImplementation.get().supertypeModifiableModuleMethodName(module);
+    }
+    return Optional.of(methodName);
+  }
+
+  /** Generates the component and returns the resulting {@link TypeSpec.Builder}. */
+  TypeSpec.Builder generate() {
+    fieldSpecsMap.asMap().values().forEach(component::addFields);
+    methodSpecsMap.asMap().values().forEach(component::addMethods);
+    typeSpecsMap.asMap().values().forEach(component::addTypes);
+    switchingProviderSupplier.stream().map(Supplier::get).forEach(component::addType);
+    return component;
+  }
+
+  /**
+   * Registers a {@ProvisionBinding} representing a multibinding as having been implemented in this
+   * component. Multibindings are modifiable across subcomponent implementations and this allows us
+   * to know whether a contribution has been made by a superclass implementation. This is only
+   * relevant for ahead-of-time subcomponents.
+   */
+  void registerImplementedMultibinding(
+      ContributionBinding multibinding, BindingRequest bindingRequest) {
+    checkArgument(multibinding.isSyntheticMultibinding());
+    // We register a multibinding as implemented each time we request the multibinding expression,
+    // so only modify the set of contributions once.
+    if (!multibindingContributionsMade.containsKey(bindingRequest)) {
+      registerImplementedMultibindingKeys(
+          bindingRequest,
+          multibinding.dependencies().stream().map(DependencyRequest::key).collect(toList()));
+    }
+  }
+
+  /**
+   * Registers the multibinding contributions represented by {@code keys} as having been implemented
+   * in this component. Multibindings are modifiable across subcomponent implementations and this
+   * allows us to know whether a contribution has been made by a superclass implementation. This is
+   * only relevant for ahead-of-time subcomponents.
+   */
+  void registerImplementedMultibindingKeys(BindingRequest bindingRequest, Iterable<Key> keys) {
+    multibindingContributionsMade.putAll(bindingRequest, keys);
+  }
+
+  /**
+   * Returns the set of multibinding contributions associated with all superclass implementations of
+   * a multibinding.
+   */
+  ImmutableSet<Key> superclassContributionsMade(BindingRequest bindingRequest) {
+    return superclassImplementation
+        .map(s -> s.getAllMultibindingContributions(bindingRequest))
+        .orElse(ImmutableSet.of());
+  }
+
+  /**
+   * Returns the set of multibinding contributions associated with all implementations of a
+   * multibinding.
+   */
+  private ImmutableSet<Key> getAllMultibindingContributions(BindingRequest bindingRequest) {
+    return ImmutableSet.copyOf(
+        Sets.union(
+            multibindingContributionsMade.get(bindingRequest),
+            superclassContributionsMade(bindingRequest)));
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentImplementationBuilder.java b/java/dagger/internal/codegen/ComponentImplementationBuilder.java
new file mode 100644
index 0000000..7579ac9
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentImplementationBuilder.java
@@ -0,0 +1,826 @@
+/*
+ * 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.MoreElements.getLocalAndInheritedMethods;
+import static com.google.auto.common.MoreTypes.asDeclared;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Predicates.in;
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.ComponentCreatorKind.BUILDER;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.BUILDER_METHOD;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.CANCELLATION_LISTENER_METHOD;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.COMPONENT_METHOD;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.CONSTRUCTOR;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.INITIALIZE_METHOD;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.MODIFIABLE_BINDING_METHOD;
+import static dagger.internal.codegen.ComponentImplementation.TypeSpecKind.COMPONENT_CREATOR;
+import static dagger.internal.codegen.ComponentImplementation.TypeSpecKind.SUBCOMPONENT;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.CodeBlocks.parameterNames;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.producers.CancellationPolicy.Propagation.PROPAGATE;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PROTECTED;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.auto.common.MoreTypes;
+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.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.Sets;
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.ComponentDefinitionType;
+import dagger.internal.Preconditions;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.ComponentImplementation.ConfigureInitializationMethod;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.AnnotationSpecs;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import dagger.producers.internal.CancellationListener;
+import dagger.producers.internal.Producers;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.DeclaredType;
+
+/** A builder of {@link ComponentImplementation}s. */
+abstract class ComponentImplementationBuilder {
+  private static final String MAY_INTERRUPT_IF_RUNNING = "mayInterruptIfRunning";
+
+  /**
+   * How many statements per {@code initialize()} or {@code onProducerFutureCancelled()} method
+   * before they get partitioned.
+   */
+  private static final int STATEMENTS_PER_METHOD = 100;
+
+  private static final String CANCELLATION_LISTENER_METHOD_NAME = "onProducerFutureCancelled";
+
+  // TODO(ronshapiro): replace this with composition instead of inheritance so we don't have
+  // non-final fields
+  @Inject BindingGraph graph;
+  @Inject ComponentBindingExpressions bindingExpressions;
+  @Inject ComponentRequirementExpressions componentRequirementExpressions;
+  @Inject ComponentImplementation componentImplementation;
+  @Inject ComponentCreatorImplementationFactory componentCreatorImplementationFactory;
+  @Inject DaggerTypes types;
+  @Inject DaggerElements elements;
+  @Inject CompilerOptions compilerOptions;
+  @Inject ComponentImplementationFactory componentImplementationFactory;
+  @Inject TopLevelImplementationComponent topLevelImplementationComponent;
+  private boolean done;
+
+  /**
+   * Returns a {@link ComponentImplementation} for this component. This is only intended to be
+   * called once (and will throw on successive invocations). If the component must be regenerated,
+   * use a new instance.
+   */
+  final ComponentImplementation build() {
+    checkState(
+        !done,
+        "ComponentImplementationBuilder has already built the ComponentImplementation for [%s].",
+        componentImplementation.name());
+    setSupertype();
+    componentImplementation.setCreatorImplementation(
+        componentCreatorImplementationFactory.create(
+            componentImplementation, Optional.of(componentImplementation.graph())));
+    componentImplementation
+        .creatorImplementation()
+        .map(ComponentCreatorImplementation::spec)
+        .ifPresent(this::addCreatorClass);
+
+    getLocalAndInheritedMethods(graph.componentTypeElement(), types, elements)
+        .forEach(method -> componentImplementation.claimMethodName(method.getSimpleName()));
+    componentImplementation
+        .superclassImplementation()
+        .ifPresent(
+            superclassImplementation -> {
+              superclassImplementation
+                  .getAllModifiableMethodNames()
+                  .forEach(componentImplementation::claimMethodName);
+            });
+
+    addFactoryMethods();
+    addInterfaceMethods();
+    addChildComponents();
+    implementModifiableModuleMethods();
+
+    addConstructorAndInitializationMethods();
+
+    if (graph.componentDescriptor().isProduction()) {
+      addCancellationListenerImplementation();
+    }
+
+    if (componentImplementation.isAbstract()
+        && !componentImplementation.baseImplementation().isPresent()) {
+      componentImplementation.addAnnotation(compilerOptions.toGenerationOptionsAnnotation());
+    }
+
+    if (componentImplementation.shouldEmitModifiableMetadataAnnotations()) {
+      componentImplementation.addAnnotation(
+          AnnotationSpec.builder(ComponentDefinitionType.class)
+              .addMember("value", "$T.class", graph.componentTypeElement())
+              .build());
+    }
+
+    done = true;
+    return componentImplementation;
+  }
+
+  /** Set the supertype for this generated class. */
+  private void setSupertype() {
+    if (componentImplementation.superclassImplementation().isPresent()) {
+      componentImplementation.addSuperclass(
+          componentImplementation.superclassImplementation().get().name());
+    } else {
+      componentImplementation.addSupertype(graph.componentTypeElement());
+    }
+  }
+
+  /**
+   * Adds {@code creator} as a nested creator class. Root components and subcomponents will nest
+   * this in different classes.
+   */
+  protected abstract void addCreatorClass(TypeSpec creator);
+
+  /** Adds component factory methods. */
+  protected abstract void addFactoryMethods();
+
+  protected void addInterfaceMethods() {
+    // Each component method may have been declared by several supertypes. We want to implement
+    // only one method for each distinct signature.
+    ImmutableListMultimap<MethodSignature, ComponentMethodDescriptor> componentMethodsBySignature =
+        Multimaps.index(graph.componentDescriptor().entryPointMethods(), this::getMethodSignature);
+    for (List<ComponentMethodDescriptor> methodsWithSameSignature :
+        Multimaps.asMap(componentMethodsBySignature).values()) {
+      ComponentMethodDescriptor anyOneMethod = methodsWithSameSignature.stream().findAny().get();
+      MethodSpec methodSpec = bindingExpressions.getComponentMethod(anyOneMethod);
+
+      if (compilerOptions.aheadOfTimeSubcomponents()) {
+        addPossiblyModifiableInterfaceMethod(anyOneMethod, methodSpec);
+      } else {
+        componentImplementation.addMethod(COMPONENT_METHOD, methodSpec);
+      }
+    }
+  }
+
+  /**
+   * Adds a component interface method in ahead-of-time subcomponents mode. If the binding that
+   * implements the method is modifiable, registers the method.
+   */
+  private void addPossiblyModifiableInterfaceMethod(
+      ComponentMethodDescriptor methodDescriptor, MethodSpec implementedComponentMethod) {
+    if (methodDescriptor.dependencyRequest().isPresent()
+        && componentImplementation
+            .getModifiableBindingMethod(bindingRequest(methodDescriptor.dependencyRequest().get()))
+            .isPresent()) {
+      // If there are multiple component methods that are modifiable and for the same binding
+      // request, implement all but one in the base implementation to delegate to the one that
+      // will remain (and be registered) modifiable
+      checkState(componentImplementation.isAbstract() && !componentImplementation.isNested());
+      componentImplementation.addMethod(
+          COMPONENT_METHOD, implementedComponentMethod.toBuilder().addModifiers(FINAL).build());
+    } else {
+      // TODO(b/117833324): Can this class be the one to interface with ComponentImplementation
+      // instead of having it go through ModifiableBindingExpressions?
+      bindingExpressions
+          .modifiableBindingExpressions()
+          .addPossiblyModifiableComponentMethod(methodDescriptor, implementedComponentMethod);
+    }
+  }
+
+  private void addCancellationListenerImplementation() {
+    componentImplementation.addSupertype(elements.getTypeElement(CancellationListener.class));
+    componentImplementation.claimMethodName(CANCELLATION_LISTENER_METHOD_NAME);
+
+    ImmutableList<ParameterSpec> parameters =
+        ImmutableList.of(ParameterSpec.builder(boolean.class, MAY_INTERRUPT_IF_RUNNING).build());
+
+    MethodSpec.Builder methodBuilder =
+        methodBuilder(CANCELLATION_LISTENER_METHOD_NAME)
+            .addModifiers(PUBLIC)
+            .addAnnotation(Override.class)
+            .addParameters(parameters);
+    if (componentImplementation.superclassImplementation().isPresent()) {
+      methodBuilder.addStatement(
+          "super.$L($L)", CANCELLATION_LISTENER_METHOD_NAME, MAY_INTERRUPT_IF_RUNNING);
+    }
+
+    ImmutableList<CodeBlock> cancellationStatements = cancellationStatements();
+
+    if (cancellationStatements.size() < STATEMENTS_PER_METHOD) {
+      methodBuilder.addCode(CodeBlocks.concat(cancellationStatements)).build();
+    } else {
+      ImmutableList<MethodSpec> cancelProducersMethods =
+          createPartitionedMethods(
+              "cancelProducers",
+              parameters,
+              cancellationStatements,
+              methodName -> methodBuilder(methodName).addModifiers(PRIVATE));
+      for (MethodSpec cancelProducersMethod : cancelProducersMethods) {
+        methodBuilder.addStatement("$N($L)", cancelProducersMethod, MAY_INTERRUPT_IF_RUNNING);
+        componentImplementation.addMethod(CANCELLATION_LISTENER_METHOD, cancelProducersMethod);
+      }
+    }
+
+    Optional<CodeBlock> cancelParentStatement = cancelParentStatement();
+    cancelParentStatement.ifPresent(methodBuilder::addCode);
+
+    if (cancellationStatements.isEmpty()
+        && !cancelParentStatement.isPresent()
+        && componentImplementation.superclassImplementation().isPresent()) {
+      // Partial child implementations that have no new cancellations don't need to override
+      // the method just to call super().
+      return;
+    }
+
+    componentImplementation.addMethod(CANCELLATION_LISTENER_METHOD, methodBuilder.build());
+  }
+
+  private ImmutableList<CodeBlock> cancellationStatements() {
+    // Reversing should order cancellations starting from entry points and going down to leaves
+    // rather than the other way around. This shouldn't really matter but seems *slightly*
+    // preferable because:
+    // When a future that another future depends on is cancelled, that cancellation will propagate
+    // up the future graph toward the entry point. Cancelling in reverse order should ensure that
+    // everything that depends on a particular node has already been cancelled when that node is
+    // cancelled, so there's no need to propagate. Otherwise, when we cancel a leaf node, it might
+    // propagate through most of the graph, making most of the cancel calls that follow in the
+    // onProducerFutureCancelled method do nothing.
+    ImmutableList<Key> cancellationKeys =
+        componentImplementation.getCancellableProducerKeys().reverse();
+
+    ImmutableList.Builder<CodeBlock> cancellationStatements = ImmutableList.builder();
+    for (Key cancellationKey : cancellationKeys) {
+      cancellationStatements.add(
+          CodeBlock.of(
+              "$T.cancel($L, $N);",
+              Producers.class,
+              bindingExpressions
+                  .getDependencyExpression(
+                      bindingRequest(cancellationKey, FrameworkType.PRODUCER_NODE),
+                      componentImplementation.name())
+                  .codeBlock(),
+              MAY_INTERRUPT_IF_RUNNING));
+    }
+    return cancellationStatements.build();
+  }
+
+  protected Optional<CodeBlock> cancelParentStatement() {
+    // Returns empty by default. Overridden in subclass(es) to add a statement if and only if the
+    // component being generated is a concrete subcomponent implementation with a parent that
+    // allows cancellation to propagate to it from subcomponents.
+    return Optional.empty();
+  }
+
+  /**
+   * For final components, reimplements all modifiable module methods that may have been modified.
+   */
+  private void implementModifiableModuleMethods() {
+    if (componentImplementation.isAbstract()) {
+      return;
+    }
+    componentImplementation
+        .getAllModifiableModuleMethods()
+        .forEach(this::implementModifiableModuleMethod);
+  }
+
+  private void implementModifiableModuleMethod(ComponentRequirement module, String methodName) {
+    // TODO(b/117833324): only reimplement methods for modules that were abstract or were repeated
+    // by an ancestor component.
+    componentImplementation.addMethod(
+        MODIFIABLE_BINDING_METHOD,
+        methodBuilder(methodName)
+            .addAnnotation(Override.class)
+            .addModifiers(PROTECTED)
+            .returns(TypeName.get(module.type()))
+            .addStatement(
+                componentRequirementExpressions
+                    .getExpression(module)
+                    .getModifiableModuleMethodExpression(componentImplementation.name()))
+            .build());
+  }
+
+  private MethodSignature getMethodSignature(ComponentMethodDescriptor method) {
+    return MethodSignature.forComponentMethod(
+        method, MoreTypes.asDeclared(graph.componentTypeElement().asType()), types);
+  }
+
+  private void addChildComponents() {
+    for (BindingGraph subgraph : graph.subgraphs()) {
+      // TODO(b/117833324): Can an abstract inner subcomponent implementation be elided if it's
+      // totally empty?
+      componentImplementation.addChild(
+          subgraph.componentDescriptor(), buildChildImplementation(subgraph));
+    }
+  }
+
+  private ComponentImplementation buildChildImplementation(BindingGraph childGraph) {
+    ComponentImplementation childImplementation =
+        compilerOptions.aheadOfTimeSubcomponents()
+            ? abstractInnerSubcomponent(childGraph)
+            : concreteSubcomponent(childGraph);
+    return topLevelImplementationComponent
+        .currentImplementationSubcomponentBuilder()
+        .componentImplementation(childImplementation)
+        .bindingGraph(childGraph)
+        .parentBuilder(Optional.of(this))
+        .parentBindingExpressions(Optional.of(bindingExpressions))
+        .parentRequirementExpressions(Optional.of(componentRequirementExpressions))
+        .build()
+        .subcomponentBuilder()
+        .build();
+  }
+
+  /** Creates an inner abstract subcomponent implementation. */
+  private ComponentImplementation abstractInnerSubcomponent(BindingGraph childGraph) {
+    return componentImplementation.childComponentImplementation(
+        childGraph,
+        Optional.of(
+            componentImplementationFactory.findChildSuperclassImplementation(
+                childGraph.componentDescriptor(), componentImplementation)),
+        PROTECTED,
+        componentImplementation.isAbstract() ? ABSTRACT : FINAL);
+  }
+
+  /** Creates a concrete inner subcomponent implementation. */
+  private ComponentImplementation concreteSubcomponent(BindingGraph childGraph) {
+    return componentImplementation.childComponentImplementation(
+        childGraph,
+        Optional.empty(), // superclassImplementation
+        PRIVATE,
+        FINAL);
+  }
+
+  /** Creates and adds the constructor and methods needed for initializing the component. */
+  private void addConstructorAndInitializationMethods() {
+    MethodSpec.Builder constructor = componentConstructorBuilder();
+    if (!componentImplementation.isAbstract()) {
+      implementInitializationMethod(constructor, initializationParameters());
+    } else if (componentImplementation.hasInitializations()) {
+      addConfigureInitializationMethod();
+    }
+    componentImplementation.addMethod(CONSTRUCTOR, constructor.build());
+  }
+
+  /** Returns a builder for the component's constructor. */
+  private MethodSpec.Builder componentConstructorBuilder() {
+    return constructorBuilder()
+            .addModifiers(componentImplementation.isAbstract() ? PROTECTED : PRIVATE);
+  }
+
+  /** Adds parameters and code to the given {@code initializationMethod}. */
+  private void implementInitializationMethod(
+      MethodSpec.Builder initializationMethod,
+      ImmutableMap<ComponentRequirement, ParameterSpec> initializationParameters) {
+    initializationMethod.addParameters(initializationParameters.values());
+    initializationMethod.addCode(
+        CodeBlocks.concat(componentImplementation.getComponentRequirementInitializations()));
+    componentImplementation
+        .superConfigureInitializationMethod()
+        .ifPresent(
+            superConfigureInitializationMethod ->
+                addSuperConfigureInitializationCall(
+                    initializationMethod,
+                    initializationParameters,
+                    superConfigureInitializationMethod));
+    addInitializeMethods(initializationMethod, initializationParameters.values().asList());
+  }
+
+  /** Creates and adds a {@code configureInitializatoin} method to the component. */
+  private void addConfigureInitializationMethod() {
+    MethodSpec.Builder method = configureInitializationMethodBuilder();
+    ImmutableMap<ComponentRequirement, ParameterSpec> parameters = initializationParameters();
+    implementInitializationMethod(method, parameters);
+    componentImplementation.setConfigureInitializationMethod(
+        ConfigureInitializationMethod.create(method.build(), parameters.keySet()));
+  }
+
+  /** Returns a builder for the component's {@code configureInitialization} method. */
+  private MethodSpec.Builder configureInitializationMethodBuilder() {
+    String methodName = componentImplementation.getUniqueMethodName("configureInitialization");
+    MethodSpec.Builder configureInitialization = methodBuilder(methodName).addModifiers(PROTECTED);
+    if (overridesSuperclassConfigureInitialization(configureInitialization.build())) {
+      configureInitialization.addAnnotation(Override.class);
+    }
+    return configureInitialization;
+  }
+
+  /**
+   * Returns whether or not the given method overrides a configureInitialization method from a
+   * superclass.
+   */
+  private boolean overridesSuperclassConfigureInitialization(MethodSpec method) {
+    for (Optional<ComponentImplementation> currentSuperImplementation =
+            componentImplementation.superclassImplementation();
+        currentSuperImplementation.isPresent();
+        currentSuperImplementation = currentSuperImplementation.get().superclassImplementation()) {
+      Optional<MethodSpec> superConfigureInitializationMethod =
+          currentSuperImplementation.get().configureInitializationMethod().map(m -> m.spec());
+      if (superConfigureInitializationMethod
+          .filter(superMethod -> haveSameSignature(method, superMethod))
+          .isPresent()) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  /** Returns whether or not methods {@code a} and {@code b} have the same signature. */
+  private boolean haveSameSignature(MethodSpec a, MethodSpec b) {
+    return a.name.equals(b.name) && types(a.parameters).equals(types(b.parameters));
+  }
+
+  private ImmutableList<TypeName> types(List<ParameterSpec> parameters) {
+    return parameters.stream().map(parameter -> parameter.type).collect(toImmutableList());
+  }
+
+  /**
+   * Adds a call to the superclass's {@code configureInitialization} method to the given {@code
+   * callingMethod}.
+   */
+  private void addSuperConfigureInitializationCall(
+      MethodSpec.Builder callingMethod,
+      ImmutableMap<ComponentRequirement, ParameterSpec> parameters,
+      ConfigureInitializationMethod superConfigureInitializationMethod) {
+    // This component's constructor may not have all of the parameters that the superclass's
+    // configureInitialization method takes, because the superclass configureInitialization method
+    // necessarily accepts things that it can't know whether will be needed or not. If they aren't
+    // needed (as is the case when the constructor doesn't have a parameter for the module), just
+    // pass null to super.configureInitialization for that parameter; it won't be used.
+    CodeBlock args =
+        superConfigureInitializationMethod.parameters().stream()
+            .map(
+                requirement ->
+                    parameters.containsKey(requirement)
+                        ? CodeBlock.of("$N", parameters.get(requirement))
+                        : CodeBlock.of("null"))
+            .collect(toParametersCodeBlock());
+
+    String qualifier =
+        haveSameSignature(callingMethod.build(), superConfigureInitializationMethod.spec())
+            ? "super."
+            : "";
+    callingMethod.addStatement(
+        qualifier + "$N($L)", superConfigureInitializationMethod.spec(), args);
+  }
+
+  /**
+   * Adds any necessary {@code initialize} methods to the component and adds calls to them to the
+   * given {@code callingMethod}.
+   */
+  private void addInitializeMethods(
+      MethodSpec.Builder callingMethod, ImmutableList<ParameterSpec> parameters) {
+    // TODO(cgdecker): It's not the case that each initialize() method has need for all of the
+    // given parameters. In some cases, those parameters may have already been assigned to fields
+    // which could be referenced instead. In other cases, an initialize method may just not need
+    // some of the parameters because the set of initializations in that partition does not
+    // include any reference to them. Right now, the Dagger code has no way of getting that
+    // information because, among other things, componentImplementation.getImplementations() just
+    // returns a bunch of CodeBlocks with no semantic information. Additionally, we may not know
+    // yet whether a field will end up needing to be created for a specific requirement, and we
+    // don't want to create a field that ends up only being used during initialization.
+    CodeBlock args = parameterNames(parameters);
+    ImmutableList<MethodSpec> methods =
+        createPartitionedMethods(
+            "initialize",
+            makeFinal(parameters),
+            componentImplementation.getInitializations(),
+            methodName ->
+                methodBuilder(methodName)
+                    .addModifiers(PRIVATE)
+                    /* TODO(gak): Strictly speaking, we only need the suppression here if we are
+                     * also initializing a raw field in this method, but the structure of this
+                     * code makes it awkward to pass that bit through.  This will be cleaned up
+                     * when we no longer separate fields and initialization as we do now. */
+                    .addAnnotation(AnnotationSpecs.suppressWarnings(UNCHECKED)));
+    for (MethodSpec method : methods) {
+      callingMethod.addStatement("$N($L)", method, args);
+      componentImplementation.addMethod(INITIALIZE_METHOD, method);
+    }
+  }
+
+  /**
+   * Creates one or more methods, all taking the given {@code parameters}, which partition the given
+   * list of {@code statements} among themselves such that no method has more than {@code
+   * STATEMENTS_PER_METHOD} statements in it and such that the returned methods, if called in order,
+   * will execute the {@code statements} in the given order.
+   */
+  private ImmutableList<MethodSpec> createPartitionedMethods(
+      String methodName,
+      Iterable<ParameterSpec> parameters,
+      List<CodeBlock> statements,
+      Function<String, MethodSpec.Builder> methodBuilderCreator) {
+    return Lists.partition(statements, STATEMENTS_PER_METHOD).stream()
+        .map(
+            partition ->
+                methodBuilderCreator
+                    .apply(componentImplementation.getUniqueMethodName(methodName))
+                    .addParameters(parameters)
+                    .addCode(CodeBlocks.concat(partition))
+                    .build())
+        .collect(toImmutableList());
+  }
+
+  /** Returns the given parameters with a final modifier added. */
+  private final ImmutableList<ParameterSpec> makeFinal(Collection<ParameterSpec> parameters) {
+    return parameters.stream()
+        .map(param -> param.toBuilder().addModifiers(FINAL).build())
+        .collect(toImmutableList());
+  }
+
+  /**
+   * Returns the parameters for the constructor or {@code configureInitilization} method as a map
+   * from the requirement the parameter fulfills to the spec for the parameter.
+   */
+  private final ImmutableMap<ComponentRequirement, ParameterSpec> initializationParameters() {
+    Map<ComponentRequirement, ParameterSpec> parameters;
+    if (componentImplementation.componentDescriptor().hasCreator()) {
+      parameters =
+          Maps.toMap(componentImplementation.requirements(), ComponentRequirement::toParameterSpec);
+    } else if (componentImplementation.isAbstract() && componentImplementation.isNested()) {
+      // If we're generating an abstract inner subcomponent, then we are not implementing module
+      // instance bindings and have no need for factory method parameters.
+      parameters = ImmutableMap.of();
+    } else if (graph.factoryMethod().isPresent()) {
+      parameters = getFactoryMethodParameters(graph);
+    } else if (componentImplementation.isAbstract()) {
+      // If we're generating an abstract base implementation of a subcomponent it's acceptable to
+      // have neither a creator nor factory method.
+      parameters = ImmutableMap.of();
+    } else {
+      throw new AssertionError(
+          "Expected either a component creator or factory method but found neither.");
+    }
+
+    if (componentImplementation.isAbstract()) {
+      parameters = Maps.filterKeys(parameters, in(configureInitializationRequirements()));
+    }
+    return renameParameters(parameters);
+  }
+
+  /**
+   * Returns the set of requirements for the configureInitialization method: the parameters that are
+   * needed either for initializing a component requirement field or for calling the superclass's
+   * {@code configureInitialization} method.
+   */
+  private ImmutableSet<ComponentRequirement> configureInitializationRequirements() {
+    ImmutableSet<ComponentRequirement> initializationParameters =
+        componentImplementation.getComponentRequirementParameters();
+    ImmutableSet<ComponentRequirement> superConfigureInitializationRequirements =
+        componentImplementation
+            .superConfigureInitializationMethod()
+            .map(ConfigureInitializationMethod::parameters)
+            .orElse(ImmutableSet.of());
+    return Sets.union(initializationParameters, superConfigureInitializationRequirements)
+        .immutableCopy();
+  }
+
+  /**
+   * Renames the given parameters to guarantee their names do not conflict with fields in the
+   * component to ensure that a parameter is never referenced where a reference to a field was
+   * intended.
+   */
+  // TODO(cgdecker): This is a bit kludgy; it would be preferable to either qualify the field
+  // references with "this." or "super." when needed to disambiguate between field and parameter,
+  // but that would require more context than is currently available when the code referencing a
+  // field is generated.
+  private ImmutableMap<ComponentRequirement, ParameterSpec> renameParameters(
+      Map<ComponentRequirement, ParameterSpec> parameters) {
+    return ImmutableMap.copyOf(
+        Maps.transformEntries(
+            parameters,
+            (requirement, parameter) ->
+                renameParameter(
+                    parameter,
+                    componentImplementation.getParameterName(requirement, parameter.name))));
+  }
+
+  private ParameterSpec renameParameter(ParameterSpec parameter, String newName) {
+    return ParameterSpec.builder(parameter.type, newName)
+        .addAnnotations(parameter.annotations)
+        .addModifiers(parameter.modifiers)
+        .build();
+  }
+
+  /** Builds a root component implementation. */
+  static final class RootComponentImplementationBuilder extends ComponentImplementationBuilder {
+    @Inject
+    RootComponentImplementationBuilder(ComponentImplementation componentImplementation) {
+      checkArgument(!componentImplementation.superclassImplementation().isPresent());
+    }
+
+    @Override
+    protected void addCreatorClass(TypeSpec creator) {
+      componentImplementation.addType(COMPONENT_CREATOR, creator);
+    }
+
+    @Override
+    protected void addFactoryMethods() {
+      // Top-level components have a static method that returns a builder or factory for the
+      // component. If the user defined a @Component.Builder or @Component.Factory, an
+      // implementation of their type is returned. Otherwise, an autogenerated Builder type is
+      // returned.
+      // TODO(cgdecker): Replace this abomination with a small class?
+      // Better yet, change things so that an autogenerated builder type has a descriptor of sorts
+      // just like a user-defined creator type.
+      ComponentCreatorKind creatorKind;
+      ClassName creatorType;
+      String factoryMethodName;
+      boolean noArgFactoryMethod;
+      if (creatorDescriptor().isPresent()) {
+        ComponentCreatorDescriptor descriptor = creatorDescriptor().get();
+        creatorKind = descriptor.kind();
+        creatorType = ClassName.get(descriptor.typeElement());
+        factoryMethodName = descriptor.factoryMethod().getSimpleName().toString();
+        noArgFactoryMethod = descriptor.factoryParameters().isEmpty();
+      } else {
+        creatorKind = BUILDER;
+        creatorType = componentCreatorName();
+        factoryMethodName = "build";
+        noArgFactoryMethod = true;
+      }
+
+      MethodSpec creatorFactoryMethod =
+          methodBuilder(creatorKind.methodName())
+              .addModifiers(PUBLIC, STATIC)
+              .returns(creatorType)
+              .addStatement("return new $T()", componentCreatorName())
+              .build();
+      componentImplementation.addMethod(BUILDER_METHOD, creatorFactoryMethod);
+      if (noArgFactoryMethod && canInstantiateAllRequirements()) {
+        componentImplementation.addMethod(
+            BUILDER_METHOD,
+            methodBuilder("create")
+                .returns(ClassName.get(super.graph.componentTypeElement()))
+                .addModifiers(PUBLIC, STATIC)
+                .addStatement(
+                    "return new $L().$L()", creatorKind.typeName(), factoryMethodName)
+                .build());
+      }
+    }
+
+    private Optional<ComponentCreatorDescriptor> creatorDescriptor() {
+      return graph.componentDescriptor().creatorDescriptor();
+    }
+
+    /** {@code true} if all of the graph's required dependencies can be automatically constructed */
+    private boolean canInstantiateAllRequirements() {
+      return !Iterables.any(
+          graph.componentRequirements(),
+          dependency -> dependency.requiresAPassedInstance(elements, types));
+    }
+
+    private ClassName componentCreatorName() {
+      return componentImplementation.creatorImplementation().get().name();
+    }
+  }
+
+  /**
+   * Builds a subcomponent implementation. If generating ahead-of-time subcomponents, this may be an
+   * abstract base class implementation, an abstract inner implementation, or a concrete
+   * implementation that extends an abstract base implementation. Otherwise it represents a private,
+   * inner, concrete, final implementation of a subcomponent which extends a user defined type.
+   */
+  static final class SubcomponentImplementationBuilder extends ComponentImplementationBuilder {
+    final Optional<ComponentImplementationBuilder> parent;
+
+    @Inject
+    SubcomponentImplementationBuilder(
+        @ParentComponent Optional<ComponentImplementationBuilder> parent) {
+      this.parent = parent;
+    }
+
+    @Override
+    protected void addCreatorClass(TypeSpec creator) {
+      if (parent.isPresent()) {
+        // In an inner implementation of a subcomponent the creator is a peer class.
+        parent.get().componentImplementation.addType(SUBCOMPONENT, creator);
+      } else {
+        componentImplementation.addType(SUBCOMPONENT, creator);
+      }
+    }
+
+    @Override
+    protected void addFactoryMethods() {
+      // Only construct instances of subcomponents that have concrete implementations.
+      if (!componentImplementation.isAbstract()) {
+        // Use the parent's factory method to create this subcomponent if the
+        // subcomponent was not added via {@link dagger.Module#subcomponents()}.
+        graph.factoryMethod().ifPresent(this::createSubcomponentFactoryMethod);
+      }
+    }
+
+    private void createSubcomponentFactoryMethod(ExecutableElement factoryMethod) {
+      checkState(parent.isPresent());
+
+      Collection<ParameterSpec> params = getFactoryMethodParameters(graph).values();
+      MethodSpec.Builder method = MethodSpec.overriding(factoryMethod, parentType(), types);
+      params.forEach(
+          param -> method.addStatement("$T.checkNotNull($N)", Preconditions.class, param));
+      method.addStatement(
+          "return new $T($L)", componentImplementation.name(), parameterNames(params));
+
+      parent.get().componentImplementation.addMethod(COMPONENT_METHOD, method.build());
+    }
+
+    private DeclaredType parentType() {
+      return asDeclared(parent.get().graph.componentTypeElement().asType());
+    }
+
+    @Override
+    protected void addInterfaceMethods() {
+      if (componentImplementation.superclassImplementation().isPresent()) {
+        // Since we're overriding a subcomponent implementation we add to its implementation given
+        // an expanded binding graph.
+
+        ComponentImplementation superclassImplementation =
+            componentImplementation.superclassImplementation().get();
+        for (ModifiableBindingMethod superclassModifiableBindingMethod :
+            superclassImplementation.getModifiableBindingMethods().values()) {
+          bindingExpressions
+              .modifiableBindingExpressions()
+              .possiblyReimplementedMethod(superclassModifiableBindingMethod)
+              .ifPresent(componentImplementation::addImplementedModifiableBindingMethod);
+        }
+      } else {
+        super.addInterfaceMethods();
+      }
+    }
+
+    @Override
+    protected Optional<CodeBlock> cancelParentStatement() {
+      if (!shouldPropagateCancellationToParent()) {
+        return Optional.empty();
+      }
+      return Optional.of(
+          CodeBlock.builder()
+              .addStatement(
+                  "$T.this.$N($N)",
+                  parent.get().componentImplementation.name(),
+                  CANCELLATION_LISTENER_METHOD_NAME,
+                  MAY_INTERRUPT_IF_RUNNING)
+              .build());
+    }
+
+    private boolean shouldPropagateCancellationToParent() {
+      return parent.isPresent()
+          && parent
+              .get()
+              .componentImplementation
+              .componentDescriptor()
+              .cancellationPolicy()
+              .map(policy -> policy.fromSubcomponents().equals(PROPAGATE))
+              .orElse(false);
+    }
+  }
+
+  /**
+   * Returns the map of {@link ComponentRequirement}s to {@link ParameterSpec}s for the
+   * given graph's factory method.
+   */
+  private static Map<ComponentRequirement, ParameterSpec> getFactoryMethodParameters(
+      BindingGraph graph) {
+    return Maps.transformValues(graph.factoryMethodParameters(), ParameterSpec::get);
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentImplementationFactory.java b/java/dagger/internal/codegen/ComponentImplementationFactory.java
new file mode 100644
index 0000000..9578ece
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentImplementationFactory.java
@@ -0,0 +1,162 @@
+/*
+ * 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.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.ComponentGenerator.componentName;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static javax.tools.Diagnostic.Kind.WARNING;
+
+import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.serialization.ProtoSerialization.InconsistentSerializedProtoException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.annotation.processing.Messager;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.lang.model.element.TypeElement;
+
+/** Factory for {@link ComponentImplementation}s. */
+@Singleton
+final class ComponentImplementationFactory implements ClearableCache {
+  private final Map<TypeElement, ComponentImplementation> topLevelComponentCache = new HashMap<>();
+  private final KeyFactory keyFactory;
+  private final CompilerOptions compilerOptions;
+  private final BindingGraphFactory bindingGraphFactory;
+  private final TopLevelImplementationComponent.Builder topLevelImplementationComponentBuilder;
+  private final DeserializedComponentImplementationBuilder
+      deserializedComponentImplementationBuilder;
+  private final DaggerElements elements;
+  private final Messager messager;
+
+  @Inject
+  ComponentImplementationFactory(
+      KeyFactory keyFactory,
+      CompilerOptions compilerOptions,
+      BindingGraphFactory bindingGraphFactory,
+      TopLevelImplementationComponent.Builder topLevelImplementationComponentBuilder,
+      DeserializedComponentImplementationBuilder deserializedComponentImplementationBuilder,
+      DaggerElements elements,
+      Messager messager) {
+    this.keyFactory = keyFactory;
+    this.compilerOptions = compilerOptions;
+    this.bindingGraphFactory = bindingGraphFactory;
+    this.topLevelImplementationComponentBuilder = topLevelImplementationComponentBuilder;
+    this.deserializedComponentImplementationBuilder = deserializedComponentImplementationBuilder;
+    this.elements = elements;
+    this.messager = messager;
+  }
+
+  /**
+   * Returns a top-level (non-nested) component implementation for a binding graph.
+   *
+   * @throws IllegalStateException if the binding graph is for a subcomponent and
+   *     ahead-of-time-subcomponents mode is not enabled
+   */
+  ComponentImplementation createComponentImplementation(BindingGraph bindingGraph) {
+    return reentrantComputeIfAbsent(
+        topLevelComponentCache,
+        bindingGraph.componentTypeElement(),
+        component -> createComponentImplementationUncached(bindingGraph));
+  }
+
+  private ComponentImplementation createComponentImplementationUncached(BindingGraph bindingGraph) {
+    ComponentImplementation componentImplementation =
+        ComponentImplementation.topLevelComponentImplementation(
+            bindingGraph,
+            componentName(bindingGraph.componentTypeElement()),
+            new SubcomponentNames(bindingGraph, keyFactory),
+            compilerOptions);
+
+    // TODO(dpb): explore using optional bindings for the "parent" bindings
+    CurrentImplementationSubcomponent currentImplementationSubcomponent =
+        topLevelImplementationComponentBuilder
+            .topLevelComponent(componentImplementation)
+            .build()
+            .currentImplementationSubcomponentBuilder()
+            .componentImplementation(componentImplementation)
+            .bindingGraph(bindingGraph)
+            .parentBuilder(Optional.empty())
+            .parentBindingExpressions(Optional.empty())
+            .parentRequirementExpressions(Optional.empty())
+            .build();
+
+    if (componentImplementation.isAbstract()) {
+      checkState(
+          compilerOptions.aheadOfTimeSubcomponents(),
+          "Calling 'componentImplementation()' on %s when not generating ahead-of-time "
+              + "subcomponents.",
+          bindingGraph.componentTypeElement());
+      return currentImplementationSubcomponent.subcomponentBuilder().build();
+    } else {
+      return currentImplementationSubcomponent.rootComponentBuilder().build();
+    }
+  }
+
+  /** Returns the superclass of the child nested within a superclass of the parent component. */
+  ComponentImplementation findChildSuperclassImplementation(
+      ComponentDescriptor child, ComponentImplementation parentImplementation) {
+    // If the current component has superclass implementations, a superclass may contain a
+    // reference to the child. Traverse this component's superimplementation hierarchy looking for
+    // the child's implementation. The child superclass implementation may not be present in the
+    // direct superclass implementations if the subcomponent builder was previously a pruned
+    // binding.
+    for (Optional<ComponentImplementation> parent = parentImplementation.superclassImplementation();
+        parent.isPresent();
+        parent = parent.get().superclassImplementation()) {
+      Optional<ComponentImplementation> superclass = parent.get().childImplementation(child);
+      if (superclass.isPresent()) {
+        return superclass.get();
+      }
+    }
+
+    if (compilerOptions.emitModifiableMetadataAnnotations()) {
+      ClassName childSuperclassName = componentName(child.typeElement());
+      TypeElement generatedChildSuperclassImplementation =
+          elements.getTypeElement(childSuperclassName);
+      if (generatedChildSuperclassImplementation != null) {
+        try {
+          return deserializedComponentImplementationBuilder.create(
+              child, generatedChildSuperclassImplementation);
+        } catch (InconsistentSerializedProtoException e) {
+          messager.printMessage(
+              WARNING,
+              String.format(
+                  "%s was compiled with a different version of Dagger than the version in this "
+                      + "compilation. To ensure the validity of Dagger's generated code, compile "
+                      + "all Dagger code with the same version.",
+                  child.typeElement().getQualifiedName()));
+        }
+      } else if (compilerOptions.forceUseSerializedComponentImplementations()) {
+        throw new TypeNotPresentException(childSuperclassName.toString(), null);
+      }
+    }
+
+    // Otherwise, the superclass implementation is top-level, so we must recreate the
+    // implementation object for the base implementation of the child by truncating the binding
+    // graph at the child.
+    BindingGraph truncatedBindingGraph = bindingGraphFactory.create(child, false);
+    return createComponentImplementation(truncatedBindingGraph);
+  }
+
+  @Override
+  public void clearCache() {
+    topLevelComponentCache.clear();
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java b/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java
new file mode 100644
index 0000000..e98d595
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.javapoet.Expression;
+
+/** A binding expression for the instance of the component itself, i.e. {@code this}. */
+final class ComponentInstanceBindingExpression extends SimpleInvocationBindingExpression {
+  private final ClassName componentName;
+  private final ContributionBinding binding;
+
+  ComponentInstanceBindingExpression(ResolvedBindings resolvedBindings, ClassName componentName) {
+    super(resolvedBindings);
+    this.componentName = componentName;
+    this.binding = resolvedBindings.contributionBinding();
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    return Expression.create(
+        binding.key().type(),
+        componentName.equals(requestingClass)
+            ? CodeBlock.of("this")
+            : CodeBlock.of("$T.this", componentName));
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentKind.java b/java/dagger/internal/codegen/ComponentKind.java
new file mode 100644
index 0000000..8e5b9ba
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentKind.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2014 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.MoreElements.isAnnotationPresent;
+import static com.google.common.collect.Sets.immutableEnumSet;
+import static dagger.internal.codegen.DaggerStreams.stream;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.DaggerStreams.valuesOf;
+import static java.util.EnumSet.allOf;
+
+import com.google.common.collect.ImmutableSet;
+import dagger.Component;
+import dagger.Module;
+import dagger.Subcomponent;
+import dagger.producers.ProducerModule;
+import dagger.producers.ProductionComponent;
+import dagger.producers.ProductionSubcomponent;
+import java.lang.annotation.Annotation;
+import java.util.Optional;
+import javax.lang.model.element.TypeElement;
+
+/** Enumeration of the different kinds of components. */
+enum ComponentKind {
+  /** {@code @Component} */
+  COMPONENT(Component.class, true, false),
+
+  /** {@code @Subcomponent} */
+  SUBCOMPONENT(Subcomponent.class, false, false),
+
+  /** {@code @ProductionComponent} */
+  PRODUCTION_COMPONENT(ProductionComponent.class, true, true),
+
+  /** {@code @ProductionSubcomponent} */
+  PRODUCTION_SUBCOMPONENT(ProductionSubcomponent.class, false, true),
+
+  /**
+   * Kind for a descriptor that was generated from a {@link Module} instead of a component type in
+   * order to validate the module's bindings.
+   */
+  MODULE(Module.class, true, false),
+
+  /**
+   * Kind for a descriptor was generated from a {@link ProducerModule} instead of a component type
+   * in order to validate the module's bindings.
+   */
+  PRODUCER_MODULE(ProducerModule.class, true, true),
+  ;
+
+  private static final ImmutableSet<ComponentKind> ROOT_COMPONENT_KINDS =
+      valuesOf(ComponentKind.class)
+          .filter(kind -> !kind.isForModuleValidation())
+          .filter(kind -> kind.isRoot())
+          .collect(toImmutableSet());
+
+  private static final ImmutableSet<ComponentKind> SUBCOMPONENT_KINDS =
+      valuesOf(ComponentKind.class)
+          .filter(kind -> !kind.isForModuleValidation())
+          .filter(kind -> !kind.isRoot())
+          .collect(toImmutableSet());
+
+  /** Returns the set of kinds for root components. */
+  static ImmutableSet<ComponentKind> rootComponentKinds() {
+    return ROOT_COMPONENT_KINDS;
+  }
+
+  /** Returns the set of kinds for subcomponents. */
+  static ImmutableSet<ComponentKind> subcomponentKinds() {
+    return SUBCOMPONENT_KINDS;
+  }
+
+  /** Returns the annotations for components of the given kinds. */
+  static ImmutableSet<Class<? extends Annotation>> annotationsFor(Iterable<ComponentKind> kinds) {
+    return stream(kinds).map(ComponentKind::annotation).collect(toImmutableSet());
+  }
+
+  /** Returns the set of component kinds the given {@code element} has annotations for. */
+  static ImmutableSet<ComponentKind> getComponentKinds(TypeElement element) {
+    return valuesOf(ComponentKind.class)
+        .filter(kind -> isAnnotationPresent(element, kind.annotation()))
+        .collect(toImmutableSet());
+  }
+
+  /**
+   * Returns the kind of an annotated element if it is annotated with one of the {@linkplain
+   * #annotation() annotations}.
+   *
+   * @throws IllegalArgumentException if the element is annotated with more than one of the
+   *     annotations
+   */
+  static Optional<ComponentKind> forAnnotatedElement(TypeElement element) {
+    ImmutableSet<ComponentKind> kinds = getComponentKinds(element);
+    if (kinds.size() > 1) {
+      throw new IllegalArgumentException(
+          element + " cannot be annotated with more than one of " + annotationsFor(kinds));
+    }
+    return kinds.stream().findAny();
+  }
+
+  private final Class<? extends Annotation> annotation;
+  private final boolean isRoot;
+  private final boolean production;
+
+  ComponentKind(
+      Class<? extends Annotation> annotation,
+      boolean isRoot,
+      boolean production) {
+    this.annotation = annotation;
+    this.isRoot = isRoot;
+    this.production = production;
+  }
+
+  /** Returns the annotation that marks a component of this kind. */
+  Class<? extends Annotation> annotation() {
+    return annotation;
+  }
+
+  /** Returns the kinds of modules that can be used with a component of this kind. */
+  ImmutableSet<ModuleKind> legalModuleKinds() {
+    return isProducer()
+        ? immutableEnumSet(allOf(ModuleKind.class))
+        : immutableEnumSet(ModuleKind.MODULE);
+  }
+
+  /** Returns the kinds of subcomponents a component of this kind can have. */
+  ImmutableSet<ComponentKind> legalSubcomponentKinds() {
+    return isProducer()
+        ? immutableEnumSet(PRODUCTION_SUBCOMPONENT)
+        : immutableEnumSet(SUBCOMPONENT, PRODUCTION_SUBCOMPONENT);
+  }
+
+  /**
+   * Returns {@code true} if the descriptor is for a root component (not a subcomponent) or is for
+   * {@linkplain #isForModuleValidation() module-validation}.
+   */
+  boolean isRoot() {
+    return isRoot;
+  }
+
+  /** Returns true if this is a production component. */
+  boolean isProducer() {
+    return production;
+  }
+
+  /** Returns {@code true} if the descriptor is for a module in order to validate its bindings. */
+  boolean isForModuleValidation() {
+    switch (this) {
+      case MODULE:
+      case PRODUCER_MODULE:
+        return true;
+      default:
+        // fall through
+    }
+    return false;
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentMethodBindingExpression.java b/java/dagger/internal/codegen/ComponentMethodBindingExpression.java
new file mode 100644
index 0000000..7e7bbd8
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentMethodBindingExpression.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkNotNull;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A binding expression that implements and uses a component method.
+ *
+ * <p>Dependents of this binding expression will just call the component method.
+ */
+final class ComponentMethodBindingExpression extends MethodBindingExpression {
+  private final ComponentImplementation componentImplementation;
+  private final ComponentMethodDescriptor componentMethod;
+
+  ComponentMethodBindingExpression(
+      BindingRequest request,
+      ResolvedBindings resolvedBindings,
+      MethodImplementationStrategy methodImplementationStrategy,
+      BindingExpression wrappedBindingExpression,
+      ComponentImplementation componentImplementation,
+      ComponentMethodDescriptor componentMethod,
+      DaggerTypes types) {
+    super(
+        request,
+        resolvedBindings,
+        methodImplementationStrategy,
+        wrappedBindingExpression,
+        componentImplementation,
+        types);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.componentMethod = checkNotNull(componentMethod);
+  }
+
+  @Override
+  protected CodeBlock getComponentMethodImplementation(
+      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
+    // There could be several methods on the component for the same request key and kind.
+    // Only one should use the BindingMethodImplementation; the others can delegate that one. So
+    // use methodImplementation.body() only if componentMethod equals the method for this instance.
+
+    // Separately, the method might be defined on a supertype that is also a supertype of some
+    // parent component. In that case, the same ComponentMethodDescriptor will be used to add a CMBE
+    // for the parent and the child. Only the parent's should use the BindingMethodImplementation;
+    // the child's can delegate to the parent. So use methodImplementation.body() only if
+    // componentName equals the component for this instance.
+    return componentMethod.equals(this.componentMethod) && component.equals(componentImplementation)
+        ? methodBodyForComponentMethod(componentMethod)
+        : super.getComponentMethodImplementation(componentMethod, component);
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    // If a component method returns a primitive, update the expression's type which might be boxed.
+    Expression expression = super.getDependencyExpression(requestingClass);
+    TypeMirror methodReturnType = componentMethod.methodElement().getReturnType();
+    return methodReturnType.getKind().isPrimitive()
+        ? Expression.create(methodReturnType, expression.codeBlock())
+        : expression;
+  }
+
+  @Override
+  protected void addMethod() {}
+
+  @Override
+  protected String methodName() {
+    return componentMethod.methodElement().getSimpleName().toString();
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentNodeImpl.java b/java/dagger/internal/codegen/ComponentNodeImpl.java
new file mode 100644
index 0000000..3a31ec7
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentNodeImpl.java
@@ -0,0 +1,64 @@
+/*
+ * 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 dagger.internal.codegen.DaggerStreams.toImmutableSet;
+
+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 final boolean isSubcomponent() {
+    return componentDescriptor().isSubcomponent();
+  }
+
+  @Override
+  public boolean isRealComponent() {
+    return componentDescriptor().isRealComponent();
+  }
+
+  @Override
+  public final ImmutableSet<DependencyRequest> entryPoints() {
+    return componentDescriptor().entryPointMethods().stream()
+        .map(method -> method.dependencyRequest().get())
+        .collect(toImmutableSet());
+  }
+
+  @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 3125ce7..645c94f 100644
--- a/java/dagger/internal/codegen/ComponentProcessingStep.java
+++ b/java/dagger/internal/codegen/ComponentProcessingStep.java
@@ -16,30 +16,27 @@
 
 package dagger.internal.codegen;
 
-import static com.google.auto.common.MoreElements.asType;
 import static com.google.common.collect.Sets.union;
-import static dagger.internal.codegen.base.ComponentAnnotation.allComponentAnnotations;
-import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotations;
-import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotations;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.allCreatorAnnotations;
+import static dagger.internal.codegen.ComponentAnnotation.allComponentAnnotations;
+import static dagger.internal.codegen.ComponentAnnotation.rootComponentAnnotations;
+import static dagger.internal.codegen.ComponentAnnotation.subcomponentAnnotations;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.allCreatorAnnotations;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.rootComponentCreatorAnnotations;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.subcomponentCreatorAnnotations;
+import static dagger.internal.codegen.ValidationType.NONE;
 import static java.util.Collections.disjoint;
 
 import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
 import com.google.auto.common.MoreElements;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
-import dagger.internal.codegen.validation.BindingGraphValidator;
-import dagger.internal.codegen.validation.ComponentCreatorValidator;
-import dagger.internal.codegen.validation.ComponentDescriptorValidator;
-import dagger.internal.codegen.validation.ComponentValidator;
-import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
-import dagger.internal.codegen.validation.ValidationReport;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+import dagger.internal.codegen.ComponentValidator.ComponentValidationReport;
 import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Set;
 import javax.annotation.processing.Messager;
 import javax.inject.Inject;
@@ -58,7 +55,14 @@
   private final ComponentDescriptorFactory componentDescriptorFactory;
   private final BindingGraphFactory bindingGraphFactory;
   private final SourceFileGenerator<BindingGraph> componentGenerator;
+  private final BindingGraphConverter bindingGraphConverter;
   private final BindingGraphValidator bindingGraphValidator;
+  private final CompilerOptions compilerOptions;
+  private ImmutableSet<Element> subcomponentElements;
+  private ImmutableSet<Element> subcomponentCreatorElements;
+  private ImmutableMap<Element, ValidationReport<TypeElement>> creatorReportsByComponent;
+  private ImmutableMap<Element, ValidationReport<TypeElement>> creatorReportsBySubcomponent;
+  private ImmutableMap<Element, ValidationReport<TypeElement>> reportsBySubcomponent;
 
   @Inject
   ComponentProcessingStep(
@@ -69,7 +73,9 @@
       ComponentDescriptorFactory componentDescriptorFactory,
       BindingGraphFactory bindingGraphFactory,
       SourceFileGenerator<BindingGraph> componentGenerator,
-      BindingGraphValidator bindingGraphValidator) {
+      BindingGraphConverter bindingGraphConverter,
+      BindingGraphValidator bindingGraphValidator,
+      CompilerOptions compilerOptions) {
     super(MoreElements::asType);
     this.messager = messager;
     this.componentValidator = componentValidator;
@@ -78,7 +84,9 @@
     this.componentDescriptorFactory = componentDescriptorFactory;
     this.bindingGraphFactory = bindingGraphFactory;
     this.componentGenerator = componentGenerator;
+    this.bindingGraphConverter = bindingGraphConverter;
     this.bindingGraphValidator = bindingGraphValidator;
+    this.compilerOptions = compilerOptions;
   }
 
   @Override
@@ -87,6 +95,27 @@
   }
 
   @Override
+  public ImmutableSet<Element> process(
+      SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
+    subcomponentElements =
+        getElementsFromAnnotations(elementsByAnnotation, subcomponentAnnotations());
+    subcomponentCreatorElements =
+        getElementsFromAnnotations(elementsByAnnotation, subcomponentCreatorAnnotations());
+
+    ImmutableSet.Builder<Element> rejectedElements = ImmutableSet.builder();
+
+    creatorReportsByComponent =
+        processCreators(
+            getElementsFromAnnotations(elementsByAnnotation, rootComponentCreatorAnnotations()),
+            rejectedElements);
+    creatorReportsBySubcomponent = processCreators(subcomponentCreatorElements, rejectedElements);
+    reportsBySubcomponent =
+        processSubcomponents(subcomponentElements, subcomponentCreatorElements, rejectedElements);
+
+    return rejectedElements.addAll(super.process(elementsByAnnotation)).build();
+  }
+
+  @Override
   protected void process(
       TypeElement element, ImmutableSet<Class<? extends Annotation>> annotations) {
     if (!disjoint(annotations, rootComponentAnnotations())) {
@@ -95,13 +124,10 @@
     if (!disjoint(annotations, subcomponentAnnotations())) {
       processSubcomponent(element);
     }
-    if (!disjoint(annotations, allCreatorAnnotations())) {
-      processCreator(element);
-    }
   }
 
   private void processRootComponent(TypeElement component) {
-    if (!isComponentValid(component)) {
+    if (!isRootComponentValid(component)) {
       return;
     }
     ComponentDescriptor componentDescriptor =
@@ -109,47 +135,112 @@
     if (!isValid(componentDescriptor)) {
       return;
     }
-    if (!validateFullBindingGraph(componentDescriptor)) {
+    if (!isFullBindingGraphValid(componentDescriptor)) {
       return;
     }
     BindingGraph bindingGraph = bindingGraphFactory.create(componentDescriptor, false);
-    if (bindingGraphValidator.isValid(bindingGraph.topLevelBindingGraph())) {
+    if (isValid(bindingGraph)) {
       generateComponent(bindingGraph);
     }
   }
 
   private void processSubcomponent(TypeElement subcomponent) {
-    if (!isComponentValid(subcomponent)) {
+    if (!compilerOptions.aheadOfTimeSubcomponents()
+        && compilerOptions.fullBindingGraphValidationType(subcomponent).equals(NONE)) {
+      return;
+    }
+    if (!isSubcomponentValid(subcomponent)) {
       return;
     }
     ComponentDescriptor subcomponentDescriptor =
         componentDescriptorFactory.subcomponentDescriptor(subcomponent);
     // TODO(dpb): ComponentDescriptorValidator for subcomponents, as we do for root components.
-    validateFullBindingGraph(subcomponentDescriptor);
+    if (!isFullBindingGraphValid(subcomponentDescriptor)) {
+      return;
+    }
+    if (compilerOptions.aheadOfTimeSubcomponents()) {
+      BindingGraph bindingGraph = bindingGraphFactory.create(subcomponentDescriptor, false);
+      if (isValid(bindingGraph)) {
+        generateComponent(bindingGraph);
+      }
+    }
   }
 
   private void generateComponent(BindingGraph bindingGraph) {
     componentGenerator.generate(bindingGraph, messager);
   }
 
-  private void processCreator(Element creator) {
-    creatorValidator.validate(MoreElements.asType(creator)).printMessagesTo(messager);
+  static ImmutableSet<Element> getElementsFromAnnotations(
+      final SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation,
+      Set<Class<? extends Annotation>> annotations) {
+    return ImmutableSet.copyOf(
+        Multimaps.filterKeys(elementsByAnnotation, Predicates.in(annotations)).values());
   }
 
-  private boolean isComponentValid(Element component) {
-    ValidationReport<?> report = componentValidator.validate(asType(component));
-    report.printMessagesTo(messager);
-    return report.isClean();
+  private ImmutableMap<Element, ValidationReport<TypeElement>> processCreators(
+      Set<? extends Element> builderElements, ImmutableSet.Builder<Element> rejectedElements) {
+    // Can't use an ImmutableMap.Builder here because a component may have (invalidly) more than one
+    // builder type, and that would make ImmutableMap.Builder throw.
+    Map<Element, ValidationReport<TypeElement>> reports = new HashMap<>();
+    for (Element element : builderElements) {
+      try {
+        ValidationReport<TypeElement> report =
+            creatorValidator.validate(MoreElements.asType(element));
+        report.printMessagesTo(messager);
+        reports.put(element.getEnclosingElement(), report);
+      } catch (TypeNotPresentException e) {
+        rejectedElements.add(element);
+      }
+    }
+    return ImmutableMap.copyOf(reports);
   }
 
-  @CanIgnoreReturnValue
-  private boolean validateFullBindingGraph(ComponentDescriptor componentDescriptor) {
-    TypeElement component = componentDescriptor.typeElement();
-    if (!bindingGraphValidator.shouldDoFullBindingGraphValidation(component)) {
+  private ImmutableMap<Element, ValidationReport<TypeElement>> processSubcomponents(
+      Set<? extends Element> subcomponentElements,
+      Set<? extends Element> subcomponentBuilderElements,
+      ImmutableSet.Builder<Element> rejectedElements) {
+    ImmutableMap.Builder<Element, ValidationReport<TypeElement>> reports = ImmutableMap.builder();
+    for (Element element : subcomponentElements) {
+      try {
+        ComponentValidationReport report =
+            componentValidator.validate(
+                MoreElements.asType(element), subcomponentElements, subcomponentBuilderElements);
+        report.report().printMessagesTo(messager);
+        reports.put(element, report.report());
+      } catch (TypeNotPresentException e) {
+        rejectedElements.add(element);
+      }
+    }
+    return reports.build();
+  }
+
+  private boolean isRootComponentValid(TypeElement rootComponent) {
+    ComponentValidationReport validationReport =
+        componentValidator.validate(
+            rootComponent, subcomponentElements, subcomponentCreatorElements);
+    validationReport.report().printMessagesTo(messager);
+    return isClean(validationReport);
+  }
+
+  // TODO(dpb): Clean up generics so this can take TypeElement.
+  private boolean isSubcomponentValid(Element subcomponentElement) {
+    ValidationReport<?> subcomponentCreatorReport =
+        creatorReportsBySubcomponent.get(subcomponentElement);
+    if (subcomponentCreatorReport != null && !subcomponentCreatorReport.isClean()) {
+      return false;
+    }
+    ValidationReport<?> subcomponentReport = reportsBySubcomponent.get(subcomponentElement);
+    return subcomponentReport == null || subcomponentReport.isClean();
+  }
+
+  private boolean isFullBindingGraphValid(ComponentDescriptor componentDescriptor) {
+    if (compilerOptions
+        .fullBindingGraphValidationType(componentDescriptor.typeElement())
+        .equals(NONE)) {
       return true;
     }
     BindingGraph fullBindingGraph = bindingGraphFactory.create(componentDescriptor, true);
-    return bindingGraphValidator.isValid(fullBindingGraph.topLevelBindingGraph());
+    return isValid(fullBindingGraph);
   }
 
   private boolean isValid(ComponentDescriptor componentDescriptor) {
@@ -158,4 +249,30 @@
     componentDescriptorReport.printMessagesTo(messager);
     return componentDescriptorReport.isClean();
   }
+
+  private boolean isValid(BindingGraph bindingGraph) {
+    return bindingGraphValidator.isValid(bindingGraphConverter.convert(bindingGraph));
+  }
+
+  /**
+   * Returns true if the component's report is clean, its builder report is clean, and all
+   * referenced subcomponent reports and subcomponent builder reports are clean.
+   */
+  private boolean isClean(ComponentValidationReport report) {
+    Element component = report.report().subject();
+    ValidationReport<?> componentReport = report.report();
+    if (!componentReport.isClean()) {
+      return false;
+    }
+    ValidationReport<?> builderReport = creatorReportsByComponent.get(component);
+    if (builderReport != null && !builderReport.isClean()) {
+      return false;
+    }
+    for (Element element : report.referencedSubcomponents()) {
+      if (!isSubcomponentValid(element)) {
+        return false;
+      }
+    }
+    return true;
+  }
 }
diff --git a/java/dagger/internal/codegen/ComponentProcessor.java b/java/dagger/internal/codegen/ComponentProcessor.java
index e392252..541a4ab 100644
--- a/java/dagger/internal/codegen/ComponentProcessor.java
+++ b/java/dagger/internal/codegen/ComponentProcessor.java
@@ -16,42 +16,25 @@
 
 package dagger.internal.codegen;
 
-import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
+import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.DYNAMIC;
 
 import com.google.auto.common.BasicAnnotationProcessor;
 import com.google.auto.service.AutoService;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
+import com.google.common.collect.Iterables;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.errorprone.annotations.CheckReturnValue;
 import dagger.BindsInstance;
 import dagger.Component;
 import dagger.Module;
 import dagger.Provides;
 import dagger.internal.codegen.SpiModule.TestingPlugins;
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.base.SourceFileGenerationException;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.InjectBindingRegistry;
-import dagger.internal.codegen.binding.MembersInjectionBinding;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.bindinggraphvalidation.BindingGraphValidationModule;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions;
-import dagger.internal.codegen.componentgenerator.ComponentGeneratorModule;
-import dagger.internal.codegen.validation.BindingGraphPlugins;
-import dagger.internal.codegen.validation.BindingMethodProcessingStep;
-import dagger.internal.codegen.validation.BindingMethodValidatorsModule;
-import dagger.internal.codegen.validation.BindsInstanceProcessingStep;
-import dagger.internal.codegen.validation.InjectBindingRegistryModule;
-import dagger.internal.codegen.validation.MonitoringModuleProcessingStep;
-import dagger.internal.codegen.validation.MultibindingAnnotationsProcessingStep;
 import dagger.spi.BindingGraphPlugin;
 import java.util.Arrays;
 import java.util.Optional;
 import java.util.Set;
-import javax.annotation.processing.ProcessingEnvironment;
 import javax.annotation.processing.Processor;
 import javax.annotation.processing.RoundEnvironment;
 import javax.inject.Inject;
@@ -65,7 +48,7 @@
  *
  * <p>TODO(gak): give this some better documentation
  */
-@IncrementalAnnotationProcessor(ISOLATING)
+@IncrementalAnnotationProcessor(DYNAMIC)
 @AutoService(Processor.class)
 public class ComponentProcessor extends BasicAnnotationProcessor {
   private final Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins;
@@ -75,6 +58,8 @@
   @Inject SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator;
   @Inject ImmutableList<ProcessingStep> processingSteps;
   @Inject BindingGraphPlugins bindingGraphPlugins;
+  @Inject CompilerOptions compilerOptions;
+  @Inject DaggerStatisticsCollector statisticsCollector;
   @Inject Set<ClearableCache> clearableCaches;
 
   public ComponentProcessor() {
@@ -110,19 +95,28 @@
 
   @Override
   public Set<String> getSupportedOptions() {
-    return Sets.union(
-            ProcessingEnvironmentCompilerOptions.supportedOptions(),
-            bindingGraphPlugins.allSupportedOptions())
-        .immutableCopy();
+    ImmutableSet.Builder<String> options = ImmutableSet.builder();
+    options.addAll(ProcessingEnvironmentCompilerOptions.supportedOptions());
+    options.addAll(bindingGraphPlugins.allSupportedOptions());
+    if (compilerOptions.useGradleIncrementalProcessing()) {
+      options.add("org.gradle.annotation.processing.isolating");
+    }
+    return options.build();
   }
 
   @Override
   protected Iterable<? extends ProcessingStep> initSteps() {
-    ProcessorComponent.factory().create(processingEnv, testingPlugins).inject(this);
+    ProcessorComponent.builder()
+        .processingEnvironmentModule(new ProcessingEnvironmentModule(processingEnv))
+        .testingPlugins(testingPlugins)
+        .build()
+        .inject(this);
 
+    statisticsCollector.processingStarted();
     bindingGraphPlugins.initializePlugins();
-
-    return processingSteps;
+    return Iterables.transform(
+        processingSteps,
+        step -> new DaggerStatisticsCollectingProcessingStep(step, statisticsCollector));
   }
 
   @Singleton
@@ -130,27 +124,32 @@
       modules = {
         BindingGraphValidationModule.class,
         BindingMethodValidatorsModule.class,
-        ComponentGeneratorModule.class,
         InjectBindingRegistryModule.class,
         ProcessingEnvironmentModule.class,
         ProcessingRoundCacheModule.class,
         ProcessingStepsModule.class,
         SourceFileGeneratorsModule.class,
-        SpiModule.class
+        SpiModule.class,
+        SystemComponentsModule.class,
+        TopLevelImplementationComponent.InstallationModule.class,
       })
   interface ProcessorComponent {
     void inject(ComponentProcessor processor);
 
-    static Factory factory() {
-      return DaggerComponentProcessor_ProcessorComponent.factory();
+    static Builder builder() {
+      return DaggerComponentProcessor_ProcessorComponent.builder();
     }
 
-    @Component.Factory
-    interface Factory {
-      @CheckReturnValue
-      ProcessorComponent create(
-          @BindsInstance ProcessingEnvironment processingEnv,
-          @BindsInstance @TestingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins);
+    @CanIgnoreReturnValue
+    @Component.Builder
+    interface Builder {
+      Builder processingEnvironmentModule(ProcessingEnvironmentModule module);
+
+      @BindsInstance
+      Builder testingPlugins(
+          @TestingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins);
+
+      @CheckReturnValue ProcessorComponent build();
     }
   }
 
@@ -160,9 +159,6 @@
     static ImmutableList<ProcessingStep> processingSteps(
         MapKeyProcessingStep mapKeyProcessingStep,
         InjectProcessingStep injectProcessingStep,
-        AssistedInjectProcessingStep assistedInjectProcessingStep,
-        AssistedFactoryProcessingStep assistedFactoryProcessingStep,
-        AssistedProcessingStep assistedProcessingStep,
         MonitoringModuleProcessingStep monitoringModuleProcessingStep,
         MultibindingAnnotationsProcessingStep multibindingAnnotationsProcessingStep,
         BindsInstanceProcessingStep bindsInstanceProcessingStep,
@@ -174,14 +170,15 @@
       return ImmutableList.of(
           mapKeyProcessingStep,
           injectProcessingStep,
-          assistedInjectProcessingStep,
-          assistedFactoryProcessingStep,
-          assistedProcessingStep,
           monitoringModuleProcessingStep,
           multibindingAnnotationsProcessingStep,
           bindsInstanceProcessingStep,
           moduleProcessingStep,
           compilerOptions.headerCompilation()
+                  // Ahead Of Time subcomponents use the regular hjar filtering in
+                  // HjarSourceFileGenerator since they must retain protected implementation methods
+                  // between subcomponents
+                  && !compilerOptions.aheadOfTimeSubcomponents()
               ? componentHjarProcessingStep
               : componentProcessingStep,
           bindingMethodProcessingStep);
@@ -190,7 +187,10 @@
 
   @Override
   protected void postRound(RoundEnvironment roundEnv) {
-    if (!roundEnv.processingOver()) {
+    statisticsCollector.roundFinished();
+    if (roundEnv.processingOver()) {
+      statisticsCollector.processingStopped();
+    } else {
       try {
         injectBindingRegistry.generateSourcesForRequiredBindings(
             factoryGenerator, membersInjectorGenerator);
diff --git a/java/dagger/internal/codegen/ComponentProvisionBindingExpression.java b/java/dagger/internal/codegen/ComponentProvisionBindingExpression.java
new file mode 100644
index 0000000..b8c6049
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentProvisionBindingExpression.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkNotNull;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.Preconditions;
+import dagger.internal.codegen.javapoet.Expression;
+
+/** A binding expression for component provision methods. */
+final class ComponentProvisionBindingExpression extends SimpleInvocationBindingExpression {
+  private final ProvisionBinding binding;
+  private final BindingGraph bindingGraph;
+  private final ComponentRequirementExpressions componentRequirementExpressions;
+  private final CompilerOptions compilerOptions;
+
+  ComponentProvisionBindingExpression(
+      ResolvedBindings resolvedBindings,
+      BindingGraph bindingGraph,
+      ComponentRequirementExpressions componentRequirementExpressions,
+      CompilerOptions compilerOptions) {
+    super(resolvedBindings);
+    this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
+    this.bindingGraph = checkNotNull(bindingGraph);
+    this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
+    this.compilerOptions = checkNotNull(compilerOptions);
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    CodeBlock invocation =
+        CodeBlock.of(
+            "$L.$L()",
+            componentRequirementExpressions.getExpression(componentRequirement(), requestingClass),
+            binding.bindingElement().get().getSimpleName());
+    return Expression.create(
+        binding.contributedPrimitiveType().orElse(binding.key().type()),
+        maybeCheckForNull(binding, compilerOptions, invocation));
+  }
+
+  private ComponentRequirement componentRequirement() {
+    return bindingGraph
+        .componentDescriptor()
+        .getDependencyThatDefinesMethod(binding.bindingElement().get());
+  }
+
+  static CodeBlock maybeCheckForNull(
+      ProvisionBinding binding, CompilerOptions compilerOptions, CodeBlock invocation) {
+    return binding.shouldCheckForNull(compilerOptions)
+        ? CodeBlock.of(
+            "$T.checkNotNull($L, $S)",
+            Preconditions.class,
+            invocation,
+            "Cannot return null from a non-@Nullable component method")
+        : invocation;
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentRequirement.java b/java/dagger/internal/codegen/ComponentRequirement.java
new file mode 100644
index 0000000..3bed5da
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentRequirement.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2016 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.MoreElements.getLocalAndInheritedMethods;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.SourceFiles.simpleVariableName;
+import static dagger.internal.codegen.Util.componentCanMakeNewInstances;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Equivalence;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.Binds;
+import dagger.BindsOptionalOf;
+import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.ComponentRequirementProto;
+import dagger.internal.codegen.serialization.ComponentRequirementProto.BoundInstanceRequirement;
+import dagger.model.BindingKind;
+import dagger.model.Key;
+import dagger.multibindings.Multibinds;
+import dagger.producers.Produces;
+import java.util.Optional;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/** A type that a component needs an instance of. */
+@AutoValue
+abstract class ComponentRequirement {
+  enum Kind {
+    /** A type listed in the component's {@code dependencies} attribute. */
+    DEPENDENCY,
+
+    /** A type listed in the component or subcomponent's {@code modules} attribute. */
+    MODULE,
+
+    /**
+     * An object that is passed to a builder's {@link dagger.BindsInstance @BindsInstance} method.
+     */
+    BOUND_INSTANCE,
+    ;
+
+    boolean isBoundInstance() {
+      return equals(BOUND_INSTANCE);
+    }
+
+    boolean isModule() {
+      return equals(MODULE);
+    }
+  }
+
+  /** The kind of requirement. */
+  abstract Kind kind();
+
+  /** Returns true if this is a {@link Kind#BOUND_INSTANCE} requirement. */
+  // TODO(ronshapiro): consider removing this and inlining the usages
+  final boolean isBoundInstance() {
+    return kind().isBoundInstance();
+  }
+
+  /**
+   * The type of the instance the component must have, wrapped so that requirements can be used as
+   * value types.
+   */
+  abstract Equivalence.Wrapper<TypeMirror> wrappedType();
+
+  /** The type of the instance the component must have. */
+  TypeMirror type() {
+    return wrappedType().get();
+  }
+
+  /** The element associated with the type of this requirement. */
+  TypeElement typeElement() {
+    return MoreTypes.asTypeElement(type());
+  }
+
+  /** The action a component builder should take if it {@code null} is passed. */
+  enum NullPolicy {
+    /** Make a new instance. */
+    NEW,
+    /** Throw an exception. */
+    THROW,
+    /** Allow use of null values. */
+    ALLOW,
+  }
+
+  /**
+   * An override for the requirement's null policy. If set, this is used as the null policy instead
+   * of the default behavior in {@link #nullPolicy}.
+   *
+   * <p>Some implementations' null policy can be determined upon construction (e.g., for binding
+   * instances), but others' require Elements and Types, which must wait until {@link #nullPolicy}
+   * is called.
+   */
+  abstract Optional<NullPolicy> overrideNullPolicy();
+
+  /** The requirement's null policy. */
+  NullPolicy nullPolicy(DaggerElements elements, DaggerTypes types) {
+    if (overrideNullPolicy().isPresent()) {
+      return overrideNullPolicy().get();
+    }
+    switch (kind()) {
+      case MODULE:
+        return componentCanMakeNewInstances(typeElement())
+            ? NullPolicy.NEW
+            : requiresAPassedInstance(elements, types) ? NullPolicy.THROW : NullPolicy.ALLOW;
+      case DEPENDENCY:
+      case BOUND_INSTANCE:
+        return NullPolicy.THROW;
+    }
+    throw new AssertionError();
+  }
+
+  /**
+   * Returns true if the passed {@link ComponentRequirement} requires a passed instance in order to
+   * be used within a component.
+   */
+  boolean requiresAPassedInstance(DaggerElements elements, DaggerTypes types) {
+    if (!kind().isModule()) {
+      // Bound instances and dependencies always require the user to provide an instance.
+      return true;
+    }
+    return requiresModuleInstance(elements, types) && !componentCanMakeNewInstances(typeElement());
+  }
+
+  /**
+   * Returns {@code true} if an instance is needed for this (module) requirement.
+   *
+   * <p>An instance is only needed if there is a binding method on the module that is neither {@code
+   * abstract} nor {@code static}; if all bindings are one of those, then there should be no
+   * possible dependency on instance state in the module's bindings.
+   */
+  private boolean requiresModuleInstance(DaggerElements elements, DaggerTypes types) {
+    ImmutableSet<ExecutableElement> methods =
+        getLocalAndInheritedMethods(typeElement(), types, elements);
+    return methods.stream()
+        .filter(this::isBindingMethod)
+        .map(ExecutableElement::getModifiers)
+        .anyMatch(modifiers -> !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC));
+  }
+
+  private boolean isBindingMethod(ExecutableElement method) {
+    // TODO(cgdecker): At the very least, we should have utility methods to consolidate this stuff
+    // in one place; listing individual annotations all over the place is brittle.
+    return isAnyAnnotationPresent(
+        method,
+        Provides.class,
+        Produces.class,
+        // TODO(ronshapiro): it would be cool to have internal meta-annotations that could describe
+        // these, like @AbstractBindingMethod
+        Binds.class,
+        Multibinds.class,
+        BindsOptionalOf.class);
+  }
+
+  /** The key for this requirement, if one is available. */
+  abstract Optional<Key> key();
+
+  /** Returns the name for this requirement that could be used as a variable. */
+  abstract String variableName();
+
+  /** Returns a parameter spec for this requirement. */
+  ParameterSpec toParameterSpec() {
+    return ParameterSpec.builder(TypeName.get(type()), variableName()).build();
+  }
+
+  /** Creates a proto representation of this requirement. */
+  ComponentRequirementProto toProto() {
+    switch (kind()) {
+      case DEPENDENCY:
+        return ComponentRequirementProto.newBuilder()
+            .setDependency(TypeProtoConverter.toProto(type()))
+            .build();
+      case MODULE:
+        return ComponentRequirementProto.newBuilder()
+            .setModule(TypeProtoConverter.toProto(type()))
+            .build();
+      case BOUND_INSTANCE:
+        return ComponentRequirementProto.newBuilder()
+            .setBoundInstance(
+                BoundInstanceRequirement.newBuilder()
+                    .setKey(KeyFactory.toProto(key().get()))
+                    .setNullable(overrideNullPolicy().equals(Optional.of(NullPolicy.ALLOW)))
+                    .setVariableName(variableName()))
+            .build();
+    }
+    throw new AssertionError(this);
+  }
+
+  static ComponentRequirement forDependency(TypeMirror type) {
+    return new AutoValue_ComponentRequirement(
+        Kind.DEPENDENCY,
+        MoreTypes.equivalence().wrap(checkNotNull(type)),
+        Optional.empty(),
+        Optional.empty(),
+        simpleVariableName(MoreTypes.asTypeElement(type)));
+  }
+
+  static ComponentRequirement forModule(TypeMirror type) {
+    return new AutoValue_ComponentRequirement(
+        Kind.MODULE,
+        MoreTypes.equivalence().wrap(checkNotNull(type)),
+        Optional.empty(),
+        Optional.empty(),
+        simpleVariableName(MoreTypes.asTypeElement(type)));
+  }
+
+  static ComponentRequirement forBoundInstance(Key key, boolean nullable, String variableName) {
+    return new AutoValue_ComponentRequirement(
+        Kind.BOUND_INSTANCE,
+        MoreTypes.equivalence().wrap(key.type()),
+        nullable ? Optional.of(NullPolicy.ALLOW) : Optional.empty(),
+        Optional.of(key),
+        variableName);
+  }
+
+  static ComponentRequirement forBoundInstance(ContributionBinding binding) {
+    checkArgument(binding.kind().equals(BindingKind.BOUND_INSTANCE));
+    return forBoundInstance(
+        binding.key(),
+        binding.nullableType().isPresent(),
+        binding.bindingElement().get().getSimpleName().toString());
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentRequirementBindingExpression.java b/java/dagger/internal/codegen/ComponentRequirementBindingExpression.java
new file mode 100644
index 0000000..d6aa053
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentRequirementBindingExpression.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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.squareup.javapoet.ClassName;
+import dagger.internal.codegen.javapoet.Expression;
+
+/**
+ * A binding expression for instances bound with {@link dagger.BindsInstance} and instances of
+ * {@linkplain dagger.Component#dependencies() component} and {@linkplain
+ * dagger.producers.ProductionComponent#dependencies() production component dependencies}.
+ */
+final class ComponentRequirementBindingExpression extends SimpleInvocationBindingExpression {
+  private final ComponentRequirement componentRequirement;
+  private final ComponentRequirementExpressions componentRequirementExpressions;
+
+  ComponentRequirementBindingExpression(
+      ResolvedBindings resolvedBindings,
+      ComponentRequirement componentRequirement,
+      ComponentRequirementExpressions componentRequirementExpressions) {
+    super(resolvedBindings);
+    this.componentRequirement = componentRequirement;
+    this.componentRequirementExpressions = componentRequirementExpressions;
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    return Expression.create(
+        componentRequirement.type(),
+        componentRequirementExpressions.getExpression(componentRequirement, requestingClass));
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentRequirementExpression.java b/java/dagger/internal/codegen/ComponentRequirementExpression.java
new file mode 100644
index 0000000..b25c01b
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentRequirementExpression.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 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.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+
+/**
+ * A factory for expressions of {@link ComponentRequirement}s in the generated component. This is
+ * <em>not</em> a {@link BindingExpression}, since {@link ComponentRequirement}s do not have a
+ * {@link dagger.model.Key}. See {@link ComponentRequirementBindingExpression} for binding
+ * expressions that are themselves a component requirement.
+ */
+interface ComponentRequirementExpression {
+  /**
+   * Returns an expression for the {@link ComponentRequirement} to be used when implementing a
+   * component method. This may add a field or method to the component in order to reference the
+   * component requirement outside of the {@code initialize()} methods.
+   */
+  CodeBlock getExpression(ClassName requestingClass);
+
+  /**
+   * Returns an expression for the {@link ComponentRequirement} to be used only within {@code
+   * initialize()} methods, where the constructor parameters are available.
+   *
+   * <p>When accessing this expression from a subcomponent, this may cause a field to be initialized
+   * or a method to be added in the component that owns this {@link ComponentRequirement}.
+   */
+  default CodeBlock getExpressionDuringInitialization(ClassName requestingClass) {
+    return getExpression(requestingClass);
+  }
+
+  /**
+   * Returns the expression for the {@link ComponentRequirement} to be used when reimplementing a
+   * modifiable module method.
+   */
+  default CodeBlock getModifiableModuleMethodExpression(ClassName requestingClass) {
+    return CodeBlock.of("return $L", getExpression(requestingClass));
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentRequirementExpressions.java b/java/dagger/internal/codegen/ComponentRequirementExpressions.java
new file mode 100644
index 0000000..4ab58c9
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentRequirementExpressions.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2017 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.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Suppliers.memoize;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static dagger.internal.codegen.ComponentImplementation.FieldSpecKind.COMPONENT_REQUIREMENT_FIELD;
+import static dagger.internal.codegen.ModuleProxies.newModuleInstance;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PROTECTED;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * A central repository of expressions used to access any {@link ComponentRequirement} available to
+ * a component.
+ */
+@PerComponentImplementation
+final class ComponentRequirementExpressions {
+
+  // TODO(dpb,ronshapiro): refactor this and ComponentBindingExpressions into a
+  // HierarchicalComponentMap<K, V>, or perhaps this use a flattened ImmutableMap, built from its
+  // parents? If so, maybe make ComponentRequirementExpression.Factory create it.
+
+  private final Optional<ComponentRequirementExpressions> parent;
+  private final Map<ComponentRequirement, ComponentRequirementExpression>
+      componentRequirementExpressions = new HashMap<>();
+  private final BindingGraph graph;
+  private final ComponentImplementation componentImplementation;
+  private final CompilerOptions compilerOptions;
+  private final DaggerElements elements;
+
+  // TODO(ronshapiro): give ComponentImplementation a graph() method
+  @Inject
+  ComponentRequirementExpressions(
+      @ParentComponent Optional<ComponentRequirementExpressions> parent,
+      BindingGraph graph,
+      ComponentImplementation componentImplementation,
+      CompilerOptions compilerOptions,
+      DaggerElements elements) {
+    this.parent = parent;
+    this.graph = graph;
+    this.componentImplementation = componentImplementation;
+    this.compilerOptions = compilerOptions;
+    this.elements = elements;
+  }
+
+  /**
+   * Returns an expression for the {@code componentRequirement} to be used when implementing a
+   * component method. This may add a field or method to the component in order to reference the
+   * component requirement outside of the {@code initialize()} methods.
+   */
+  CodeBlock getExpression(ComponentRequirement componentRequirement, ClassName requestingClass) {
+    return getExpression(componentRequirement).getExpression(requestingClass);
+  }
+
+  /**
+   * Returns an expression for the {@code componentRequirement} to be used only within {@code
+   * initialize()} methods, where the component constructor parameters are available.
+   *
+   * <p>When accessing this expression from a subcomponent, this may cause a field to be initialized
+   * or a method to be added in the component that owns this {@link ComponentRequirement}.
+   */
+  CodeBlock getExpressionDuringInitialization(
+      ComponentRequirement componentRequirement, ClassName requestingClass) {
+    return getExpression(componentRequirement).getExpressionDuringInitialization(requestingClass);
+  }
+
+  ComponentRequirementExpression getExpression(ComponentRequirement componentRequirement) {
+    if (graph.componentRequirements().contains(componentRequirement)) {
+      return componentRequirementExpressions.computeIfAbsent(
+          componentRequirement, this::createMethodOrField);
+    }
+    if (parent.isPresent()) {
+      return parent.get().getExpression(componentRequirement);
+    }
+
+    if (componentRequirement.kind().isModule() && compilerOptions.aheadOfTimeSubcomponents()) {
+      return new PrunedModifiableModule(componentRequirement);
+    }
+
+    throw new IllegalStateException(
+        "no component requirement expression found for " + componentRequirement);
+  }
+
+  /**
+   * If {@code requirement} is a module that may be owned by a future ancestor component, returns a
+   * modifiable module method. Otherwise, returns a field for {@code requirement}.
+   */
+  private ComponentRequirementExpression createMethodOrField(ComponentRequirement requirement) {
+    if (componentImplementation.isAbstract() && requirement.kind().isModule()) {
+      return new ModifiableModule(requirement);
+    }
+    return createField(requirement);
+  }
+
+  /** Returns a field for a {@link ComponentRequirement}. */
+  private ComponentRequirementExpression createField(ComponentRequirement requirement) {
+    if (componentImplementation.componentDescriptor().hasCreator()) {
+      return new ComponentParameterField(requirement, componentImplementation, Optional.empty());
+    } else if (graph.factoryMethod().isPresent()
+        && graph.factoryMethodParameters().containsKey(requirement)) {
+      String parameterName =
+          graph.factoryMethodParameters().get(requirement).getSimpleName().toString();
+      return new ComponentParameterField(
+          requirement, componentImplementation, Optional.of(parameterName));
+    } else if (requirement.kind().isModule()) {
+      return new InstantiableModuleField(requirement, componentImplementation);
+    } else {
+      throw new AssertionError(
+          String.format("Can't create %s in %s", requirement, componentImplementation.name()));
+    }
+  }
+
+  private abstract static class AbstractField implements ComponentRequirementExpression {
+    final ComponentRequirement componentRequirement;
+    final ComponentImplementation componentImplementation;
+    final String fieldName;
+    private final Supplier<MemberSelect> field = memoize(this::addField);
+
+    private AbstractField(
+        ComponentRequirement componentRequirement,
+        ComponentImplementation componentImplementation) {
+      this.componentRequirement = checkNotNull(componentRequirement);
+      this.componentImplementation = checkNotNull(componentImplementation);
+      // Note: The field name is being claimed eagerly here even though we don't know at this point
+      // whether or not the requirement will even need a field. This is done because:
+      // A) ComponentParameterField wants to ensure that it doesn't give the parameter the same name
+      //    as any field in the component, which requires that it claim a "field name" for itself
+      //    when naming the parameter.
+      // B) The parameter name may be needed before the field name is.
+      // C) We want to prefer giving the best name to the field rather than the parameter given its
+      //    wider scope.
+      this.fieldName =
+          componentImplementation.getUniqueFieldName(componentRequirement.variableName());
+    }
+
+    @Override
+    public CodeBlock getExpression(ClassName requestingClass) {
+      return field.get().getExpressionFor(requestingClass);
+    }
+
+    private MemberSelect addField() {
+      FieldSpec field = createField();
+      componentImplementation.addField(COMPONENT_REQUIREMENT_FIELD, field);
+      componentImplementation.addComponentRequirementInitialization(fieldInitialization(field));
+      return MemberSelect.localField(componentImplementation.name(), fieldName);
+    }
+
+    private FieldSpec createField() {
+      FieldSpec.Builder field =
+          FieldSpec.builder(TypeName.get(componentRequirement.type()), fieldName, PRIVATE);
+      if (!componentImplementation.isAbstract()) {
+        field.addModifiers(FINAL);
+      }
+      return field.build();
+    }
+
+    /** Returns the {@link CodeBlock} that initializes the component field during construction. */
+    abstract CodeBlock fieldInitialization(FieldSpec componentField);
+  }
+
+  /**
+   * A {@link ComponentRequirementExpression} for {@link ComponentRequirement}s that can be
+   * instantiated by the component (i.e. a static class with a no-arg constructor).
+   */
+  private final class InstantiableModuleField extends AbstractField {
+    private final TypeElement moduleElement;
+
+    private InstantiableModuleField(
+        ComponentRequirement module, ComponentImplementation componentImplementation) {
+      super(module, componentImplementation);
+      checkArgument(module.kind().isModule());
+      this.moduleElement = module.typeElement();
+    }
+
+    @Override
+    CodeBlock fieldInitialization(FieldSpec componentField) {
+      return CodeBlock.of(
+          "this.$N = $L;",
+          componentField,
+          newModuleInstance(moduleElement, componentImplementation.name(), elements));
+    }
+  }
+
+  /**
+   * A {@link ComponentRequirementExpression} for {@link ComponentRequirement}s that are passed in
+   * as parameters to the component's constructor.
+   */
+  private static final class ComponentParameterField extends AbstractField {
+    private final String parameterName;
+
+    private ComponentParameterField(
+        ComponentRequirement componentRequirement,
+        ComponentImplementation componentImplementation,
+        Optional<String> name) {
+      super(componentRequirement, componentImplementation);
+      componentImplementation.addComponentRequirementParameter(componentRequirement);
+      // Get the name that the component implementation will use for its parameter for the
+      // requirement. If the given name is different than the name of the field created for the
+      // requirement (as may be the case when the parameter name is derived from a user-written
+      // factory method parameter), just use that as the base name for the parameter. Otherwise,
+      // append "Param" to the end of the name to differentiate.
+      // In either case, componentImplementation.getParameterName() will ensure that the final name
+      // that is used is not the same name as any field in the component even if there's something
+      // weird where the component actually has fields named, say, "foo" and "fooParam".
+      String baseName = name.filter(n -> !n.equals(fieldName)).orElse(fieldName + "Param");
+      this.parameterName = componentImplementation.getParameterName(componentRequirement, baseName);
+    }
+
+    @Override
+    public CodeBlock getExpressionDuringInitialization(ClassName requestingClass) {
+      if (componentImplementation.name().equals(requestingClass)) {
+        return CodeBlock.of("$L", parameterName);
+      } else {
+        // requesting this component requirement during initialization of a child component requires
+        // it to be accessed from a field and not the parameter (since it is no longer available)
+        return getExpression(requestingClass);
+      }
+    }
+
+    @Override
+    CodeBlock fieldInitialization(FieldSpec componentField) {
+      // Don't checkNotNull here because the parameter may be nullable; if it isn't, the caller
+      // should handle checking that before passing the parameter.
+      return CodeBlock.of("this.$N = $L;", componentField, parameterName);
+    }
+  }
+
+  private final class ModifiableModule implements ComponentRequirementExpression {
+    private final ComponentRequirement module;
+    private final Supplier<MemberSelect> method = Suppliers.memoize(this::methodSelect);
+
+    private ModifiableModule(ComponentRequirement module) {
+      checkArgument(module.kind().isModule());
+      this.module = module;
+    }
+
+    @Override
+    public CodeBlock getExpression(ClassName requestingClass) {
+      return method.get().getExpressionFor(requestingClass);
+    }
+
+    private MemberSelect methodSelect() {
+      String methodName =
+          componentImplementation
+              .supertypeModifiableModuleMethodName(module)
+              .orElseGet(this::createMethod);
+      return MemberSelect.localMethod(componentImplementation.name(), methodName);
+    }
+
+    private String createMethod() {
+      String methodName =
+          UPPER_CAMEL.to(
+              LOWER_CAMEL,
+              componentImplementation.getUniqueMethodName(
+                  module.typeElement().getSimpleName().toString()));
+      MethodSpec.Builder methodBuilder =
+          methodBuilder(methodName)
+              .addModifiers(PROTECTED)
+              .returns(TypeName.get(module.type()));
+      // TODO(b/117833324): if the module is instantiable, we could provide an implementation here
+      // too. Then, if no ancestor ever repeats the module, there's nothing to do in subclasses.
+      if (graph.componentDescriptor().creatorDescriptor().isPresent()) {
+        methodBuilder.addStatement(
+            "return $L",
+            createField(module).getExpression(componentImplementation.name()));
+      } else {
+        methodBuilder.addModifiers(ABSTRACT);
+      }
+      componentImplementation.addModifiableModuleMethod(module, methodBuilder.build());
+      return methodName;
+    }
+  }
+
+  private static final class PrunedModifiableModule implements ComponentRequirementExpression {
+    private final ComponentRequirement module;
+
+    private PrunedModifiableModule(ComponentRequirement module) {
+      checkArgument(module.kind().isModule());
+      this.module = module;
+    }
+
+    @Override
+    public CodeBlock getExpression(ClassName requestingClass) {
+      throw new UnsupportedOperationException(module + " is pruned - it cannot be requested");
+    }
+
+    @Override
+    public CodeBlock getModifiableModuleMethodExpression(ClassName requestingClass) {
+      return CodeBlock.builder()
+          .add(
+              "// $L has been pruned from the final resolved binding graph. The result of this "
+                  + "method should never be used, but it may be called in an initialize() method "
+                  + "when creating a framework instance of a now-pruned binding. Those framework "
+                  + "instances should never be used.\n",
+              module.typeElement())
+          .add("return null")
+          .build();
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentTreeTraverser.java b/java/dagger/internal/codegen/ComponentTreeTraverser.java
new file mode 100644
index 0000000..cc1efd2
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentTreeTraverser.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.model.ComponentPath;
+import dagger.model.DependencyRequest;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * An object that traverses the entire component hierarchy, starting from the root component.
+ *
+ * <p>Subclasses can override {@link #visitComponent(BindingGraph)} to perform custom logic at each
+ * component in the tree, and {@link #visitSubcomponentFactoryMethod(BindingGraph, BindingGraph,
+ * ExecutableElement)} to perform custom logic at each subcomponent factory method.
+ */
+public class ComponentTreeTraverser {
+
+  /** The path from the root graph to the currently visited graph. */
+  private final Deque<BindingGraph> bindingGraphPath = new ArrayDeque<>();
+
+  /** The {@link ComponentPath} for each component in {@link #bindingGraphPath}. */
+  private final Deque<ComponentPath> componentPaths = new ArrayDeque<>();
+
+  /** Constructs a traverser for a root (component, not subcomponent) binding graph. */
+  public ComponentTreeTraverser(BindingGraph rootGraph) {
+    bindingGraphPath.add(rootGraph);
+    componentPaths.add(ComponentPath.create(ImmutableList.of(rootGraph.componentTypeElement())));
+  }
+
+  /**
+   * Calls {@link #visitComponent(BindingGraph)} for the root component.
+   *
+   * @throws IllegalStateException if a traversal is in progress
+   */
+  public final void traverseComponents() {
+    checkState(bindingGraphPath.size() == 1);
+    checkState(componentPaths.size() == 1);
+    visitComponent(bindingGraphPath.getFirst());
+  }
+
+  /**
+   * Called once for each component in a component hierarchy.
+   *
+   * <p>Subclasses can override this method to perform whatever logic is required per component.
+   * They should call the {@code super} implementation if they want to continue the traversal in the
+   * standard order.
+   *
+   * <p>This implementation does the following:
+   *
+   * <ol>
+   *   <li>If this component is installed in its parent by a subcomponent factory method, calls
+   *       {@link #visitSubcomponentFactoryMethod(BindingGraph, BindingGraph, ExecutableElement)}.
+   *   <li>For each entry point in the component, calls {@link #visitEntryPoint(DependencyRequest,
+   *       BindingGraph)}.
+   *   <li>For each child component, calls {@link #visitComponent(BindingGraph)}, updating the
+   *       traversal state.
+   * </ol>
+   *
+   * @param graph the currently visited graph
+   */
+  protected void visitComponent(BindingGraph graph) {
+    if (bindingGraphPath.size() > 1) {
+      BindingGraph parent = Iterators.get(bindingGraphPath.descendingIterator(), 1);
+      parent
+          .componentDescriptor()
+          .getFactoryMethodForChildComponent(graph.componentDescriptor())
+          .ifPresent(
+              childFactoryMethod ->
+                  visitSubcomponentFactoryMethod(
+                      graph, parent, childFactoryMethod.methodElement()));
+    }
+
+    for (ComponentMethodDescriptor entryPointMethod :
+        graph.componentDescriptor().entryPointMethods()) {
+      visitEntryPoint(entryPointMethod.dependencyRequest().get(), graph);
+    }
+
+    for (BindingGraph child : graph.subgraphs()) {
+      bindingGraphPath.addLast(child);
+      ComponentPath childPath =
+          ComponentPath.create(
+              bindingGraphPath.stream()
+                  .map(BindingGraph::componentTypeElement)
+                  .collect(toImmutableList()));
+      componentPaths.addLast(childPath);
+      try {
+        visitComponent(child);
+      } finally {
+        verify(bindingGraphPath.removeLast().equals(child));
+        verify(componentPaths.removeLast().equals(childPath));
+      }
+    }
+  }
+
+  /**
+   * Called if this component was installed in its parent by a subcomponent factory method.
+   *
+   * <p>This implementation does nothing.
+   *
+   * @param graph the currently visited graph
+   * @param parent the parent graph
+   * @param factoryMethod the factory method in the parent component that declares that the current
+   *     component is a child
+   */
+  protected void visitSubcomponentFactoryMethod(
+      BindingGraph graph, BindingGraph parent, ExecutableElement factoryMethod) {}
+
+  /**
+   * Called once for each entry point in a component.
+   *
+   * <p>Subclasses can override this method to perform whatever logic is required per entry point.
+   * They should call the {@code super} implementation if they want to continue the traversal in the
+   * standard order.
+   *
+   * <p>This implementation does nothing.
+   *
+   * @param graph the graph for the component that contains the entry point
+   */
+  protected void visitEntryPoint(DependencyRequest entryPoint, BindingGraph graph) {}
+
+  /**
+   * Returns an immutable snapshot of the path from the root component to the currently visited
+   * component.
+   */
+  protected final ComponentPath componentPath() {
+    return componentPaths.getLast();
+  }
+
+  /**
+   * Returns the subpath from the root component to the matching {@code ancestor} of the current
+   * component.
+   */
+  protected final ComponentPath pathFromRootToAncestor(TypeElement ancestor) {
+    for (ComponentPath componentPath : componentPaths) {
+      if (componentPath.currentComponent().equals(ancestor)) {
+        return componentPath;
+      }
+    }
+    throw new IllegalArgumentException(
+        String.format("%s is not in the current path: %s", ancestor.getQualifiedName(), this));
+  }
+
+  /**
+   * Returns the BindingGraph for {@code ancestor}, where {@code ancestor} is in the component path
+   * of the current traversal.
+   */
+  protected final BindingGraph graphForAncestor(TypeElement ancestor) {
+    for (BindingGraph graph : bindingGraphPath) {
+      if (graph.componentTypeElement().equals(ancestor)) {
+        return graph;
+      }
+    }
+    throw new IllegalArgumentException(
+        String.format("%s is not in the current path: %s", ancestor.getQualifiedName(), this));
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentValidator.java b/java/dagger/internal/codegen/ComponentValidator.java
new file mode 100644
index 0000000..7739915
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentValidator.java
@@ -0,0 +1,522 @@
+/*
+ * Copyright (C) 2014 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.MoreElements.asType;
+import static com.google.auto.common.MoreElements.getLocalAndInheritedMethods;
+import static com.google.auto.common.MoreElements.isAnnotationPresent;
+import static com.google.auto.common.MoreTypes.asDeclared;
+import static com.google.auto.common.MoreTypes.asExecutable;
+import static com.google.common.base.Verify.verify;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.collect.Multimaps.asMap;
+import static com.google.common.collect.Sets.intersection;
+import static dagger.internal.codegen.ComponentAnnotation.anyComponentAnnotation;
+import static dagger.internal.codegen.ComponentAnnotation.componentAnnotation;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.creatorAnnotationsFor;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.productionCreatorAnnotations;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.subcomponentCreatorAnnotations;
+import static dagger.internal.codegen.ComponentKind.annotationsFor;
+import static dagger.internal.codegen.ConfigurationAnnotations.enclosedAnnotatedTypes;
+import static dagger.internal.codegen.ConfigurationAnnotations.getTransitiveModules;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages.builderMethodRequiresNoArgs;
+import static dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages.moreThanOneRefToSubcomponent;
+import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
+import static java.util.Comparator.comparing;
+import static javax.lang.model.element.ElementKind.CLASS;
+import static javax.lang.model.element.ElementKind.INTERFACE;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.type.TypeKind.VOID;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
+import dagger.Component;
+import dagger.Reusable;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.producers.CancellationPolicy;
+import dagger.producers.ProductionComponent;
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVisitor;
+import javax.lang.model.util.SimpleTypeVisitor6;
+import javax.lang.model.util.SimpleTypeVisitor8;
+
+/**
+ * Performs superficial validation of the contract of the {@link Component} and {@link
+ * ProductionComponent} annotations.
+ */
+final class ComponentValidator {
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+  private final ModuleValidator moduleValidator;
+  private final ComponentCreatorValidator creatorValidator;
+  private final DependencyRequestValidator dependencyRequestValidator;
+  private final MembersInjectionValidator membersInjectionValidator;
+  private final MethodSignatureFormatter methodSignatureFormatter;
+  private final DependencyRequestFactory dependencyRequestFactory;
+
+  @Inject
+  ComponentValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      ModuleValidator moduleValidator,
+      ComponentCreatorValidator creatorValidator,
+      DependencyRequestValidator dependencyRequestValidator,
+      MembersInjectionValidator membersInjectionValidator,
+      MethodSignatureFormatter methodSignatureFormatter,
+      DependencyRequestFactory dependencyRequestFactory) {
+    this.elements = elements;
+    this.types = types;
+    this.moduleValidator = moduleValidator;
+    this.creatorValidator = creatorValidator;
+    this.dependencyRequestValidator = dependencyRequestValidator;
+    this.membersInjectionValidator = membersInjectionValidator;
+    this.methodSignatureFormatter = methodSignatureFormatter;
+    this.dependencyRequestFactory = dependencyRequestFactory;
+  }
+
+  @AutoValue
+  abstract static class ComponentValidationReport {
+    abstract ImmutableSet<Element> referencedSubcomponents();
+
+    abstract ValidationReport<TypeElement> report();
+  }
+
+  /**
+   * Validates the given component subject. Also validates any referenced subcomponents that aren't
+   * already included in the {@code validatedSubcomponents} set.
+   */
+  public ComponentValidationReport validate(
+      TypeElement subject,
+      Set<? extends Element> validatedSubcomponents,
+      Set<? extends Element> validatedSubcomponentCreators) {
+    ValidationReport.Builder<TypeElement> report = ValidationReport.about(subject);
+
+    ImmutableSet<ComponentKind> componentKinds = ComponentKind.getComponentKinds(subject);
+    ImmutableSet<Element> allSubcomponents;
+    if (componentKinds.size() > 1) {
+      String error =
+          "Components may not be annotated with more than one component annotation: found "
+              + annotationsFor(componentKinds);
+      report.addError(error, subject);
+      allSubcomponents = ImmutableSet.of();
+    } else {
+      ComponentKind componentKind = getOnlyElement(componentKinds);
+      ComponentAnnotation componentAnnotation = anyComponentAnnotation(subject).get();
+      allSubcomponents =
+          validate(
+              subject,
+              componentAnnotation,
+              componentKind,
+              validatedSubcomponents,
+              validatedSubcomponentCreators,
+              report);
+    }
+
+    return new AutoValue_ComponentValidator_ComponentValidationReport(
+        allSubcomponents, report.build());
+  }
+
+  private ImmutableSet<Element> validate(
+      TypeElement subject,
+      ComponentAnnotation componentAnnotation,
+      ComponentKind componentKind,
+      Set<? extends Element> validatedSubcomponents,
+      Set<? extends Element> validatedSubcomponentCreators,
+      ValidationReport.Builder<TypeElement> report) {
+    if (isAnnotationPresent(subject, CancellationPolicy.class) && !componentKind.isProducer()) {
+      report.addError(
+          "@CancellationPolicy may only be applied to production components and subcomponents",
+          subject);
+    }
+
+    if (!subject.getKind().equals(INTERFACE)
+        && !(subject.getKind().equals(CLASS) && subject.getModifiers().contains(ABSTRACT))) {
+      report.addError(
+          String.format(
+              "@%s may only be applied to an interface or abstract class",
+              componentKind.annotation().getSimpleName()),
+          subject);
+    }
+
+    ImmutableList<DeclaredType> creators =
+        creatorAnnotationsFor(componentAnnotation).stream()
+            .flatMap(annotation -> enclosedAnnotatedTypes(subject, annotation).stream())
+            .collect(toImmutableList());
+    if (creators.size() > 1) {
+      report.addError(
+          String.format(ErrorMessages.componentMessagesFor(componentKind).moreThanOne(), creators),
+          subject);
+    }
+
+    Optional<AnnotationMirror> reusableAnnotation = getAnnotationMirror(subject, Reusable.class);
+    if (reusableAnnotation.isPresent()) {
+      report.addError(
+          "@Reusable cannot be applied to components or subcomponents",
+          subject,
+          reusableAnnotation.get());
+    }
+
+    DeclaredType subjectType = MoreTypes.asDeclared(subject.asType());
+
+    SetMultimap<Element, ExecutableElement> referencedSubcomponents = LinkedHashMultimap.create();
+    getLocalAndInheritedMethods(subject, types, elements).stream()
+        .filter(method -> method.getModifiers().contains(ABSTRACT))
+        .forEachOrdered(
+            method -> {
+              ExecutableType resolvedMethod = asExecutable(types.asMemberOf(subjectType, method));
+              List<? extends TypeMirror> parameterTypes = resolvedMethod.getParameterTypes();
+              List<? extends VariableElement> parameters = method.getParameters();
+              TypeMirror returnType = resolvedMethod.getReturnType();
+
+              if (!resolvedMethod.getTypeVariables().isEmpty()) {
+                report.addError("Component methods cannot have type variables", method);
+              }
+
+              // abstract methods are ones we have to implement, so they each need to be validated
+              // first, check the return type. if it's a subcomponent, validate that method as such.
+              Optional<AnnotationMirror> subcomponentAnnotation =
+                  checkForAnnotations(
+                      returnType,
+                      componentKind.legalSubcomponentKinds().stream()
+                          .map(ComponentKind::annotation)
+                          .collect(toImmutableSet()));
+              Optional<AnnotationMirror> subcomponentCreatorAnnotation =
+                  checkForAnnotations(
+                      returnType,
+                      componentAnnotation.isProduction()
+                          ? intersection(
+                              subcomponentCreatorAnnotations(), productionCreatorAnnotations())
+                          : subcomponentCreatorAnnotations());
+              if (subcomponentAnnotation.isPresent()) {
+                referencedSubcomponents.put(MoreTypes.asElement(returnType), method);
+                validateSubcomponentMethod(
+                    report,
+                    ComponentKind.forAnnotatedElement(MoreTypes.asTypeElement(returnType)).get(),
+                    method,
+                    parameters,
+                    parameterTypes,
+                    returnType,
+                    subcomponentAnnotation);
+              } else if (subcomponentCreatorAnnotation.isPresent()) {
+                referencedSubcomponents.put(
+                    MoreTypes.asElement(returnType).getEnclosingElement(), method);
+                validateSubcomponentCreatorMethod(
+                    report, method, parameters, returnType, validatedSubcomponentCreators);
+              } else {
+                // if it's not a subcomponent...
+                switch (parameters.size()) {
+                  case 0:
+                    // no parameters means that it is a provision method
+                    dependencyRequestValidator.validateDependencyRequest(
+                        report, method, returnType);
+                    break;
+                  case 1:
+                    // one parameter means that it's a members injection method
+                    TypeMirror parameterType = Iterables.getOnlyElement(parameterTypes);
+                    report.addSubreport(
+                        membersInjectionValidator.validateMembersInjectionMethod(
+                            method, parameterType));
+                    if (!(returnType.getKind().equals(VOID)
+                        || types.isSameType(returnType, parameterType))) {
+                      report.addError(
+                          "Members injection methods may only return the injected type or void.",
+                          method);
+                    }
+                    break;
+                  default:
+                    // this isn't any method that we know how to implement...
+                    report.addError(
+                        "This method isn't a valid provision method, members injection method or "
+                            + "subcomponent factory method. Dagger cannot implement this method",
+                        method);
+                    break;
+                }
+              }
+            });
+
+    checkConflictingEntryPoints(report);
+
+    Maps.filterValues(referencedSubcomponents.asMap(), methods -> methods.size() > 1)
+        .forEach(
+            (subcomponent, methods) ->
+                report.addError(
+                    String.format(moreThanOneRefToSubcomponent(), subcomponent, methods), subject));
+
+    validateComponentDependencies(report, componentAnnotation.dependencyTypes());
+    report.addSubreport(
+        moduleValidator.validateReferencedModules(
+            subject,
+            componentAnnotation.annotation(),
+            componentKind.legalModuleKinds(),
+            new HashSet<>()));
+
+    // Make sure we validate any subcomponents we're referencing, unless we know we validated
+    // them already in this pass.
+    // TODO(sameb): If subcomponents refer to each other and both aren't in
+    //              'validatedSubcomponents' (e.g, both aren't compiled in this pass),
+    //              then this can loop forever.
+    ImmutableSet.Builder<Element> allSubcomponents =
+        ImmutableSet.<Element>builder().addAll(referencedSubcomponents.keySet());
+    for (Element subcomponent :
+        Sets.difference(referencedSubcomponents.keySet(), validatedSubcomponents)) {
+      ComponentValidationReport subreport =
+          validate(asType(subcomponent), validatedSubcomponents, validatedSubcomponentCreators);
+      report.addItems(subreport.report().items());
+      allSubcomponents.addAll(subreport.referencedSubcomponents());
+    }
+    return allSubcomponents.build();
+  }
+
+  private void checkConflictingEntryPoints(ValidationReport.Builder<TypeElement> report) {
+    DeclaredType componentType = asDeclared(report.getSubject().asType());
+
+    // Collect entry point methods that are not overridden by others. If the "same" method is
+    // inherited from more than one supertype, each will be in the multimap.
+    SetMultimap<String, ExecutableElement> entryPointMethods = HashMultimap.create();
+
+    methodsIn(elements.getAllMembers(report.getSubject()))
+        .stream()
+        .filter(
+            method -> isEntryPoint(method, asExecutable(types.asMemberOf(componentType, method))))
+        .forEach(
+            method ->
+                addMethodUnlessOverridden(
+                    method, entryPointMethods.get(method.getSimpleName().toString())));
+
+    for (Set<ExecutableElement> methods : asMap(entryPointMethods).values()) {
+      if (distinctKeys(methods, report.getSubject()).size() > 1) {
+        reportConflictingEntryPoints(methods, report);
+      }
+    }
+  }
+
+  private boolean isEntryPoint(ExecutableElement method, ExecutableType methodType) {
+    return method.getModifiers().contains(ABSTRACT)
+        && method.getParameters().isEmpty()
+        && !methodType.getReturnType().getKind().equals(VOID)
+        && methodType.getTypeVariables().isEmpty();
+  }
+
+  private ImmutableSet<Key> distinctKeys(Set<ExecutableElement> methods, TypeElement component) {
+    return methods
+        .stream()
+        .map(method -> dependencyRequest(method, component))
+        .map(DependencyRequest::key)
+        .collect(toImmutableSet());
+  }
+
+  private DependencyRequest dependencyRequest(ExecutableElement method, TypeElement component) {
+    ExecutableType methodType =
+        asExecutable(types.asMemberOf(asDeclared(component.asType()), method));
+    return ComponentKind.forAnnotatedElement(component).get().isProducer()
+        ? dependencyRequestFactory.forComponentProductionMethod(method, methodType)
+        : dependencyRequestFactory.forComponentProvisionMethod(method, methodType);
+  }
+
+  private void addMethodUnlessOverridden(ExecutableElement method, Set<ExecutableElement> methods) {
+    if (methods.stream().noneMatch(existingMethod -> overridesAsDeclared(existingMethod, method))) {
+      methods.removeIf(existingMethod -> overridesAsDeclared(method, existingMethod));
+      methods.add(method);
+    }
+  }
+
+  /**
+   * Returns {@code true} if {@code overrider} overrides {@code overridden} considered from within
+   * the type that declares {@code overrider}.
+   */
+  // TODO(dpb): Does this break for ECJ?
+  private boolean overridesAsDeclared(ExecutableElement overridder, ExecutableElement overridden) {
+    return elements.overrides(overridder, overridden, asType(overridder.getEnclosingElement()));
+  }
+
+  private void reportConflictingEntryPoints(
+      Collection<ExecutableElement> methods, ValidationReport.Builder<TypeElement> report) {
+    verify(
+        methods.stream().map(ExecutableElement::getEnclosingElement).distinct().count()
+            == methods.size(),
+        "expected each method to be declared on a different type: %s",
+        methods);
+    StringBuilder message = new StringBuilder("conflicting entry point declarations:");
+    methodSignatureFormatter
+        .typedFormatter(asDeclared(report.getSubject().asType()))
+        .formatIndentedList(
+            message,
+            ImmutableList.sortedCopyOf(
+                comparing(
+                    method -> asType(method.getEnclosingElement()).getQualifiedName().toString()),
+                methods),
+            1);
+    report.addError(message.toString());
+  }
+
+  private void validateSubcomponentMethod(
+      final ValidationReport.Builder<TypeElement> report,
+      final ComponentKind subcomponentKind,
+      ExecutableElement method,
+      List<? extends VariableElement> parameters,
+      List<? extends TypeMirror> parameterTypes,
+      TypeMirror returnType,
+      Optional<AnnotationMirror> subcomponentAnnotation) {
+    ImmutableSet<TypeElement> moduleTypes =
+        componentAnnotation(subcomponentAnnotation.get()).modules();
+
+    // TODO(gak): This logic maybe/probably shouldn't live here as it requires us to traverse
+    // subcomponents and their modules separately from how it is done in ComponentDescriptor and
+    // ModuleDescriptor
+    @SuppressWarnings("deprecation")
+    ImmutableSet<TypeElement> transitiveModules =
+        getTransitiveModules(types, elements, moduleTypes);
+
+    Set<TypeElement> variableTypes = Sets.newHashSet();
+
+    for (int i = 0; i < parameterTypes.size(); i++) {
+      VariableElement parameter = parameters.get(i);
+      TypeMirror parameterType = parameterTypes.get(i);
+      Optional<TypeElement> moduleType =
+          parameterType.accept(
+              new SimpleTypeVisitor6<Optional<TypeElement>, Void>() {
+                @Override
+                protected Optional<TypeElement> defaultAction(TypeMirror e, Void p) {
+                  return Optional.empty();
+                }
+
+                @Override
+                public Optional<TypeElement> visitDeclared(DeclaredType t, Void p) {
+                  for (ModuleKind moduleKind : subcomponentKind.legalModuleKinds()) {
+                    if (isAnnotationPresent(t.asElement(), moduleKind.annotation())) {
+                      return Optional.of(MoreTypes.asTypeElement(t));
+                    }
+                  }
+                  return Optional.empty();
+                }
+              },
+              null);
+      if (moduleType.isPresent()) {
+        if (variableTypes.contains(moduleType.get())) {
+          report.addError(
+              String.format(
+                  "A module may only occur once an an argument in a Subcomponent factory "
+                      + "method, but %s was already passed.",
+                  moduleType.get().getQualifiedName()),
+              parameter);
+        }
+        if (!transitiveModules.contains(moduleType.get())) {
+          report.addError(
+              String.format(
+                  "%s is present as an argument to the %s factory method, but is not one of the"
+                      + " modules used to implement the subcomponent.",
+                  moduleType.get().getQualifiedName(),
+                  MoreTypes.asTypeElement(returnType).getQualifiedName()),
+              method);
+        }
+        variableTypes.add(moduleType.get());
+      } else {
+        report.addError(
+            String.format(
+                "Subcomponent factory methods may only accept modules, but %s is not.",
+                parameterType),
+            parameter);
+      }
+    }
+  }
+
+  private void validateSubcomponentCreatorMethod(
+      ValidationReport.Builder<TypeElement> report,
+      ExecutableElement method,
+      List<? extends VariableElement> parameters,
+      TypeMirror returnType,
+      Set<? extends Element> validatedSubcomponentCreators) {
+    if (!parameters.isEmpty()) {
+      report.addError(builderMethodRequiresNoArgs(), method);
+    }
+
+    // If we haven't already validated the subcomponent creator itself, validate it now.
+    TypeElement creatorElement = MoreTypes.asTypeElement(returnType);
+    if (!validatedSubcomponentCreators.contains(creatorElement)) {
+      // TODO(sameb): The creator validator right now assumes the element is being compiled
+      // in this pass, which isn't true here.  We should change error messages to spit out
+      // this method as the subject and add the original subject to the message output.
+      report.addItems(creatorValidator.validate(creatorElement).items());
+    }
+  }
+
+  private static <T extends Element> void validateComponentDependencies(
+      ValidationReport.Builder<T> report, Iterable<TypeMirror> types) {
+    for (TypeMirror type : types) {
+      type.accept(CHECK_DEPENDENCY_TYPES, report);
+    }
+  }
+
+  private static final TypeVisitor<Void, ValidationReport.Builder<?>> CHECK_DEPENDENCY_TYPES =
+      new SimpleTypeVisitor8<Void, ValidationReport.Builder<?>>() {
+        @Override
+        protected Void defaultAction(TypeMirror type, ValidationReport.Builder<?> report) {
+          report.addError(type + " is not a valid component dependency type");
+          return null;
+        }
+
+        @Override
+        public Void visitDeclared(DeclaredType type, ValidationReport.Builder<?> report) {
+          if (moduleAnnotation(MoreTypes.asTypeElement(type)).isPresent()) {
+            report.addError(type + " is a module, which cannot be a component dependency");
+          }
+          return null;
+        }
+      };
+
+  private static Optional<AnnotationMirror> checkForAnnotations(
+      TypeMirror type, final Set<? extends Class<? extends Annotation>> annotations) {
+    return type.accept(
+        new SimpleTypeVisitor6<Optional<AnnotationMirror>, Void>(Optional.empty()) {
+          @Override
+          public Optional<AnnotationMirror> visitDeclared(DeclaredType t, Void p) {
+            return getAnyAnnotation(t.asElement(), annotations);
+          }
+        },
+        null);
+  }
+}
diff --git a/java/dagger/internal/codegen/ConfigurationAnnotations.java b/java/dagger/internal/codegen/ConfigurationAnnotations.java
new file mode 100644
index 0000000..a9bba29
--- /dev/null
+++ b/java/dagger/internal/codegen/ConfigurationAnnotations.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.consumingIterable;
+import static dagger.internal.codegen.ComponentAnnotation.subcomponentAnnotation;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.subcomponentCreatorAnnotations;
+import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
+import static dagger.internal.codegen.MoreAnnotationMirrors.getTypeListValue;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
+import static javax.lang.model.util.ElementFilter.typesIn;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import dagger.Component;
+import dagger.Module;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.lang.annotation.Annotation;
+import java.util.ArrayDeque;
+import java.util.List;
+import java.util.Optional;
+import java.util.Queue;
+import java.util.Set;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Utility methods related to dagger configuration annotations (e.g.: {@link Component}
+ * and {@link Module}).
+ */
+final class ConfigurationAnnotations {
+
+  static Optional<TypeElement> getSubcomponentCreator(TypeElement subcomponent) {
+    checkArgument(subcomponentAnnotation(subcomponent).isPresent());
+    for (TypeElement nestedType : typesIn(subcomponent.getEnclosedElements())) {
+      if (isSubcomponentCreator(nestedType)) {
+        return Optional.of(nestedType);
+      }
+    }
+    return Optional.empty();
+  }
+
+  static boolean isSubcomponentCreator(Element element) {
+    return isAnyAnnotationPresent(element, subcomponentCreatorAnnotations());
+  }
+
+  // Dagger 1 support.
+  static ImmutableList<TypeMirror> getModuleInjects(AnnotationMirror moduleAnnotation) {
+    checkNotNull(moduleAnnotation);
+    return getTypeListValue(moduleAnnotation, "injects");
+  }
+
+  /** Returns the first type that specifies this' nullability, or empty if none. */
+  static Optional<DeclaredType> getNullableType(Element element) {
+    List<? extends AnnotationMirror> mirrors = element.getAnnotationMirrors();
+    for (AnnotationMirror mirror : mirrors) {
+      if (mirror.getAnnotationType().asElement().getSimpleName().contentEquals("Nullable")) {
+        return Optional.of(mirror.getAnnotationType());
+      }
+    }
+    return Optional.empty();
+  }
+
+  /**
+   * Returns the full set of modules transitively {@linkplain Module#includes included} from the
+   * given seed modules. If a module is malformed and a type listed in {@link Module#includes} is
+   * not annotated with {@link Module}, it is ignored.
+   *
+   * @deprecated Use {@link ComponentDescriptor#modules()}.
+   */
+  @Deprecated
+  static ImmutableSet<TypeElement> getTransitiveModules(
+      DaggerTypes types, DaggerElements elements, Iterable<TypeElement> seedModules) {
+    TypeMirror objectType = elements.getTypeElement(Object.class).asType();
+    Queue<TypeElement> moduleQueue = new ArrayDeque<>();
+    Iterables.addAll(moduleQueue, seedModules);
+    Set<TypeElement> moduleElements = Sets.newLinkedHashSet();
+    for (TypeElement moduleElement : consumingIterable(moduleQueue)) {
+      moduleAnnotation(moduleElement)
+          .ifPresent(
+              moduleAnnotation -> {
+                ImmutableSet.Builder<TypeElement> moduleDependenciesBuilder =
+                    ImmutableSet.builder();
+                moduleDependenciesBuilder.addAll(moduleAnnotation.includes());
+                // We don't recur on the parent class because we don't want the parent class as a
+                // root that the component depends on, and also because we want the dependencies
+                // rooted against this element, not the parent.
+                addIncludesFromSuperclasses(
+                    types, moduleElement, moduleDependenciesBuilder, objectType);
+                ImmutableSet<TypeElement> moduleDependencies = moduleDependenciesBuilder.build();
+                moduleElements.add(moduleElement);
+                for (TypeElement dependencyType : moduleDependencies) {
+                  if (!moduleElements.contains(dependencyType)) {
+                    moduleQueue.add(dependencyType);
+                  }
+                }
+              });
+    }
+    return ImmutableSet.copyOf(moduleElements);
+  }
+
+  /** Returns the enclosed types annotated with the given annotation. */
+  static ImmutableList<DeclaredType> enclosedAnnotatedTypes(
+      TypeElement typeElement, Class<? extends Annotation> annotation) {
+    final ImmutableList.Builder<DeclaredType> builders = ImmutableList.builder();
+    for (TypeElement element : typesIn(typeElement.getEnclosedElements())) {
+      if (MoreElements.isAnnotationPresent(element, annotation)) {
+        builders.add(MoreTypes.asDeclared(element.asType()));
+      }
+    }
+    return builders.build();
+  }
+
+  /** Traverses includes from superclasses and adds them into the builder. */
+  private static void addIncludesFromSuperclasses(
+      DaggerTypes types,
+      TypeElement element,
+      ImmutableSet.Builder<TypeElement> builder,
+      TypeMirror objectType) {
+    // Also add the superclass to the queue, in case any @Module definitions were on that.
+    TypeMirror superclass = element.getSuperclass();
+    while (!types.isSameType(objectType, superclass)
+        && superclass.getKind().equals(TypeKind.DECLARED)) {
+      element = MoreElements.asType(types.asElement(superclass));
+      moduleAnnotation(element)
+          .ifPresent(moduleAnnotation -> builder.addAll(moduleAnnotation.includes()));
+      superclass = element.getSuperclass();
+    }
+  }
+
+  private ConfigurationAnnotations() {}
+}
diff --git a/java/dagger/internal/codegen/ContributionBinding.java b/java/dagger/internal/codegen/ContributionBinding.java
new file mode 100644
index 0000000..0958bc8
--- /dev/null
+++ b/java/dagger/internal/codegen/ContributionBinding.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.CLASS_CONSTRUCTOR;
+import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.DELEGATE;
+import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
+import static dagger.internal.codegen.MapKeys.unwrapValue;
+import static dagger.internal.codegen.MoreAnnotationMirrors.unwrapOptionalEquivalence;
+import static java.util.Arrays.asList;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.base.Equivalence;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.errorprone.annotations.CheckReturnValue;
+import dagger.internal.codegen.ContributionType.HasContributionType;
+import dagger.model.BindingKind;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * An abstract class for a value object representing the mechanism by which a {@link Key} can be
+ * contributed to a dependency graph.
+ */
+abstract class ContributionBinding extends Binding implements HasContributionType {
+
+  /** Returns the type that specifies this' nullability, absent if not nullable. */
+  abstract Optional<DeclaredType> nullableType();
+
+  abstract Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedMapKeyAnnotation();
+
+  final Optional<AnnotationMirror> mapKeyAnnotation() {
+    return unwrapOptionalEquivalence(wrappedMapKeyAnnotation());
+  }
+
+  /**
+   * If this is a map contribution, returns the key of its map entry.
+   *
+   * @throws IllegalStateException if {@link #mapKeyAnnotation()} returns an empty value.
+   */
+  final Object mapKey() {
+    checkState(mapKeyAnnotation().isPresent());
+    AnnotationMirror mapKeyAnnotation = mapKeyAnnotation().get();
+    return unwrapValue(mapKeyAnnotation).map(AnnotationValue::getValue).orElse(mapKeyAnnotation);
+  }
+
+  /** If {@link #bindingElement()} is a method that returns a primitive type, returns that type. */
+  final Optional<TypeMirror> contributedPrimitiveType() {
+    return bindingElement()
+        .filter(bindingElement -> bindingElement instanceof ExecutableElement)
+        .map(bindingElement -> MoreElements.asExecutable(bindingElement).getReturnType())
+        .filter(type -> type.getKind().isPrimitive());
+  }
+
+  @Override
+  public final boolean isNullable() {
+    return nullableType().isPresent();
+  }
+
+  /**
+   * The strategy for getting an instance of a factory for a {@link ContributionBinding}.
+   */
+  enum FactoryCreationStrategy {
+    /** The factory class is a single instance. */
+    SINGLETON_INSTANCE,
+    /** The factory must be created by calling the constructor. */
+    CLASS_CONSTRUCTOR,
+    /** The factory is simply delegated to another. */
+    DELEGATE,
+  }
+
+  /**
+   * Returns the {@link FactoryCreationStrategy} appropriate for a binding.
+   *
+   * <p>Delegate bindings use the {@link FactoryCreationStrategy#DELEGATE} strategy.
+   *
+   * <p>Bindings without dependencies that don't require a module instance use the {@link
+   * FactoryCreationStrategy#SINGLETON_INSTANCE} strategy.
+   *
+   * <p>All other bindings use the {@link FactoryCreationStrategy#CLASS_CONSTRUCTOR} strategy.
+   */
+  final FactoryCreationStrategy factoryCreationStrategy() {
+    switch (kind()) {
+      case DELEGATE:
+        return DELEGATE;
+      case PROVISION:
+        return dependencies().isEmpty() && !requiresModuleInstance()
+            ? SINGLETON_INSTANCE
+            : CLASS_CONSTRUCTOR;
+      case INJECTION:
+      case MULTIBOUND_SET:
+      case MULTIBOUND_MAP:
+        return dependencies().isEmpty() ? SINGLETON_INSTANCE : CLASS_CONSTRUCTOR;
+      default:
+        return CLASS_CONSTRUCTOR;
+    }
+  }
+
+  /**
+   * The {@link TypeMirror type} for the {@code Factory<T>} or {@code Producer<T>} which is created
+   * for this binding. Uses the binding's key, V in the case of {@code Map<K, FrameworkClass<V>>>},
+   * and E {@code Set<E>} for {@link dagger.multibindings.IntoSet @IntoSet} methods.
+   */
+  final TypeMirror contributedType() {
+    switch (contributionType()) {
+      case MAP:
+        return MapType.from(key()).unwrappedFrameworkValueType();
+      case SET:
+        return SetType.from(key()).elementType();
+      case SET_VALUES:
+      case UNIQUE:
+        return key().type();
+    }
+    throw new AssertionError();
+  }
+
+  final boolean isSyntheticMultibinding() {
+    switch (kind()) {
+      case MULTIBOUND_SET:
+      case MULTIBOUND_MAP:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  /** Whether the bound type has a generated implementation. */
+  final boolean requiresGeneratedInstance() {
+    switch (kind()) {
+      case COMPONENT:
+      case SUBCOMPONENT_CREATOR:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  /**
+   * Returns {@link BindingKind#MULTIBOUND_SET} or {@link
+   * BindingKind#MULTIBOUND_MAP} if the key is a set or map.
+   *
+   * @throws IllegalArgumentException if {@code key} is neither a set nor a map
+   */
+  static BindingKind bindingKindForMultibindingKey(Key key) {
+    if (SetType.isSet(key)) {
+      return BindingKind.MULTIBOUND_SET;
+    } else if (MapType.isMap(key)) {
+      return BindingKind.MULTIBOUND_MAP;
+    } else {
+      throw new IllegalArgumentException(String.format("key is not for a set or map: %s", key));
+    }
+  }
+
+  /**
+   * Base builder for {@link com.google.auto.value.AutoValue @AutoValue} subclasses of {@link
+   * ContributionBinding}.
+   */
+  @CanIgnoreReturnValue
+  abstract static class Builder<C extends ContributionBinding, B extends Builder<C, B>> {
+    abstract B dependencies(Iterable<DependencyRequest> dependencies);
+
+    B dependencies(DependencyRequest... dependencies) {
+      return dependencies(asList(dependencies));
+    }
+
+    abstract B unresolved(C unresolved);
+
+    abstract B contributionType(ContributionType contributionType);
+
+    abstract B bindingElement(Element bindingElement);
+
+    abstract B contributingModule(TypeElement contributingModule);
+
+    abstract B key(Key key);
+
+    abstract B nullableType(Optional<DeclaredType> nullableType);
+
+    abstract B wrappedMapKeyAnnotation(
+        Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedMapKeyAnnotation);
+
+    abstract B kind(BindingKind kind);
+
+    @CheckReturnValue
+    abstract C build();
+  }
+}
diff --git a/java/dagger/internal/codegen/ContributionType.java b/java/dagger/internal/codegen/ContributionType.java
new file mode 100644
index 0000000..66b5289
--- /dev/null
+++ b/java/dagger/internal/codegen/ContributionType.java
@@ -0,0 +1,67 @@
+/*
+ * 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.MoreElements.isAnnotationPresent;
+
+import dagger.Provides;
+import dagger.multibindings.ElementsIntoSet;
+import dagger.multibindings.IntoMap;
+import dagger.multibindings.IntoSet;
+import javax.lang.model.element.Element;
+
+/** Whether a binding or declaration is for a unique contribution or a map or set multibinding. */
+enum ContributionType {
+  /** Represents map bindings. */
+  MAP,
+  /** Represents set bindings. */
+  SET,
+  /** Represents set values bindings. */
+  SET_VALUES,
+  /** Represents a valid non-collection binding. */
+  UNIQUE,
+  ;
+
+  /** An object that is associated with a {@link ContributionType}. */
+  interface HasContributionType {
+
+    /** The contribution type of this object. */
+    ContributionType contributionType();
+  }
+
+  /** {@code true} if this is for a multibinding. */
+  boolean isMultibinding() {
+    return !this.equals(UNIQUE);
+  }
+
+  /**
+   * The contribution type from a binding element's annotations. Presumes a well-formed binding
+   * element (at most one of @IntoSet, @IntoMap, @ElementsIntoSet and @Provides.type). {@link
+   * BindingMethodValidator} and {@link BindsInstanceProcessingStep} validate correctness on their
+   * own.
+   */
+  static ContributionType fromBindingElement(Element element) {
+    if (isAnnotationPresent(element, IntoMap.class)) {
+      return ContributionType.MAP;
+    } else if (isAnnotationPresent(element, IntoSet.class)) {
+      return ContributionType.SET;
+    } else if (isAnnotationPresent(element, ElementsIntoSet.class)) {
+      return ContributionType.SET_VALUES;
+    }
+    return ContributionType.UNIQUE;
+  }
+}
diff --git a/java/dagger/internal/codegen/CurrentImplementationSubcomponent.java b/java/dagger/internal/codegen/CurrentImplementationSubcomponent.java
new file mode 100644
index 0000000..c78d60d
--- /dev/null
+++ b/java/dagger/internal/codegen/CurrentImplementationSubcomponent.java
@@ -0,0 +1,58 @@
+/*
+ * 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 dagger.BindsInstance;
+import dagger.Subcomponent;
+import dagger.internal.codegen.ComponentImplementationBuilder.RootComponentImplementationBuilder;
+import dagger.internal.codegen.ComponentImplementationBuilder.SubcomponentImplementationBuilder;
+import java.util.Optional;
+
+/**
+ * A subcomponent that injects all objects that are responsible for creating a single {@link
+ * ComponentImplementation} instance. Each child {@link ComponentImplementation} will have its own
+ * instance of {@link CurrentImplementationSubcomponent}.
+ */
+@Subcomponent(modules = GenerationOptionsModule.class)
+@PerComponentImplementation
+interface CurrentImplementationSubcomponent {
+  RootComponentImplementationBuilder rootComponentBuilder();
+
+  SubcomponentImplementationBuilder subcomponentBuilder();
+
+  @Subcomponent.Builder
+  interface Builder {
+    @BindsInstance
+    Builder componentImplementation(ComponentImplementation componentImplementation);
+
+    @BindsInstance
+    Builder bindingGraph(BindingGraph bindingGraph);
+
+    @BindsInstance
+    Builder parentBuilder(@ParentComponent Optional<ComponentImplementationBuilder> parentBuilder);
+
+    @BindsInstance
+    Builder parentBindingExpressions(
+        @ParentComponent Optional<ComponentBindingExpressions> parentBindingExpressions);
+
+    @BindsInstance
+    Builder parentRequirementExpressions(
+        @ParentComponent Optional<ComponentRequirementExpressions> parentRequirementExpressions);
+
+    CurrentImplementationSubcomponent build();
+  }
+}
diff --git a/java/dagger/internal/codegen/DaggerGraphs.java b/java/dagger/internal/codegen/DaggerGraphs.java
new file mode 100644
index 0000000..dda6c11
--- /dev/null
+++ b/java/dagger/internal/codegen/DaggerGraphs.java
@@ -0,0 +1,98 @@
+/*
+ * 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.common.collect.Sets.difference;
+import static com.google.common.graph.Graphs.reachableNodes;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.graph.Graph;
+import com.google.common.graph.SuccessorsFunction;
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+/** Utility methods for {@link com.google.common.graph} types. */
+public final class DaggerGraphs {
+  /**
+   * Returns a shortest path from {@code nodeU} to {@code nodeV} in {@code graph} as a list of the
+   * nodes visited in sequence, including both {@code nodeU} and {@code nodeV}. (Note that there may
+   * be many possible shortest paths.)
+   *
+   * <p>If {@code nodeV} is not {@link
+   * com.google.common.graph.Graphs#reachableNodes(com.google.common.graph.Graph, Object) reachable}
+   * from {@code nodeU}, the list returned is empty.
+   *
+   * @throws IllegalArgumentException if {@code nodeU} or {@code nodeV} is not present in {@code
+   *     graph}
+   */
+  public static <N> ImmutableList<N> shortestPath(SuccessorsFunction<N> graph, N nodeU, N nodeV) {
+    if (nodeU.equals(nodeV)) {
+      return ImmutableList.of(nodeU);
+    }
+    Set<N> successors = ImmutableSet.copyOf(graph.successors(nodeU));
+    if (successors.contains(nodeV)) {
+      return ImmutableList.of(nodeU, nodeV);
+    }
+
+    Map<N, N> visitedNodeToPathPredecessor = new HashMap<>(); // encodes shortest path tree
+    for (N node : successors) {
+      visitedNodeToPathPredecessor.put(node, nodeU);
+    }
+    Queue<N> currentNodes = new ArrayDeque<N>(successors);
+    Queue<N> nextNodes = new ArrayDeque<N>();
+
+    // Perform a breadth-first traversal starting with the successors of nodeU.
+    while (!currentNodes.isEmpty()) {
+      while (!currentNodes.isEmpty()) {
+        N currentNode = currentNodes.remove();
+        for (N nextNode : graph.successors(currentNode)) {
+          if (visitedNodeToPathPredecessor.containsKey(nextNode)) {
+            continue; // we already have a shortest path to nextNode
+          }
+          visitedNodeToPathPredecessor.put(nextNode, currentNode);
+          if (nextNode.equals(nodeV)) {
+            ImmutableList.Builder<N> builder = ImmutableList.builder();
+            N node = nodeV;
+            builder.add(node);
+            while (!node.equals(nodeU)) {
+              node = visitedNodeToPathPredecessor.get(node);
+              builder.add(node);
+            }
+            return builder.build().reverse();
+          }
+          nextNodes.add(nextNode);
+        }
+      }
+      Queue<N> emptyQueue = currentNodes;
+      currentNodes = nextNodes;
+      nextNodes = emptyQueue; // reusing empty queue faster than allocating new one
+    }
+
+    return ImmutableList.of();
+  }
+
+  /** Returns the nodes in a graph that are not reachable from a node. */
+  public static <N> ImmutableSet<N> unreachableNodes(Graph<N> graph, N node) {
+    return ImmutableSet.copyOf(difference(graph.nodes(), reachableNodes(graph, node)));
+  }
+
+  private DaggerGraphs() {}
+}
diff --git a/java/dagger/internal/codegen/DaggerKythePlugin.java b/java/dagger/internal/codegen/DaggerKythePlugin.java
new file mode 100644
index 0000000..5a685ef
--- /dev/null
+++ b/java/dagger/internal/codegen/DaggerKythePlugin.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+// This must be in the dagger.internal.codegen package since Dagger doesn't expose its APIs publicly
+// https://github.com/google/dagger/issues/773 could present an opportunity to put this somewhere in
+// the regular kythe/java tree.
+package dagger.internal.codegen;
+
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
+
+import com.google.auto.service.AutoService;
+import com.google.common.collect.Iterables;
+import com.google.devtools.kythe.analyzers.base.EntrySet;
+import com.google.devtools.kythe.analyzers.base.FactEmitter;
+import com.google.devtools.kythe.analyzers.base.KytheEntrySets;
+import com.google.devtools.kythe.analyzers.java.Plugin;
+import com.google.devtools.kythe.proto.Storage.VName;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Context;
+import dagger.BindsInstance;
+import dagger.Component;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.producers.ProductionComponent;
+import java.util.Optional;
+import java.util.logging.Logger;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.lang.model.element.Element;
+
+/**
+ * A plugin which emits nodes and edges for <a href="https://github.com/google/dagger">Dagger</a>
+ * specific code.
+ */
+@AutoService(Plugin.class)
+public class DaggerKythePlugin extends Plugin.Scanner<Void, Void> {
+  // TODO(ronshapiro): use flogger
+  private static final Logger logger = Logger.getLogger(DaggerKythePlugin.class.getCanonicalName());
+  private FactEmitter emitter;
+  @Inject ComponentDescriptorFactory componentDescriptorFactory;
+  @Inject BindingGraphFactory bindingGraphFactory;
+
+  @Override
+  public Void visitClassDef(JCClassDecl tree, Void p) {
+    if (tree.sym != null
+        && isAnyAnnotationPresent(tree.sym, Component.class, ProductionComponent.class)) {
+      addNodesForGraph(
+          bindingGraphFactory.create(
+              componentDescriptorFactory.rootComponentDescriptor(tree.sym), false));
+    }
+    return super.visitClassDef(tree, p);
+  }
+
+  private void addNodesForGraph(BindingGraph graph) {
+    addDependencyEdges(graph);
+    addModuleEdges(graph);
+    addChildComponentEdges(graph);
+
+    graph.subgraphs().forEach(this::addNodesForGraph);
+  }
+
+  private void addDependencyEdges(BindingGraph graph) {
+    for (ResolvedBindings resolvedBinding : graph.resolvedBindings()) {
+      for (Binding binding : resolvedBinding.bindings()) {
+        for (DependencyRequest dependency : binding.explicitDependencies()) {
+          addEdgesForDependencyRequest(dependency, dependency.key(), graph);
+        }
+      }
+    }
+
+    for (ComponentDescriptor.ComponentMethodDescriptor componentMethod :
+        graph.componentDescriptor().componentMethods()) {
+      componentMethod
+          .dependencyRequest()
+          .ifPresent(request -> addEdgesForDependencyRequest(request, request.key(), graph));
+    }
+  }
+
+  /**
+   * Add {@code /inject/satisfiedby} edges from {@code dependency}'s {@link
+   * DependencyRequest#requestElement()} to any {@link BindingDeclaration#bindingElement() binding
+   * elements} that satisfy the request.
+   *
+   * <p>This collapses requests for synthetic bindings so that a request for a multibound key
+   * points to all of the contributions for the multibound object. It does so by recursively calling
+   * this method, with each dependency's key as the {@code targetKey}.
+   */
+  private void addEdgesForDependencyRequest(
+      DependencyRequest dependency, Key targetKey, BindingGraph graph) {
+    if (!dependency.requestElement().isPresent()) {
+      return;
+    }
+    BindingRequest request = bindingRequest(targetKey, dependency.kind());
+    ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
+    for (Binding binding : resolvedBindings.bindings()) {
+      if (binding.bindingElement().isPresent()) {
+        addDependencyEdge(dependency, binding);
+      } else {
+        for (DependencyRequest subsequentDependency : binding.explicitDependencies()) {
+          addEdgesForDependencyRequest(dependency, subsequentDependency.key(), graph);
+        }
+      }
+    }
+    for (BindingDeclaration bindingDeclaration :
+        Iterables.concat(
+            resolvedBindings.multibindingDeclarations(),
+            resolvedBindings.optionalBindingDeclarations())) {
+      addDependencyEdge(dependency, bindingDeclaration);
+    }
+  }
+
+  private void addDependencyEdge(
+      DependencyRequest dependency, BindingDeclaration bindingDeclaration) {
+    Element requestElement = dependency.requestElement().get();
+    Element bindingElement = bindingDeclaration.bindingElement().get();
+    Optional<VName> requestElementNode = jvmNode(requestElement, "request element");
+    Optional<VName> bindingElementNode = jvmNode(bindingElement, "binding element");
+    emitEdge(requestElementNode, "/inject/satisfiedby", bindingElementNode);
+    // TODO(ronshapiro): emit facts about the component that satisfies the edge
+  }
+
+  private void addModuleEdges(BindingGraph graph) {
+    Optional<VName> componentNode = jvmNode(graph.componentTypeElement(), "component");
+    for (ModuleDescriptor module : graph.componentDescriptor().modules()) {
+      Optional<VName> moduleNode = jvmNode(module.moduleElement(), "module");
+      emitEdge(componentNode, "/inject/installsmodule", moduleNode);
+    }
+  }
+
+  private void addChildComponentEdges(BindingGraph graph) {
+    Optional<VName> componentNode = jvmNode(graph.componentTypeElement(), "component");
+    for (BindingGraph subgraph : graph.subgraphs()) {
+      Optional<VName> subcomponentNode =
+          jvmNode(subgraph.componentTypeElement(), "child component");
+      emitEdge(componentNode, "/inject/childcomponent", subcomponentNode);
+    }
+  }
+
+  private Optional<VName> jvmNode(Element element, String name) {
+    Optional<VName> jvmNode = kytheGraph.getJvmNode((Symbol) element).map(KytheNode::getVName);
+    if (!jvmNode.isPresent()) {
+      logger.warning(String.format("Missing JVM node for %s: %s", name, element));
+    }
+    return jvmNode;
+  }
+
+  private void emitEdge(Optional<VName> source, String edgeName, Optional<VName> target) {
+    source.ifPresent(
+        s -> target.ifPresent(t -> new EntrySet.Builder(s, edgeName, t).build().emit(emitter)));
+  }
+
+  @Override
+  public void run(
+      JCCompilationUnit compilationUnit, KytheEntrySets entrySets, KytheGraph kytheGraph) {
+    if (bindingGraphFactory == null) {
+      emitter = entrySets.getEmitter();
+      DaggerDaggerKythePlugin_PluginComponent.builder()
+          .context(kytheGraph.getJavaContext())
+          .build()
+          .inject(this);
+    }
+    super.run(compilationUnit, entrySets, kytheGraph);
+  }
+
+  @Singleton
+  @Component(modules = JavacPluginModule.class)
+  interface PluginComponent {
+    void inject(DaggerKythePlugin plugin);
+
+    @Component.Builder
+    interface Builder {
+      @BindsInstance
+      Builder context(Context context);
+
+      PluginComponent build();
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DaggerStatistics.java b/java/dagger/internal/codegen/DaggerStatistics.java
new file mode 100644
index 0000000..790ec76
--- /dev/null
+++ b/java/dagger/internal/codegen/DaggerStatistics.java
@@ -0,0 +1,90 @@
+/*
+ * 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.common.BasicAnnotationProcessor.ProcessingStep;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import java.time.Duration;
+
+/** Statistics collected over the course of Dagger annotation processing. */
+@AutoValue
+abstract class DaggerStatistics {
+  /** Returns a new {@link Builder}. */
+  static Builder builder() {
+    return new AutoValue_DaggerStatistics.Builder();
+  }
+
+  /** Returns a new {@link RoundStatistics} builder. */
+  static RoundStatistics.Builder roundBuilder() {
+    return new AutoValue_DaggerStatistics_RoundStatistics.Builder();
+  }
+
+  /** Total time spent in Dagger annotation processing. */
+  abstract Duration totalProcessingTime();
+
+  /** List of statistics for processing rounds that the Dagger processor handled. */
+  abstract ImmutableList<RoundStatistics> rounds();
+
+  /** Builder for {@link DaggerStatistics}. */
+  @AutoValue.Builder
+  abstract static class Builder {
+    /** Sets the given duration for the total time spent in Dagger processing. */
+    @CanIgnoreReturnValue
+    abstract Builder setTotalProcessingTime(Duration totalProcessingTime);
+
+    /** Returns a builder for adding processing round statistics. */
+    abstract ImmutableList.Builder<RoundStatistics> roundsBuilder();
+
+    /** Adds the given {@code round} statistics. */
+    @CanIgnoreReturnValue
+    final Builder addRound(RoundStatistics round) {
+      roundsBuilder().add(round);
+      return this;
+    }
+
+    /** Creates a new {@link DaggerStatistics} instance. */
+    abstract DaggerStatistics build();
+  }
+
+  /** Statistics for each processing step in a single processing round. */
+  @AutoValue
+  abstract static class RoundStatistics {
+    /** Map of processing step class to duration of that step for this round. */
+    abstract ImmutableMap<Class<? extends ProcessingStep>, Duration> stepDurations();
+
+    /** Builder for {@link RoundStatistics}. */
+    @AutoValue.Builder
+    abstract static class Builder {
+      /** Returns a builder for adding durations for each processing step for the round. */
+      abstract ImmutableMap.Builder<Class<? extends ProcessingStep>, Duration>
+          stepDurationsBuilder();
+
+      /** Adds the given {@code duration} for the given {@code step}. */
+      @CanIgnoreReturnValue
+      final Builder addStepDuration(ProcessingStep step, Duration duration) {
+        stepDurationsBuilder().put(step.getClass(), duration);
+        return this;
+      }
+
+      /** Creates a new {@link RoundStatistics} instance. */
+      abstract RoundStatistics build();
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DaggerStatisticsCollectingProcessingStep.java b/java/dagger/internal/codegen/DaggerStatisticsCollectingProcessingStep.java
new file mode 100644
index 0000000..51f6fc3
--- /dev/null
+++ b/java/dagger/internal/codegen/DaggerStatisticsCollectingProcessingStep.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 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.common.base.Preconditions.checkNotNull;
+
+import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
+import com.google.common.collect.SetMultimap;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+import javax.lang.model.element.Element;
+
+/**
+ * {@link ProcessingStep} that delegates to another {@code ProcessingStep} and collects timing
+ * statistics for each processing round for that step.
+ */
+final class DaggerStatisticsCollectingProcessingStep implements ProcessingStep {
+
+  private final ProcessingStep delegate;
+  private final DaggerStatisticsCollector statisticsCollector;
+
+  DaggerStatisticsCollectingProcessingStep(
+      ProcessingStep delegate, DaggerStatisticsCollector statisticsCollector) {
+    this.delegate = checkNotNull(delegate);
+    this.statisticsCollector = checkNotNull(statisticsCollector);
+  }
+
+  @Override
+  public Set<? extends Class<? extends Annotation>> annotations() {
+    return delegate.annotations();
+  }
+
+  @Override
+  public Set<? extends Element> process(
+      SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
+    statisticsCollector.stepStarted(delegate);
+    try {
+      return delegate.process(elementsByAnnotation);
+    } finally {
+      statisticsCollector.stepFinished(delegate);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DaggerStatisticsCollector.java b/java/dagger/internal/codegen/DaggerStatisticsCollector.java
new file mode 100644
index 0000000..e14fbb7
--- /dev/null
+++ b/java/dagger/internal/codegen/DaggerStatisticsCollector.java
@@ -0,0 +1,94 @@
+/*
+ * 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.common.base.Preconditions.checkState;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Ticker;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/** Collects {@link DaggerStatistics} over the course of Dagger annotation processing. */
+@Singleton // for state sharing
+final class DaggerStatisticsCollector {
+
+  private final Ticker ticker;
+  private final Stopwatch totalRuntimeStopwatch;
+  private final Map<ProcessingStep, Stopwatch> stepStopwatches = new HashMap<>();
+
+  private final DaggerStatistics.Builder statisticsBuilder = DaggerStatistics.builder();
+  private DaggerStatistics.RoundStatistics.Builder roundBuilder = DaggerStatistics.roundBuilder();
+
+  private final Optional<DaggerStatisticsRecorder> statisticsRecorder;
+
+  @Inject
+  DaggerStatisticsCollector(Ticker ticker, Optional<DaggerStatisticsRecorder> statisticsRecorder) {
+    this.ticker = ticker;
+    this.totalRuntimeStopwatch = Stopwatch.createUnstarted(ticker);
+    this.statisticsRecorder = statisticsRecorder;
+  }
+
+  /** Called when Dagger annotation processing starts. */
+  void processingStarted() {
+    checkState(!totalRuntimeStopwatch.isRunning());
+    totalRuntimeStopwatch.start();
+  }
+
+  /** Called when the given {@code step} starts processing for a round. */
+  void stepStarted(ProcessingStep step) {
+    Stopwatch stopwatch =
+        stepStopwatches.computeIfAbsent(step, unused -> Stopwatch.createUnstarted(ticker));
+    stopwatch.start();
+  }
+
+  /** Called when the given {@code step} finishes processing for a round. */
+  void stepFinished(ProcessingStep step) {
+    Stopwatch stopwatch = stepStopwatches.get(step);
+    roundBuilder.addStepDuration(step, elapsedTime(stopwatch));
+    stopwatch.reset();
+  }
+
+  /** Called when Dagger finishes a processing round. */
+  void roundFinished() {
+    statisticsBuilder.addRound(roundBuilder.build());
+    roundBuilder = DaggerStatistics.roundBuilder();
+  }
+
+  /** Called when Dagger annotation processing completes. */
+  void processingStopped() {
+    checkState(totalRuntimeStopwatch.isRunning());
+    totalRuntimeStopwatch.stop();
+    statisticsBuilder.setTotalProcessingTime(elapsedTime(totalRuntimeStopwatch));
+
+    statisticsRecorder.ifPresent(
+        recorder -> recorder.recordStatistics(statisticsBuilder.build()));
+  }
+
+  @SuppressWarnings("StopwatchNanosToDuration") // intentional
+  private Duration elapsedTime(Stopwatch stopwatch) {
+    // Using the java 7 method here as opposed to the Duration-returning version to avoid issues
+    // when other annotation processors rely on java 7's guava
+    return Duration.ofNanos(stopwatch.elapsed(NANOSECONDS));
+  }
+}
diff --git a/java/dagger/internal/codegen/DaggerStatisticsRecorder.java b/java/dagger/internal/codegen/DaggerStatisticsRecorder.java
new file mode 100644
index 0000000..66f41d1
--- /dev/null
+++ b/java/dagger/internal/codegen/DaggerStatisticsRecorder.java
@@ -0,0 +1,23 @@
+/*
+ * 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;
+
+/** Records collected {@link DaggerStatistics}. */
+interface DaggerStatisticsRecorder {
+  /** Records the given {@code statistics}. */
+  void recordStatistics(DaggerStatistics statistics);
+}
diff --git a/java/dagger/internal/codegen/DaggerStreams.java b/java/dagger/internal/codegen/DaggerStreams.java
new file mode 100644
index 0000000..50d17a6
--- /dev/null
+++ b/java/dagger/internal/codegen/DaggerStreams.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2013 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 java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.toList;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Maps;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+/** Utilities for streams. */
+public final class DaggerStreams {
+
+  /**
+   * Returns a {@link Collector} that accumulates the input elements into a new {@link
+   * ImmutableList}, in encounter order.
+   */
+  // TODO(b/68008628): Use ImmutableList.toImmutableList().
+  public static <T> Collector<T, ?, ImmutableList<T>> toImmutableList() {
+    return collectingAndThen(toList(), ImmutableList::copyOf);
+  }
+
+  /**
+   * Returns a {@link Collector} that accumulates the input elements into a new {@link
+   * ImmutableSet}, in encounter order.
+   */
+  // TODO(b/68008628): Use ImmutableSet.toImmutableSet().
+  public static <T> Collector<T, ?, ImmutableSet<T>> toImmutableSet() {
+    return collectingAndThen(toList(), ImmutableSet::copyOf);
+  }
+
+  /**
+   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys
+   * and values are the result of applying the provided mapping functions to the input elements.
+   * Entries appear in the result {@code ImmutableMap} in encounter order.
+   */
+  // TODO(b/68008628): Use ImmutableMap.toImmutableMap().
+  public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
+      Function<? super T, K> keyMapper, Function<? super T, V> valueMapper) {
+    return Collectors.mapping(
+        value -> Maps.immutableEntry(keyMapper.apply(value), valueMapper.apply(value)),
+        Collector.of(
+            ImmutableMap::builder,
+            (ImmutableMap.Builder<K, V> builder, Map.Entry<K, V> entry) -> builder.put(entry),
+            (left, right) -> left.putAll(right.build()),
+            ImmutableMap.Builder::build));
+  }
+
+  /**
+   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSetMultimap}
+   * whose keys and values are the result of applying the provided mapping functions to the input
+   * elements. Entries appear in the result {@code ImmutableSetMultimap} in encounter order.
+   */
+  // TODO(b/68008628): Use ImmutableSetMultimap.toImmutableSetMultimap().
+  public static <T, K, V> Collector<T, ?, ImmutableSetMultimap<K, V>> toImmutableSetMultimap(
+      Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
+    return Collectors.mapping(
+        value -> Maps.immutableEntry(keyMapper.apply(value), valueMapper.apply(value)),
+        Collector.of(
+            ImmutableSetMultimap::builder,
+            (ImmutableSetMultimap.Builder<K, V> builder, Map.Entry<K, V> entry) ->
+                builder.put(entry),
+            (left, right) -> left.putAll(right.build()),
+            ImmutableSetMultimap.Builder::build));
+  }
+
+  /**
+   * Returns a function from {@link Object} to {@code Stream<T>}, which returns a stream containing
+   * its input if its input is an instance of {@code T}.
+   *
+   * <p>Use as an argument to {@link Stream#flatMap(Function)}:
+   *
+   * <pre>{@code Stream<Bar>} barStream = fooStream.flatMap(instancesOf(Bar.class));</pre>
+   */
+  public static <T> Function<Object, Stream<T>> instancesOf(Class<T> to) {
+    return f -> to.isInstance(f) ? Stream.of(to.cast(f)) : Stream.empty();
+  }
+
+  /** Returns a stream of all values of the given {@code enumType}. */
+  public static <E extends Enum<E>> Stream<E> valuesOf(Class<E> enumType) {
+    return EnumSet.allOf(enumType).stream();
+  }
+
+  /**
+   * A function that you can use to extract the present values from a stream of {@link Optional}s.
+   *
+   * <pre>{@code
+   * Set<Foo> foos =
+   *     optionalFoos()
+   *         .flatMap(DaggerStreams.presentValues())
+   *         .collect(toSet());
+   * }</pre>
+   */
+  public static <T> Function<Optional<T>, Stream<T>> presentValues() {
+    return optional -> optional.map(Stream::of).orElse(Stream.empty());
+  }
+
+  /**
+   * Returns a sequential {@link Stream} of the contents of {@code iterable}, delegating to {@link
+   * Collection#stream} if possible.
+   */
+  public static <T> Stream<T> stream(Iterable<T> iterable) {
+    return (iterable instanceof Collection)
+        ? ((Collection<T>) iterable).stream()
+        : StreamSupport.stream(iterable.spliterator(), false);
+  }
+
+  private DaggerStreams() {}
+}
diff --git a/java/dagger/internal/codegen/DeferredModifiableBindingExpression.java b/java/dagger/internal/codegen/DeferredModifiableBindingExpression.java
new file mode 100644
index 0000000..c41cf2c
--- /dev/null
+++ b/java/dagger/internal/codegen/DeferredModifiableBindingExpression.java
@@ -0,0 +1,75 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.Optional;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A {@link ModifiableAbstractMethodBindingExpression} for a binding that exists but is not ready to
+ * be expressed in this compilation unit and should be deferred until a future compilation.
+ * Generates a method that will be implemented in the future compilation.
+ *
+ * <p>A deferred modifiable binding expression is used when:
+ *
+ * <ul>
+ *   <li>The generated code for a binding requires an instance of a type that is generated in the
+ *       root component compilation unit.
+ *   <li>A {@linkplain ModifiableBindingType#BINDS_METHOD_WITH_MISSING_DEPENDENCY {@code @Binds}
+ *       method's dependency is missing} in a subcomponent.
+ * </ul>
+ */
+final class DeferredModifiableBindingExpression extends ModifiableAbstractMethodBindingExpression {
+  private final ComponentImplementation componentImplementation;
+  private final ContributionBinding binding;
+  private final BindingRequest request;
+
+  DeferredModifiableBindingExpression(
+      ComponentImplementation componentImplementation,
+      ModifiableBindingType modifiableBindingType,
+      ContributionBinding binding,
+      BindingRequest request,
+      Optional<ModifiableBindingMethod> matchingModifiableBindingMethod,
+      Optional<ComponentMethodDescriptor> matchingComponentMethod,
+      DaggerTypes types) {
+    super(
+        componentImplementation,
+        modifiableBindingType,
+        request,
+        matchingModifiableBindingMethod,
+        matchingComponentMethod,
+        types);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.binding = checkNotNull(binding);
+    this.request = checkNotNull(request);
+  }
+
+  @Override
+  String chooseMethodName() {
+    return componentImplementation.getUniqueMethodName(request);
+  }
+
+  @Override
+  protected TypeMirror contributedType() {
+    return binding.contributedType();
+  }
+}
diff --git a/java/dagger/internal/codegen/DelegateBindingExpression.java b/java/dagger/internal/codegen/DelegateBindingExpression.java
new file mode 100644
index 0000000..8cdf6d1
--- /dev/null
+++ b/java/dagger/internal/codegen/DelegateBindingExpression.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.RequestKinds.requestType;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static dagger.model.BindingKind.DELEGATE;
+
+import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.RequestKind;
+import javax.lang.model.type.TypeMirror;
+
+/** A {@link BindingExpression} for {@code @Binds} methods. */
+final class DelegateBindingExpression extends BindingExpression {
+  private final ContributionBinding binding;
+  private final RequestKind requestKind;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final DaggerTypes types;
+  private final BindsTypeChecker bindsTypeChecker;
+
+  DelegateBindingExpression(
+      ResolvedBindings resolvedBindings,
+      RequestKind requestKind,
+      ComponentBindingExpressions componentBindingExpressions,
+      DaggerTypes types,
+      DaggerElements elements) {
+    this.binding = checkNotNull(resolvedBindings.contributionBinding());
+    this.requestKind = checkNotNull(requestKind);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+    this.types = checkNotNull(types);
+    this.bindsTypeChecker = new BindsTypeChecker(types, elements);
+  }
+
+  /**
+   * Returns {@code true} if the {@code @Binds} binding's scope is stronger than the scope of the
+   * binding it depends on.
+   */
+  static boolean isBindsScopeStrongerThanDependencyScope(
+      ResolvedBindings resolvedBindings, BindingGraph graph) {
+    ContributionBinding bindsBinding = resolvedBindings.contributionBinding();
+    checkArgument(bindsBinding.kind().equals(DELEGATE));
+    Binding dependencyBinding =
+        graph
+            .contributionBindings()
+            .get(getOnlyElement(bindsBinding.dependencies()).key())
+            .binding();
+    ScopeKind bindsScope = ScopeKind.get(bindsBinding, graph);
+    ScopeKind dependencyScope = ScopeKind.get(dependencyBinding, graph);
+    return bindsScope.isStrongerScopeThan(dependencyScope);
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    Expression delegateExpression =
+        componentBindingExpressions.getDependencyExpression(
+            bindingRequest(getOnlyElement(binding.dependencies()).key(), requestKind),
+            requestingClass);
+
+    TypeMirror contributedType = binding.contributedType();
+    switch (requestKind) {
+      case INSTANCE:
+        return instanceRequiresCast(delegateExpression, requestingClass)
+            ? delegateExpression.castTo(contributedType)
+            : delegateExpression;
+      default:
+        return castToRawTypeIfNecessary(
+            delegateExpression, requestType(requestKind, contributedType, types));
+    }
+  }
+
+  private boolean instanceRequiresCast(Expression delegateExpression, ClassName requestingClass) {
+    // delegateExpression.type() could be Object if expression is satisfied with a raw
+    // Provider's get() method.
+    return !bindsTypeChecker.isAssignable(
+        delegateExpression.type(), binding.contributedType(), binding.contributionType())
+        && isTypeAccessibleFrom(binding.contributedType(), requestingClass.packageName());
+  }
+
+  /**
+   * If {@code delegateExpression} can be assigned to {@code desiredType} safely, then {@code
+   * delegateExpression} is returned unchanged. If the {@code delegateExpression} is already a raw
+   * type, returns {@code delegateExpression} as well, as casting would have no effect. Otherwise,
+   * returns a {@link Expression#castTo(TypeMirror) casted} version of {@code delegateExpression}
+   * to the raw type of {@code desiredType}.
+   */
+  // TODO(ronshapiro): this probably can be generalized for usage in InjectionMethods
+  private Expression castToRawTypeIfNecessary(
+      Expression delegateExpression, TypeMirror desiredType) {
+    if (types.isAssignable(delegateExpression.type(), desiredType)) {
+      return delegateExpression;
+    }
+    return delegateExpression.castTo(types.erasure(desiredType));
+  }
+
+  private enum ScopeKind {
+    UNSCOPED,
+    SINGLE_CHECK,
+    DOUBLE_CHECK,
+    ;
+
+    static ScopeKind get(Binding binding, BindingGraph graph) {
+      return binding
+          .scope()
+          .map(scope -> scope.isReusable() ? SINGLE_CHECK : DOUBLE_CHECK)
+          .orElse(UNSCOPED);
+    }
+
+    boolean isStrongerScopeThan(ScopeKind other) {
+      return this.ordinal() > other.ordinal();
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DelegateDeclaration.java b/java/dagger/internal/codegen/DelegateDeclaration.java
new file mode 100644
index 0000000..67991de
--- /dev/null
+++ b/java/dagger/internal/codegen/DelegateDeclaration.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.MapKeys.getMapKey;
+import static dagger.internal.codegen.MoreAnnotationMirrors.wrapOptionalInEquivalence;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.base.Equivalence;
+import com.google.common.collect.Iterables;
+import dagger.Binds;
+import dagger.internal.codegen.ContributionType.HasContributionType;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.ExecutableType;
+
+/**
+ * The declaration for a delegate binding established by a {@link Binds} method.
+ */
+@AutoValue
+abstract class DelegateDeclaration extends BindingDeclaration implements HasContributionType {
+  abstract DependencyRequest delegateRequest();
+
+  abstract Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedMapKey();
+
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  @Override
+  public abstract boolean equals(Object obj);
+
+  static final class Factory {
+    private final DaggerTypes types;
+    private final KeyFactory keyFactory;
+    private final DependencyRequestFactory dependencyRequestFactory;
+
+    @Inject
+    Factory(
+        DaggerTypes types,
+        KeyFactory keyFactory,
+        DependencyRequestFactory dependencyRequestFactory) {
+      this.types = types;
+      this.keyFactory = keyFactory;
+      this.dependencyRequestFactory = dependencyRequestFactory;
+    }
+
+    DelegateDeclaration create(
+        ExecutableElement bindsMethod, TypeElement contributingModule) {
+      checkArgument(MoreElements.isAnnotationPresent(bindsMethod, Binds.class));
+      ExecutableType resolvedMethod =
+          MoreTypes.asExecutable(
+              types.asMemberOf(MoreTypes.asDeclared(contributingModule.asType()), bindsMethod));
+      DependencyRequest delegateRequest =
+          dependencyRequestFactory.forRequiredResolvedVariable(
+              Iterables.getOnlyElement(bindsMethod.getParameters()),
+              Iterables.getOnlyElement(resolvedMethod.getParameterTypes()));
+      return new AutoValue_DelegateDeclaration(
+          ContributionType.fromBindingElement(bindsMethod),
+          keyFactory.forBindsMethod(bindsMethod, contributingModule),
+          Optional.<Element>of(bindsMethod),
+          Optional.of(contributingModule),
+          delegateRequest,
+          wrapOptionalInEquivalence(getMapKey(bindsMethod)));
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java b/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java
new file mode 100644
index 0000000..7524cdf
--- /dev/null
+++ b/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java
@@ -0,0 +1,56 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.model.DependencyRequest;
+
+/** A framework instance creation expression for a {@link dagger.Binds @Binds} binding. */
+final class DelegatingFrameworkInstanceCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final ContributionBinding binding;
+  private final ComponentImplementation componentImplementation;
+  private final ComponentBindingExpressions componentBindingExpressions;
+
+  DelegatingFrameworkInstanceCreationExpression(
+      ContributionBinding binding,
+      ComponentImplementation componentImplementation,
+      ComponentBindingExpressions componentBindingExpressions) {
+    this.binding = checkNotNull(binding);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    DependencyRequest dependency = getOnlyElement(binding.dependencies());
+    return CodeBlocks.cast(
+        componentBindingExpressions
+            .getDependencyExpression(
+                bindingRequest(dependency.key(), binding.frameworkType()),
+                componentImplementation.name())
+            .codeBlock(),
+        binding.frameworkType().frameworkClass());
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyCycleValidator.java b/java/dagger/internal/codegen/DependencyCycleValidator.java
new file mode 100644
index 0000000..d5d4b62
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyCycleValidator.java
@@ -0,0 +1,319 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.getLast;
+import static com.google.common.collect.Iterables.limit;
+import static com.google.common.collect.Iterables.skip;
+import static com.google.common.collect.Sets.newHashSetWithExpectedSize;
+import static dagger.internal.codegen.DaggerGraphs.shortestPath;
+import static dagger.internal.codegen.DaggerStreams.instancesOf;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.RequestKinds.extractKeyType;
+import static dagger.internal.codegen.RequestKinds.getRequestKind;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.graph.EndpointPair;
+import com.google.common.graph.ImmutableNetwork;
+import com.google.common.graph.MutableNetwork;
+import com.google.common.graph.NetworkBuilder;
+import dagger.model.BindingGraph;
+import dagger.model.BindingGraph.ComponentNode;
+import dagger.model.BindingGraph.DependencyEdge;
+import dagger.model.BindingGraph.Node;
+import dagger.model.BindingKind;
+import dagger.model.DependencyRequest;
+import dagger.model.RequestKind;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.lang.model.type.TypeMirror;
+
+/** Reports errors for dependency cycles. */
+final class DependencyCycleValidator implements BindingGraphPlugin {
+
+  private final DependencyRequestFormatter dependencyRequestFormatter;
+
+  @Inject
+  DependencyCycleValidator(DependencyRequestFormatter dependencyRequestFormatter) {
+    this.dependencyRequestFormatter = dependencyRequestFormatter;
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/DependencyCycle";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    ImmutableNetwork<Node, DependencyEdge> dependencyGraph =
+        nonCycleBreakingDependencyGraph(bindingGraph);
+    // Check each endpoint pair only once, no matter how many parallel edges connect them.
+    Set<EndpointPair<Node>> dependencyEndpointPairs = dependencyGraph.asGraph().edges();
+    Set<EndpointPair<Node>> visited = newHashSetWithExpectedSize(dependencyEndpointPairs.size());
+    for (EndpointPair<Node> endpointPair : dependencyEndpointPairs) {
+      cycleContainingEndpointPair(endpointPair, dependencyGraph, visited)
+          .ifPresent(cycle -> reportCycle(cycle, bindingGraph, diagnosticReporter));
+    }
+  }
+
+  private Optional<Cycle<Node>> cycleContainingEndpointPair(
+      EndpointPair<Node> endpoints,
+      ImmutableNetwork<Node, DependencyEdge> dependencyGraph,
+      Set<EndpointPair<Node>> visited) {
+    if (!visited.add(endpoints)) {
+      // don't recheck endpoints we already know are part of a cycle
+      return Optional.empty();
+    }
+
+    // If there's a path from the target back to the source, there's a cycle.
+    ImmutableList<Node> cycleNodes =
+        shortestPath(dependencyGraph, endpoints.target(), endpoints.source());
+    if (cycleNodes.isEmpty()) {
+      return Optional.empty();
+    }
+
+    Cycle<Node> cycle = Cycle.fromPath(cycleNodes);
+    visited.addAll(cycle.endpointPairs()); // no need to check any edge in this cycle again
+    return Optional.of(cycle);
+  }
+
+  /**
+   * Reports a dependency cycle at the dependency into the cycle that is closest to an entry point.
+   *
+   * <p>For cycles found in reachable binding graphs, looks for the shortest path from the component
+   * that contains the cycle (all bindings in a cycle must be in the same component; see below) to
+   * some binding in the cycle. Then looks for the last dependency in that path that is not in the
+   * cycle; that is the dependency that will be reported, so that the dependency trace will end just
+   * before the cycle.
+   *
+   * <p>For cycles found during full binding graph validation, just reports the component that
+   * contains the cycle.
+   *
+   * <p>Proof (by counterexample) that all bindings in a cycle must be in the same component: Assume
+   * one binding in the cycle is in a parent component. Bindings cannot depend on bindings in child
+   * components, so that binding cannot depend on the next binding in the cycle.
+   */
+  private void reportCycle(
+      Cycle<Node> cycle, BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    if (bindingGraph.isFullBindingGraph()) {
+      diagnosticReporter.reportComponent(
+          ERROR,
+          bindingGraph.componentNode(cycle.nodes().asList().get(0).componentPath()).get(),
+          errorMessage(cycle, bindingGraph));
+      return;
+    }
+
+    ImmutableList<Node> path = shortestPathToCycleFromAnEntryPoint(cycle, bindingGraph);
+    Node cycleStartNode = path.get(path.size() - 1);
+    Node previousNode = path.get(path.size() - 2);
+    DependencyEdge dependencyToReport =
+        chooseDependencyEdgeConnecting(previousNode, cycleStartNode, bindingGraph);
+    diagnosticReporter.reportDependency(
+        ERROR, dependencyToReport, errorMessage(cycle.shift(cycleStartNode), bindingGraph));
+  }
+
+  private ImmutableList<Node> shortestPathToCycleFromAnEntryPoint(
+      Cycle<Node> cycle, BindingGraph bindingGraph) {
+    Node someCycleNode = cycle.nodes().asList().get(0);
+    ComponentNode componentContainingCycle =
+        bindingGraph.componentNode(someCycleNode.componentPath()).get();
+    ImmutableList<Node> pathToCycle =
+        shortestPath(bindingGraph.network(), componentContainingCycle, someCycleNode);
+    return subpathToCycle(pathToCycle, cycle);
+  }
+
+  /**
+   * Returns the subpath from the head of {@code path} to the first node in {@code path} that's in
+   * the cycle.
+   */
+  private ImmutableList<Node> subpathToCycle(ImmutableList<Node> path, Cycle<Node> cycle) {
+    ImmutableList.Builder<Node> subpath = ImmutableList.builder();
+    for (Node node : path) {
+      subpath.add(node);
+      if (cycle.nodes().contains(node)) {
+        return subpath.build();
+      }
+    }
+    throw new IllegalArgumentException(
+        "path " + path + " doesn't contain any nodes in cycle " + cycle);
+  }
+
+  private String errorMessage(Cycle<Node> cycle, BindingGraph graph) {
+    StringBuilder message = new StringBuilder("Found a dependency cycle:");
+    ImmutableList<DependencyRequest> cycleRequests =
+        cycle.endpointPairs().stream()
+            // TODO(dpb): Would be nice to take the dependency graph here.
+            .map(endpointPair -> nonCycleBreakingEdge(endpointPair, graph))
+            .map(DependencyEdge::dependencyRequest)
+            .collect(toImmutableList())
+            .reverse();
+    dependencyRequestFormatter.formatIndentedList(message, cycleRequests, 0);
+    return message.toString();
+  }
+
+  /**
+   * Returns one of the edges between two nodes that doesn't {@linkplain
+   * #breaksCycle(DependencyEdge, BindingGraph) break} a cycle.
+   */
+  private DependencyEdge nonCycleBreakingEdge(EndpointPair<Node> endpointPair, BindingGraph graph) {
+    return graph.network().edgesConnecting(endpointPair.source(), endpointPair.target()).stream()
+        .flatMap(instancesOf(DependencyEdge.class))
+        .filter(edge -> !breaksCycle(edge, graph))
+        .findFirst()
+        .get();
+  }
+
+  private boolean breaksCycle(DependencyEdge edge, BindingGraph graph) {
+    if (edge.dependencyRequest().key().multibindingContributionIdentifier().isPresent()) {
+      return false;
+    }
+    if (breaksCycle(edge.dependencyRequest().key().type(), edge.dependencyRequest().kind())) {
+      return true;
+    }
+    Node target = graph.network().incidentNodes(edge).target();
+    if (target instanceof dagger.model.Binding
+        && ((dagger.model.Binding) target).kind().equals(BindingKind.OPTIONAL)) {
+      /* For @BindsOptionalOf bindings, unwrap the type inside the Optional. If the unwrapped type
+       * breaks the cycle, so does the optional binding. */
+      TypeMirror optionalValueType = OptionalType.from(edge.dependencyRequest().key()).valueType();
+      RequestKind requestKind = getRequestKind(optionalValueType);
+      return breaksCycle(extractKeyType(requestKind, optionalValueType), requestKind);
+    }
+    return false;
+  }
+
+  private boolean breaksCycle(TypeMirror requestedType, RequestKind requestKind) {
+    switch (requestKind) {
+      case PROVIDER:
+      case LAZY:
+      case PROVIDER_OF_LAZY:
+        return true;
+
+      case INSTANCE:
+        if (MapType.isMap(requestedType)) {
+          MapType mapType = MapType.from(requestedType);
+          return !mapType.isRawType() && mapType.valuesAreTypeOf(Provider.class);
+        }
+        // fall through
+
+      default:
+        return false;
+    }
+  }
+
+  private DependencyEdge chooseDependencyEdgeConnecting(
+      Node source, Node target, BindingGraph bindingGraph) {
+    return bindingGraph.network().edgesConnecting(source, target).stream()
+        .flatMap(instancesOf(DependencyEdge.class))
+        .findFirst()
+        .get();
+  }
+
+  /** Returns the subgraph containing only {@link DependencyEdge}s that would not break a cycle. */
+  // TODO(dpb): Return a network containing only Binding nodes.
+  private ImmutableNetwork<Node, DependencyEdge> nonCycleBreakingDependencyGraph(
+      BindingGraph bindingGraph) {
+    MutableNetwork<Node, DependencyEdge> dependencyNetwork =
+        NetworkBuilder.from(bindingGraph.network())
+            .expectedNodeCount(bindingGraph.network().nodes().size())
+            .expectedEdgeCount(bindingGraph.dependencyEdges().size())
+            .build();
+    bindingGraph.dependencyEdges().stream()
+        .filter(edge -> !breaksCycle(edge, bindingGraph))
+        .forEach(
+            edge -> {
+              EndpointPair<Node> endpoints = bindingGraph.network().incidentNodes(edge);
+              dependencyNetwork.addEdge(endpoints.source(), endpoints.target(), edge);
+            });
+    return ImmutableNetwork.copyOf(dependencyNetwork);
+  }
+
+  /**
+   * An ordered set of endpoint pairs representing the edges in the cycle. The target of each pair
+   * is the source of the next pair. The target of the last pair is the source of the first pair.
+   */
+  @AutoValue
+  abstract static class Cycle<N> {
+    /**
+     * The ordered set of endpoint pairs representing the edges in the cycle. The target of each
+     * pair is the source of the next pair. The target of the last pair is the source of the first
+     * pair.
+     */
+    abstract ImmutableSet<EndpointPair<N>> endpointPairs();
+
+    /** Returns the nodes that participate in the cycle. */
+    ImmutableSet<N> nodes() {
+      return endpointPairs().stream()
+          .flatMap(pair -> Stream.of(pair.source(), pair.target()))
+          .collect(toImmutableSet());
+    }
+
+    /** Returns the number of edges in the cycle. */
+    int size() {
+      return endpointPairs().size();
+    }
+
+    /**
+     * Shifts this cycle so that it starts with a specific node.
+     *
+     * @return a cycle equivalent to this one but whose first pair starts with {@code startNode}
+     */
+    Cycle<N> shift(N startNode) {
+      int startIndex = Iterables.indexOf(endpointPairs(), pair -> pair.source().equals(startNode));
+      checkArgument(
+          startIndex >= 0, "startNode (%s) is not part of this cycle: %s", startNode, this);
+      if (startIndex == 0) {
+        return this;
+      }
+      ImmutableSet.Builder<EndpointPair<N>> shifted = ImmutableSet.builder();
+      shifted.addAll(skip(endpointPairs(), startIndex));
+      shifted.addAll(limit(endpointPairs(), size() - startIndex));
+      return new AutoValue_DependencyCycleValidator_Cycle<>(shifted.build());
+    }
+
+    @Override
+    public final String toString() {
+      return endpointPairs().toString();
+    }
+
+    /**
+     * Creates a {@link Cycle} from a nonempty list of nodes, assuming there is an edge between each
+     * pair of nodes as well as an edge from the last node to the first.
+     */
+    static <N> Cycle<N> fromPath(List<N> nodes) {
+      checkArgument(!nodes.isEmpty());
+      ImmutableSet.Builder<EndpointPair<N>> cycle = ImmutableSet.builder();
+      cycle.add(EndpointPair.ordered(getLast(nodes), nodes.get(0)));
+      for (int i = 0; i < nodes.size() - 1; i++) {
+        cycle.add(EndpointPair.ordered(nodes.get(i), nodes.get(i + 1)));
+      }
+      return new AutoValue_DependencyCycleValidator_Cycle<>(cycle.build());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyEdgeImpl.java b/java/dagger/internal/codegen/DependencyEdgeImpl.java
new file mode 100644
index 0000000..64b0845
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyEdgeImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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 dagger.model.BindingGraph.DependencyEdge;
+import dagger.model.DependencyRequest;
+
+/** An implementation of {@link DependencyEdge}. */
+final class DependencyEdgeImpl implements DependencyEdge {
+
+  private final DependencyRequest dependencyRequest;
+  private final boolean entryPoint;
+
+  DependencyEdgeImpl(DependencyRequest dependencyRequest, boolean entryPoint) {
+    this.dependencyRequest = dependencyRequest;
+    this.entryPoint = entryPoint;
+  }
+
+  @Override
+  public DependencyRequest dependencyRequest() {
+    return dependencyRequest;
+  }
+
+  @Override
+  public boolean isEntryPoint() {
+    return entryPoint;
+  }
+
+  @Override
+  public String toString() {
+    String string =
+        dependencyRequest
+            .requestElement()
+            .map(ElementFormatter::elementToString)
+            .orElseGet(
+                () ->
+                    "synthetic request for "
+                        + dependencyRequest.kind().format(dependencyRequest.key()));
+    return entryPoint ? string + " (entry point)" : string;
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java b/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java
new file mode 100644
index 0000000..b42f9c4
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java
@@ -0,0 +1,97 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
+import static dagger.internal.codegen.javapoet.TypeNames.dependencyMethodProducerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+
+/**
+ * A {@link dagger.producers.Producer} creation expression for a production method on a production
+ * component's {@linkplain dagger.producers.ProductionComponent#dependencies()} dependency} that
+ * returns a {@link com.google.common.util.concurrent.ListenableFuture}.
+ */
+// TODO(dpb): Resolve with DependencyMethodProviderCreationExpression.
+final class DependencyMethodProducerCreationExpression
+    implements FrameworkInstanceCreationExpression {
+  private final ContributionBinding binding;
+  private final ComponentImplementation componentImplementation;
+  private final ComponentRequirementExpressions componentRequirementExpressions;
+  private final BindingGraph graph;
+
+  DependencyMethodProducerCreationExpression(
+      ContributionBinding binding,
+      ComponentImplementation componentImplementation,
+      ComponentRequirementExpressions componentRequirementExpressions,
+      BindingGraph graph) {
+    this.binding = checkNotNull(binding);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
+    this.graph = checkNotNull(graph);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    ComponentRequirement dependency =
+        graph.componentDescriptor().getDependencyThatDefinesMethod(binding.bindingElement().get());
+    FieldSpec dependencyField =
+        FieldSpec.builder(
+                ClassName.get(dependency.typeElement()), dependency.variableName(), PRIVATE, FINAL)
+            .initializer(
+                componentRequirementExpressions.getExpressionDuringInitialization(
+                    dependency,
+                    // This isn't a real class name, but we want the requesting class for the
+                    // expression to *not* be the same class as the component implementation,
+                    // because it isn't... it's an anonymous inner class.
+                    // TODO(cgdecker): If we didn't use an anonymous inner class here but instead
+                    // generated a named nested class as with
+                    // DependencyMethodProviderCreationExpression, we wouldn't need to deal with
+                    // this and might be able to avoid potentially creating an extra field in the
+                    // component?
+                    componentImplementation.name().nestedClass("Anonymous")))
+            .build();
+    // TODO(b/70395982): Explore using a private static type instead of an anonymous class.
+    TypeName keyType = TypeName.get(binding.key().type());
+    return CodeBlock.of(
+        "$L",
+        anonymousClassBuilder("")
+            .superclass(dependencyMethodProducerOf(keyType))
+            .addField(dependencyField)
+            .addMethod(
+                methodBuilder("callDependencyMethod")
+                    .addAnnotation(Override.class)
+                    .addModifiers(PUBLIC)
+                    .returns(listenableFutureOf(keyType))
+                    .addStatement(
+                        "return $N.$L()",
+                        dependencyField,
+                        binding.bindingElement().get().getSimpleName())
+                    .build())
+            .build());
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java b/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java
new file mode 100644
index 0000000..8532481
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java
@@ -0,0 +1,125 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.ComponentImplementation.TypeSpecKind.COMPONENT_PROVISION_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.auto.common.MoreTypes;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import javax.lang.model.element.Element;
+
+/**
+ * A {@link javax.inject.Provider} creation expression for a provision method on a component's
+ * {@linkplain dagger.Component#dependencies()} dependency}.
+ */
+// TODO(dpb): Resolve with DependencyMethodProducerCreationExpression.
+final class DependencyMethodProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final ComponentImplementation componentImplementation;
+  private final ComponentRequirementExpressions componentRequirementExpressions;
+  private final CompilerOptions compilerOptions;
+  private final BindingGraph graph;
+  private final ContributionBinding binding;
+
+  DependencyMethodProviderCreationExpression(
+      ContributionBinding binding,
+      ComponentImplementation componentImplementation,
+      ComponentRequirementExpressions componentRequirementExpressions,
+      CompilerOptions compilerOptions,
+      BindingGraph graph) {
+    this.binding = checkNotNull(binding);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
+    this.compilerOptions = checkNotNull(compilerOptions);
+    this.graph = checkNotNull(graph);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    // TODO(sameb): The Provider.get() throws a very vague NPE.  The stack trace doesn't
+    // help to figure out what the method or return type is.  If we include a string
+    // of the return type or method name in the error message, that can defeat obfuscation.
+    // We can easily include the raw type (no generics) + annotation type (no values),
+    // using .class & String.format -- but that wouldn't be the whole story.
+    // What should we do?
+    CodeBlock invocation =
+        ComponentProvisionBindingExpression.maybeCheckForNull(
+            (ProvisionBinding) binding,
+            compilerOptions,
+            CodeBlock.of(
+                "$N.$N()", dependency().variableName(), provisionMethod().getSimpleName()));
+    ClassName dependencyClassName = ClassName.get(dependency().typeElement());
+    TypeName keyType = TypeName.get(binding.key().type());
+    MethodSpec.Builder getMethod =
+        methodBuilder("get")
+            .addAnnotation(Override.class)
+            .addModifiers(PUBLIC)
+            .returns(keyType)
+            .addStatement("return $L", invocation);
+    if (binding.nullableType().isPresent()) {
+      getMethod.addAnnotation(ClassName.get(MoreTypes.asTypeElement(binding.nullableType().get())));
+    }
+    componentImplementation.addType(
+        COMPONENT_PROVISION_FACTORY,
+        classBuilder(factoryClassName())
+            .addSuperinterface(providerOf(keyType))
+            .addModifiers(PRIVATE, STATIC)
+            .addField(dependencyClassName, dependency().variableName(), PRIVATE, FINAL)
+            .addMethod(
+                constructorBuilder()
+                    .addParameter(dependencyClassName, dependency().variableName())
+                    .addStatement("this.$1L = $1L", dependency().variableName())
+                    .build())
+            .addMethod(getMethod.build())
+            .build());
+    return CodeBlock.of(
+        "new $T($L)",
+        factoryClassName(),
+        componentRequirementExpressions.getExpressionDuringInitialization(
+            dependency(), componentImplementation.name()));
+  }
+
+  private ClassName factoryClassName() {
+    String factoryName =
+        ClassName.get(dependency().typeElement()).toString().replace('.', '_')
+            + "_"
+            + binding.bindingElement().get().getSimpleName();
+    return componentImplementation.name().nestedClass(factoryName);
+  }
+
+  private ComponentRequirement dependency() {
+    return graph.componentDescriptor().getDependencyThatDefinesMethod(provisionMethod());
+  }
+
+  private Element provisionMethod() {
+    return binding.bindingElement().get();
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyRequestFactory.java b/java/dagger/internal/codegen/DependencyRequestFactory.java
new file mode 100644
index 0000000..3ad12e2
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyRequestFactory.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2014 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.isTypeOf;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
+import static dagger.internal.codegen.RequestKinds.extractKeyType;
+import static dagger.internal.codegen.RequestKinds.frameworkClass;
+import static dagger.internal.codegen.RequestKinds.getRequestKind;
+import static dagger.model.RequestKind.FUTURE;
+import static dagger.model.RequestKind.INSTANCE;
+import static dagger.model.RequestKind.MEMBERS_INJECTION;
+import static dagger.model.RequestKind.PRODUCER;
+import static dagger.model.RequestKind.PROVIDER;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
+import dagger.Lazy;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import java.util.List;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Factory for {@link DependencyRequest}s.
+ *
+ * <p>Any factory method may throw {@link TypeNotPresentException} if a type is not available, which
+ * may mean that the type will be generated in a later round of processing.
+ */
+final class DependencyRequestFactory {
+  private final KeyFactory keyFactory;
+  private final DaggerTypes types;
+
+  @Inject
+  DependencyRequestFactory(KeyFactory keyFactory, DaggerTypes types) {
+    this.keyFactory = keyFactory;
+    this.types = types;
+  }
+
+  ImmutableSet<DependencyRequest> forRequiredResolvedVariables(
+      List<? extends VariableElement> variables, List<? extends TypeMirror> resolvedTypes) {
+    checkState(resolvedTypes.size() == variables.size());
+    ImmutableSet.Builder<DependencyRequest> builder = ImmutableSet.builder();
+    for (int i = 0; i < variables.size(); i++) {
+      builder.add(forRequiredResolvedVariable(variables.get(i), resolvedTypes.get(i)));
+    }
+    return builder.build();
+  }
+
+  /**
+   * Creates synthetic dependency requests for each individual multibinding contribution in {@code
+   * multibindingContributions}.
+   */
+  ImmutableSet<DependencyRequest> forMultibindingContributions(
+      Key multibindingKey, Iterable<ContributionBinding> multibindingContributions) {
+    ImmutableSet.Builder<DependencyRequest> requests = ImmutableSet.builder();
+    for (ContributionBinding multibindingContribution : multibindingContributions) {
+      requests.add(forMultibindingContribution(multibindingKey, multibindingContribution));
+    }
+    return requests.build();
+  }
+
+  /** Creates a synthetic dependency request for one individual {@code multibindingContribution}. */
+  private DependencyRequest forMultibindingContribution(
+      Key multibindingKey, ContributionBinding multibindingContribution) {
+    checkArgument(
+        multibindingContribution.key().multibindingContributionIdentifier().isPresent(),
+        "multibindingContribution's key must have a multibinding contribution identifier: %s",
+        multibindingContribution);
+    return DependencyRequest.builder()
+        .kind(multibindingContributionRequestKind(multibindingKey, multibindingContribution))
+        .key(multibindingContribution.key())
+        .build();
+  }
+
+  // TODO(b/28555349): support PROVIDER_OF_LAZY here too
+  private static final ImmutableSet<RequestKind> WRAPPING_MAP_VALUE_FRAMEWORK_TYPES =
+      ImmutableSet.of(PROVIDER, PRODUCER);
+
+  private RequestKind multibindingContributionRequestKind(
+      Key multibindingKey, ContributionBinding multibindingContribution) {
+    switch (multibindingContribution.contributionType()) {
+      case MAP:
+        MapType mapType = MapType.from(multibindingKey);
+        for (RequestKind kind : WRAPPING_MAP_VALUE_FRAMEWORK_TYPES) {
+          if (mapType.valuesAreTypeOf(frameworkClass(kind))) {
+            return kind;
+          }
+        }
+        // fall through
+      case SET:
+      case SET_VALUES:
+        return INSTANCE;
+      case UNIQUE:
+        throw new IllegalArgumentException(
+            "multibindingContribution must be a multibinding: " + multibindingContribution);
+    }
+    throw new AssertionError(multibindingContribution.toString());
+  }
+
+  DependencyRequest forRequiredResolvedVariable(
+      VariableElement variableElement, TypeMirror resolvedType) {
+    checkNotNull(variableElement);
+    checkNotNull(resolvedType);
+    Optional<AnnotationMirror> qualifier = InjectionAnnotations.getQualifier(variableElement);
+    return newDependencyRequest(variableElement, resolvedType, qualifier);
+  }
+
+  DependencyRequest forComponentProvisionMethod(
+      ExecutableElement provisionMethod, ExecutableType provisionMethodType) {
+    checkNotNull(provisionMethod);
+    checkNotNull(provisionMethodType);
+    checkArgument(
+        provisionMethod.getParameters().isEmpty(),
+        "Component provision methods must be empty: %s",
+        provisionMethod);
+    Optional<AnnotationMirror> qualifier = InjectionAnnotations.getQualifier(provisionMethod);
+    return newDependencyRequest(provisionMethod, provisionMethodType.getReturnType(), qualifier);
+  }
+
+  DependencyRequest forComponentProductionMethod(
+      ExecutableElement productionMethod, ExecutableType productionMethodType) {
+    checkNotNull(productionMethod);
+    checkNotNull(productionMethodType);
+    checkArgument(
+        productionMethod.getParameters().isEmpty(),
+        "Component production methods must be empty: %s",
+        productionMethod);
+    TypeMirror type = productionMethodType.getReturnType();
+    Optional<AnnotationMirror> qualifier = InjectionAnnotations.getQualifier(productionMethod);
+    // Only a component production method can be a request for a ListenableFuture, so we
+    // special-case it here.
+    if (isTypeOf(ListenableFuture.class, type)) {
+      return DependencyRequest.builder()
+          .kind(FUTURE)
+          .key(keyFactory.forQualifiedType(qualifier, types.unwrapType(type)))
+          .requestElement(productionMethod)
+          .build();
+    } else {
+      return newDependencyRequest(productionMethod, type, qualifier);
+    }
+  }
+
+  DependencyRequest forComponentMembersInjectionMethod(
+      ExecutableElement membersInjectionMethod, ExecutableType membersInjectionMethodType) {
+    checkNotNull(membersInjectionMethod);
+    checkNotNull(membersInjectionMethodType);
+    Optional<AnnotationMirror> qualifier =
+        InjectionAnnotations.getQualifier(membersInjectionMethod);
+    checkArgument(!qualifier.isPresent());
+    TypeMirror membersInjectedType = getOnlyElement(membersInjectionMethodType.getParameterTypes());
+    return DependencyRequest.builder()
+        .kind(MEMBERS_INJECTION)
+        .key(keyFactory.forMembersInjectedType(membersInjectedType))
+        .requestElement(membersInjectionMethod)
+        .build();
+  }
+
+  DependencyRequest forProductionImplementationExecutor() {
+    return DependencyRequest.builder()
+        .kind(PROVIDER)
+        .key(keyFactory.forProductionImplementationExecutor())
+        .build();
+  }
+
+  DependencyRequest forProductionComponentMonitor() {
+    return DependencyRequest.builder()
+        .kind(PROVIDER)
+        .key(keyFactory.forProductionComponentMonitor())
+        .build();
+  }
+
+  /**
+   * Returns a synthetic request for the present value of an optional binding generated from a
+   * {@link dagger.BindsOptionalOf} declaration.
+   */
+  DependencyRequest forSyntheticPresentOptionalBinding(Key requestKey, RequestKind kind) {
+    Optional<Key> key = keyFactory.unwrapOptional(requestKey);
+    checkArgument(key.isPresent(), "not a request for optional: %s", requestKey);
+    return DependencyRequest.builder()
+        .kind(kind)
+        .key(key.get())
+        .isNullable(
+            allowsNull(getRequestKind(OptionalType.from(requestKey).valueType()), Optional.empty()))
+        .build();
+  }
+
+  private DependencyRequest newDependencyRequest(
+      Element requestElement, TypeMirror type, Optional<AnnotationMirror> qualifier) {
+    RequestKind requestKind = getRequestKind(type);
+    return DependencyRequest.builder()
+        .kind(requestKind)
+        .key(keyFactory.forQualifiedType(qualifier, extractKeyType(requestKind, type)))
+        .requestElement(requestElement)
+        .isNullable(allowsNull(requestKind, getNullableType(requestElement)))
+        .build();
+  }
+
+  /**
+   * Returns {@code true} if a given request element allows null values. {@link
+   * RequestKind#INSTANCE} requests must be annotated with {@code @Nullable} in order to allow null
+   * values. All other request kinds implicitly allow null values because they are are wrapped
+   * inside {@link Provider}, {@link Lazy}, etc.
+   */
+  private boolean allowsNull(RequestKind kind, Optional<DeclaredType> nullableType) {
+    return nullableType.isPresent() || !kind.equals(INSTANCE);
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyRequestFormatter.java b/java/dagger/internal/codegen/DependencyRequestFormatter.java
new file mode 100644
index 0000000..25becaf
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyRequestFormatter.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2014 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 dagger.internal.codegen.ElementFormatter.elementToString;
+import static dagger.internal.codegen.RequestKinds.requestType;
+
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import dagger.producers.Produces;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementKindVisitor8;
+
+/**
+ * Formats a {@link DependencyRequest} into a {@link String} suitable for an error message listing a
+ * chain of dependencies.
+ *
+ * <dl>
+ *   <dt>For component provision methods
+ *   <dd>{@code @Qualifier SomeType is provided at\n ComponentType.method()}
+ *   <dt>For component injection methods
+ *   <dd>{@code SomeType is injected at\n ComponentType.method(foo)}
+ *   <dt>For parameters to {@link Provides @Provides}, {@link Produces @Produces}, or {@link
+ *       Inject @Inject} methods:
+ *   <dd>{@code @Qualified ResolvedType is injected at\n EnclosingType.method([…, ]param[, …])}
+ *   <dt>For parameters to {@link Inject @Inject} constructors:
+ *   <dd>{@code @Qualified ResolvedType is injected at\n EnclosingType([…, ]param[, …])}
+ *   <dt>For {@link Inject @Inject} fields:
+ *   <dd>{@code @Qualified ResolvedType is injected at\n EnclosingType.field}
+ * </dl>
+ */
+final class DependencyRequestFormatter extends Formatter<DependencyRequest> {
+
+  private final DaggerTypes types;
+
+  @Inject
+  DependencyRequestFormatter(DaggerTypes types) {
+    this.types = types;
+  }
+
+  @Override
+  public String format(DependencyRequest request) {
+    return request
+        .requestElement()
+        .map(element -> element.accept(formatVisitor, request))
+        .orElse("");
+  }
+
+  /**
+   * Appends a newline and the formatted dependency request unless {@link
+   * #format(DependencyRequest)} returns the empty string.
+   */
+  @CanIgnoreReturnValue
+  StringBuilder appendFormatLine(StringBuilder builder, DependencyRequest dependencyRequest) {
+    String formatted = format(dependencyRequest);
+    if (!formatted.isEmpty()) {
+      builder.append('\n').append(formatted);
+    }
+    return builder;
+  }
+
+  private final ElementVisitor<String, DependencyRequest> formatVisitor =
+      new ElementKindVisitor8<String, DependencyRequest>() {
+
+        @Override
+        public String visitExecutableAsMethod(ExecutableElement method, DependencyRequest request) {
+          return INDENT
+              + request.key()
+              + " is "
+              + componentMethodRequestVerb(request)
+              + " at\n"
+              + DOUBLE_INDENT
+              + elementToString(method);
+        }
+
+        @Override
+        public String visitVariable(VariableElement variable, DependencyRequest request) {
+          TypeMirror requestedType = requestType(request.kind(), request.key().type(), types);
+          return INDENT
+              + formatQualifier(request.key().qualifier())
+              + requestedType
+              + " is injected at\n"
+              + DOUBLE_INDENT
+              + elementToString(variable);
+        }
+
+        @Override
+        public String visitType(TypeElement e, DependencyRequest request) {
+          return ""; // types by themselves provide no useful information.
+        }
+
+        @Override
+        protected String defaultAction(Element element, DependencyRequest request) {
+          throw new IllegalStateException(
+              "Invalid request " + element.getKind() + " element " + element);
+        }
+      };
+
+  private String formatQualifier(Optional<AnnotationMirror> maybeQualifier) {
+    return maybeQualifier.map(qualifier -> qualifier + " ").orElse("");
+  }
+
+  /**
+   * Returns the verb for a component method dependency request. Returns "produced", "provided", or
+   * "injected", depending on the kind of request.
+   */
+  private String componentMethodRequestVerb(DependencyRequest request) {
+    switch (request.kind()) {
+      case FUTURE:
+      case PRODUCER:
+        return "produced";
+
+      case INSTANCE:
+      case LAZY:
+      case PROVIDER:
+      case PROVIDER_OF_LAZY:
+        return "provided";
+
+      case MEMBERS_INJECTION:
+        return "injected";
+
+      case PRODUCED:
+        break;
+    }
+    throw new AssertionError("illegal request kind for method: " + request);
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyRequestValidator.java b/java/dagger/internal/codegen/DependencyRequestValidator.java
new file mode 100644
index 0000000..1a99818
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyRequestValidator.java
@@ -0,0 +1,97 @@
+/*
+ * 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 dagger.internal.codegen.InjectionAnnotations.getQualifiers;
+import static dagger.internal.codegen.RequestKinds.extractKeyType;
+import static dagger.internal.codegen.RequestKinds.getRequestKind;
+import static javax.lang.model.type.TypeKind.WILDCARD;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import dagger.MembersInjector;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/** Validation for dependency requests. */
+final class DependencyRequestValidator {
+  private final MembersInjectionValidator membersInjectionValidator;
+
+  @Inject
+  DependencyRequestValidator(MembersInjectionValidator membersInjectionValidator) {
+    this.membersInjectionValidator = membersInjectionValidator;
+  }
+
+  /**
+   * Adds an error if the given dependency request has more than one qualifier annotation or is a
+   * non-instance request with a wildcard type.
+   */
+  void validateDependencyRequest(
+      ValidationReport.Builder<?> report, Element requestElement, TypeMirror requestType) {
+    ImmutableSet<? extends AnnotationMirror> qualifiers = getQualifiers(requestElement);
+    if (qualifiers.size() > 1) {
+      for (AnnotationMirror qualifier : qualifiers) {
+        report.addError(
+            "A single dependency request may not use more than one @Qualifier",
+            requestElement,
+            qualifier);
+      }
+    }
+
+    TypeMirror keyType = extractKeyType(getRequestKind(requestType), requestType);
+    if (keyType.getKind().equals(WILDCARD)) {
+      // TODO(ronshapiro): Explore creating this message using RequestKinds.
+      report.addError(
+          "Dagger does not support injecting Provider<T>, Lazy<T>, Producer<T>, "
+              + "or Produced<T> when T is a wildcard type such as "
+              + keyType,
+          requestElement);
+    }
+    if (MoreTypes.isType(keyType) && MoreTypes.isTypeOf(MembersInjector.class, keyType)) {
+      DeclaredType membersInjectorType = MoreTypes.asDeclared(keyType);
+      if (membersInjectorType.getTypeArguments().isEmpty()) {
+        report.addError("Cannot inject a raw MembersInjector", requestElement);
+      } else {
+        report.addSubreport(
+            membersInjectionValidator.validateMembersInjectionRequest(
+                requestElement, membersInjectorType.getTypeArguments().get(0)));
+      }
+    }
+  }
+
+  /**
+   * Adds an error if the given dependency request is for a {@link dagger.producers.Producer} or
+   * {@link dagger.producers.Produced}.
+   *
+   * <p>Only call this when processing a provision binding.
+   */
+  // TODO(dpb): Should we disallow Producer entry points in non-production components?
+  void checkNotProducer(ValidationReport.Builder<?> report, VariableElement requestElement) {
+    TypeMirror requestType = requestElement.asType();
+    if (FrameworkTypes.isProducerType(requestType)) {
+      report.addError(
+          String.format(
+              "%s may only be injected in @Produces methods",
+              MoreTypes.asTypeElement(requestType).getSimpleName()),
+          requestElement);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyVariableNamer.java b/java/dagger/internal/codegen/DependencyVariableNamer.java
new file mode 100644
index 0000000..21f2d32
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyVariableNamer.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 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 dagger.internal.codegen.SourceFiles.simpleVariableName;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.base.Ascii;
+import com.google.common.base.CaseFormat;
+import dagger.Lazy;
+import dagger.model.DependencyRequest;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.inject.Provider;
+
+/**
+ * Picks a reasonable name for what we think is being provided from the variable name associated
+ * with the {@link DependencyRequest}.  I.e. strips out words like "lazy" and "provider" if we
+ * believe that those refer to {@link Lazy} and {@link Provider} rather than the type being
+ * provided.
+ */
+//TODO(gak): develop the heuristics to get better names
+final class DependencyVariableNamer {
+  private static final Pattern LAZY_PROVIDER_PATTERN = Pattern.compile("lazy(\\w+)Provider");
+
+  static String name(DependencyRequest dependency) {
+    if (!dependency.requestElement().isPresent()) {
+      return simpleVariableName(MoreTypes.asTypeElement(dependency.key().type()));
+    }
+
+    String variableName = dependency.requestElement().get().getSimpleName().toString();
+    if (Ascii.isUpperCase(variableName.charAt(0))) {
+      variableName = toLowerCamel(variableName);
+    }
+    switch (dependency.kind()) {
+      case INSTANCE:
+        return variableName;
+      case LAZY:
+        return variableName.startsWith("lazy") && !variableName.equals("lazy")
+            ? toLowerCamel(variableName.substring(4))
+            : variableName;
+      case PROVIDER_OF_LAZY:
+        Matcher matcher = LAZY_PROVIDER_PATTERN.matcher(variableName);
+        if (matcher.matches()) {
+          return toLowerCamel(matcher.group(1));
+        }
+        // fall through
+      case PROVIDER:
+        return variableName.endsWith("Provider") && !variableName.equals("Provider")
+            ? variableName.substring(0, variableName.length() - 8)
+            : variableName;
+      case PRODUCED:
+        return variableName.startsWith("produced") && !variableName.equals("produced")
+            ? toLowerCamel(variableName.substring(8))
+            : variableName;
+      case PRODUCER:
+        return variableName.endsWith("Producer") && !variableName.equals("Producer")
+            ? variableName.substring(0, variableName.length() - 8)
+            : variableName;
+      default:
+        throw new AssertionError();
+    }
+  }
+
+  private static String toLowerCamel(String name) {
+    return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, name);
+  }
+}
diff --git a/java/dagger/internal/codegen/DependsOnProductionExecutorValidator.java b/java/dagger/internal/codegen/DependsOnProductionExecutorValidator.java
new file mode 100644
index 0000000..e611d22
--- /dev/null
+++ b/java/dagger/internal/codegen/DependsOnProductionExecutorValidator.java
@@ -0,0 +1,69 @@
+/*
+ * 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 dagger.internal.codegen.DaggerStreams.instancesOf;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import dagger.model.BindingGraph;
+import dagger.model.BindingGraph.MaybeBinding;
+import dagger.model.Key;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import javax.inject.Inject;
+
+/**
+ * Reports an error on all bindings that depend explicitly on the {@code @Production Executor} key.
+ */
+// TODO(dpb,beder): Validate this during @Inject/@Provides/@Produces validation.
+final class DependsOnProductionExecutorValidator implements BindingGraphPlugin {
+  private final CompilerOptions compilerOptions;
+  private final KeyFactory keyFactory;
+
+  @Inject
+  DependsOnProductionExecutorValidator(CompilerOptions compilerOptions, KeyFactory keyFactory) {
+    this.compilerOptions = compilerOptions;
+    this.keyFactory = keyFactory;
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/DependsOnProductionExecutor";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    if (!compilerOptions.usesProducers()) {
+      return;
+    }
+
+    Key productionImplementationExecutorKey = keyFactory.forProductionImplementationExecutor();
+    Key productionExecutorKey = keyFactory.forProductionExecutor();
+
+    bindingGraph.network().nodes().stream()
+        .flatMap(instancesOf(MaybeBinding.class))
+        .filter(node -> node.key().equals(productionExecutorKey))
+        .flatMap(productionExecutor -> bindingGraph.requestingBindings(productionExecutor).stream())
+        .filter(binding -> !binding.key().equals(productionImplementationExecutorKey))
+        .forEach(binding -> reportError(diagnosticReporter, binding));
+  }
+
+  private void reportError(DiagnosticReporter diagnosticReporter, dagger.model.Binding binding) {
+    diagnosticReporter.reportBinding(
+        ERROR, binding, "%s may not depend on the production executor", binding.key());
+  }
+}
diff --git a/java/dagger/internal/codegen/DerivedFromFrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/DerivedFromFrameworkInstanceBindingExpression.java
new file mode 100644
index 0000000..4f2f622
--- /dev/null
+++ b/java/dagger/internal/codegen/DerivedFromFrameworkInstanceBindingExpression.java
@@ -0,0 +1,82 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+
+import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import javax.lang.model.type.TypeMirror;
+
+/** A binding expression that depends on a framework instance. */
+final class DerivedFromFrameworkInstanceBindingExpression extends BindingExpression {
+
+  private final BindingRequest frameworkRequest;
+  private final RequestKind requestKind;
+  private final FrameworkType frameworkType;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final DaggerTypes types;
+
+  DerivedFromFrameworkInstanceBindingExpression(
+      Key key,
+      FrameworkType frameworkType,
+      RequestKind requestKind,
+      ComponentBindingExpressions componentBindingExpressions,
+      DaggerTypes types) {
+    this.frameworkRequest = bindingRequest(key, frameworkType);
+    this.requestKind = checkNotNull(requestKind);
+    this.frameworkType = checkNotNull(frameworkType);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+    this.types = checkNotNull(types);
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    return frameworkType.to(
+        requestKind,
+        componentBindingExpressions.getDependencyExpression(frameworkRequest, requestingClass),
+        types);
+  }
+
+  @Override
+  Expression getDependencyExpressionForComponentMethod(
+      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
+    Expression frameworkInstance =
+        componentBindingExpressions.getDependencyExpressionForComponentMethod(
+            frameworkRequest, componentMethod, component);
+    Expression forRequestKind = frameworkType.to(requestKind, frameworkInstance, types);
+    TypeMirror rawReturnType = types.erasure(componentMethod.resolvedReturnType(types));
+    if (!types.isAssignable(forRequestKind.type(), rawReturnType)) {
+      checkState(
+          component.isAbstract(),
+          "FrameworkType.to() should always return an accessible type unless we're in "
+              + "ahead-of-time mode, where the framework instance type is erased since it's not "
+              + "publicly accessible, but the return type is accessible to the package. "
+              + "\n  Component: %s, method: %s",
+          component.name(),
+          componentMethod);
+      return forRequestKind.castTo(rawReturnType);
+    }
+    return forRequestKind;
+  }
+}
diff --git a/java/dagger/internal/codegen/DeserializedComponentImplementationBuilder.java b/java/dagger/internal/codegen/DeserializedComponentImplementationBuilder.java
new file mode 100644
index 0000000..45e99a8
--- /dev/null
+++ b/java/dagger/internal/codegen/DeserializedComponentImplementationBuilder.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2019 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.AnnotationMirrors.getAnnotationValue;
+import static com.google.auto.common.MoreElements.getAnnotationMirror;
+import static com.google.auto.common.MoreElements.isAnnotationPresent;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.MoreAnnotationValues.asAnnotationValues;
+import static dagger.internal.codegen.serialization.ProtoSerialization.fromAnnotationValue;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+import static javax.lang.model.util.ElementFilter.typesIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.ComponentDefinitionType;
+import dagger.internal.ConfigureInitializationParameters;
+import dagger.internal.ModifiableBinding;
+import dagger.internal.ModifiableModule;
+import dagger.internal.codegen.ComponentImplementation.ConfigureInitializationMethod;
+import dagger.internal.codegen.serialization.BindingRequestProto;
+import dagger.internal.codegen.serialization.ComponentRequirementProto;
+import dagger.internal.codegen.serialization.FrameworkTypeWrapper;
+import dagger.internal.codegen.serialization.KeyProto;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Reconstructs {@link ComponentImplementation}s that have already been compiled. Uses metadata
+ * annotations on the generated type and it's methods to reconstitute the equivalent {@link
+ * ComponentImplementation} state.
+ */
+final class DeserializedComponentImplementationBuilder {
+  private final CompilerOptions compilerOptions;
+  private final ComponentCreatorImplementationFactory componentCreatorImplementationFactory;
+  private final TypeProtoConverter typeProtoConverter;
+  private final KeyFactory keyFactory;
+
+  @Inject
+  DeserializedComponentImplementationBuilder(
+      CompilerOptions compilerOptions,
+      ComponentCreatorImplementationFactory componentCreatorImplementationFactory,
+      TypeProtoConverter typeProtoConverter,
+      KeyFactory keyFactory) {
+    this.compilerOptions = compilerOptions;
+    this.componentCreatorImplementationFactory = componentCreatorImplementationFactory;
+    this.typeProtoConverter = typeProtoConverter;
+    this.keyFactory = keyFactory;
+  }
+
+  /** Creates a new {@link ComponentImplementation} from a compiled component. */
+  ComponentImplementation create(ComponentDescriptor component, TypeElement generatedComponent) {
+    Optional<ComponentImplementation> superclassImplementation =
+        deserializedSuperclassImplementation(
+            component, MoreTypes.asTypeElement(generatedComponent.getSuperclass()));
+
+    ComponentImplementation componentImplementation =
+        ComponentImplementation.forDeserializedComponent(
+            component,
+            ClassName.get(generatedComponent),
+            generatedComponent.getNestingKind(),
+            superclassImplementation,
+            compilerOptions);
+
+    componentImplementation.setCreatorImplementation(
+        superclassImplementation.isPresent()
+            ? Optional.empty()
+            : componentCreatorImplementationFactory.create(
+                componentImplementation, Optional.empty()));
+
+    // TODO(b/117833324): Consider omitting superclass implementations, so that only one instance of
+    // ComponentImplementation needs to be created (in most cases, we don't care about nested levels
+    // of superclass implementations, except for the base implementation). If that's possible, use
+    // getLocalAndInheritedMethods instead of getEnclosedElements() here.
+    for (ExecutableElement method : methodsIn(generatedComponent.getEnclosedElements())) {
+      getAnnotationMirror(method, ModifiableBinding.class)
+          .asSet()
+          .forEach(
+              annotation ->
+                  addModifiableBindingMethod(componentImplementation, method, annotation));
+
+      getAnnotationMirror(method, ModifiableModule.class)
+          .asSet()
+          .forEach(
+              annotation -> addModifiableModuleMethod(componentImplementation, method, annotation));
+
+      getAnnotationMirror(method, ConfigureInitializationParameters.class)
+          .asSet()
+          .forEach(
+              annotation ->
+                  setConfigureInitializationMethod(componentImplementation, method, annotation));
+    }
+
+    for (TypeElement nestedType : typesIn(generatedComponent.getEnclosedElements())) {
+      addChildImplementation(component, componentImplementation, nestedType);
+    }
+
+    return componentImplementation;
+  }
+
+  private Optional<ComponentImplementation> deserializedSuperclassImplementation(
+      ComponentDescriptor component, TypeElement superclassElement) {
+    return isAnnotationPresent(superclassElement, ComponentDefinitionType.class)
+        ? Optional.of(create(component, superclassElement))
+        : Optional.empty();
+  }
+
+  private void addModifiableBindingMethod(
+      ComponentImplementation componentImplementation,
+      ExecutableElement method,
+      AnnotationMirror metadataAnnotation) {
+    ModifiableBindingType modifiableBindingType =
+        ModifiableBindingType.valueOf(
+            getAnnotationValue(metadataAnnotation, "modifiableBindingType").getValue().toString());
+
+    BindingRequest request =
+        parseBindingRequest(getAnnotationValue(metadataAnnotation, "bindingRequest"));
+
+    ImmutableList<Key> multibindingContributions =
+        asAnnotationValues(getAnnotationValue(metadataAnnotation, "multibindingContributions"))
+            .stream()
+            .map(this::parseKey)
+            .collect(toImmutableList());
+
+    componentImplementation.addModifiableBindingMethod(
+        modifiableBindingType,
+        request,
+        method.getReturnType(),
+        methodDeclaration(method),
+        method.getModifiers().contains(FINAL));
+    componentImplementation.registerImplementedMultibindingKeys(request, multibindingContributions);
+  }
+
+  private BindingRequest fromProto(BindingRequestProto bindingRequest) {
+    Key key = keyFactory.fromProto(bindingRequest.getKey());
+    return bindingRequest.getFrameworkType().equals(FrameworkTypeWrapper.FrameworkType.UNKNOWN)
+        ? bindingRequest(key, RequestKind.valueOf(bindingRequest.getRequestKind().name()))
+        : bindingRequest(key, FrameworkType.valueOf(bindingRequest.getFrameworkType().name()));
+  }
+
+  /**
+   * Returns a {@link MethodSpec} for a {@link
+   * dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod}. The method contents
+   * are not relevant since this represents a method that has already been compiled.
+   *
+   * <p>Ideally this could be {@code MethodSpec.overriding(method).build()}, but that doesn't work
+   * for {@code final} methods
+   */
+  private MethodSpec methodDeclaration(ExecutableElement method) {
+    return methodBuilder(method.getSimpleName().toString())
+        .addModifiers(method.getModifiers())
+        .returns(TypeName.get(method.getReturnType()))
+        .build();
+  }
+
+  private void addModifiableModuleMethod(
+      ComponentImplementation componentImplementation,
+      ExecutableElement method,
+      AnnotationMirror metadataAnnotation) {
+    ComponentRequirement moduleRequirement =
+        parseComponentRequirement(getAnnotationValue(metadataAnnotation, "value"));
+    componentImplementation.registerModifiableModuleMethod(
+        moduleRequirement, method.getSimpleName().toString());
+  }
+
+  private void setConfigureInitializationMethod(
+      ComponentImplementation componentImplementation,
+      ExecutableElement method,
+      AnnotationMirror metadataAnnotation) {
+    ImmutableSet<ComponentRequirement> parameters =
+        asAnnotationValues(getAnnotationValue(metadataAnnotation, "value")).stream()
+            .map(this::parseComponentRequirement)
+            .collect(toImmutableSet());
+
+    componentImplementation.setConfigureInitializationMethod(
+        ConfigureInitializationMethod.create(MethodSpec.overriding(method).build(), parameters));
+  }
+
+  private void addChildImplementation(
+      ComponentDescriptor component,
+      ComponentImplementation componentImplementation,
+      TypeElement nestedType) {
+    getAnnotationMirror(nestedType, ComponentDefinitionType.class)
+        .transform(annotation -> (TypeMirror) getAnnotationValue(annotation, "value").getValue())
+        .transform(MoreTypes::asTypeElement)
+        .asSet()
+        .forEach(
+            componentDefinitionType -> {
+              ComponentDescriptor child =
+                  component.childComponentsByElement().get(componentDefinitionType);
+              componentImplementation.addChild(child, create(child, nestedType));
+            });
+  }
+
+  private Key parseKey(AnnotationValue annotationValue) {
+    return keyFactory.fromProto(
+        fromAnnotationValue(annotationValue, KeyProto.getDefaultInstance()));
+  }
+
+  private BindingRequest parseBindingRequest(AnnotationValue annotationValue) {
+    return fromProto(
+        fromAnnotationValue(annotationValue, BindingRequestProto.getDefaultInstance()));
+  }
+
+  private ComponentRequirement parseComponentRequirement(AnnotationValue annotationValue) {
+    return fromProto(
+        fromAnnotationValue(annotationValue, ComponentRequirementProto.getDefaultInstance()));
+  }
+
+  private ComponentRequirement fromProto(ComponentRequirementProto proto) {
+    switch (proto.getRequirementCase()) {
+      case MODULE:
+        return ComponentRequirement.forModule(typeProtoConverter.fromProto(proto.getModule()));
+      case DEPENDENCY:
+        return ComponentRequirement.forDependency(
+            typeProtoConverter.fromProto(proto.getDependency()));
+      case BOUND_INSTANCE:
+        return ComponentRequirement.forBoundInstance(
+            keyFactory.fromProto(proto.getBoundInstance().getKey()),
+            proto.getBoundInstance().getNullable(),
+            proto.getBoundInstance().getVariableName());
+      case REQUIREMENT_NOT_SET:
+        // fall through
+    }
+    throw new AssertionError(proto);
+  }
+}
diff --git a/java/dagger/internal/codegen/DiagnosticFormatting.java b/java/dagger/internal/codegen/DiagnosticFormatting.java
new file mode 100644
index 0000000..8502ecb
--- /dev/null
+++ b/java/dagger/internal/codegen/DiagnosticFormatting.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 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 java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility methods for formatting diagnostics to the {@link javax.annotation.processing.Messager}.
+ */
+final class DiagnosticFormatting {
+
+  /**
+   * A regular expression to match a small list of specific packages deemed to be unhelpful to
+   * display in fully qualified types in error messages.
+   *
+   * <p>Note: This should never be applied to messages themselves.
+   */
+  private static final Pattern COMMON_PACKAGE_PATTERN =
+      Pattern.compile(
+          "(?:^|[^.a-z_])" // What we want to match on but not capture.
+              + "((?:" // Start a group with a non-capturing or part
+              + "java[.]lang"
+              + "|java[.]util"
+              + "|javax[.]inject"
+              + "|dagger"
+              + "|com[.]google[.]common[.]base"
+              + "|com[.]google[.]common[.]collect"
+              + ")[.])" // Always end with a literal .
+              + "[A-Z]"); // What we want to match on but not capture.
+
+  /**
+   * A method to strip out common packages and a few rare type prefixes from types' string
+   * representation before being used in error messages.
+   *
+   * <p>This type assumes a String value that is a valid fully qualified (and possibly
+   * parameterized) type, and should NOT be used with arbitrary text, especially prose error
+   * messages.
+   *
+   * <p>TODO(cgruber): Tighten these to take type representations (mirrors and elements) to avoid
+   * accidental mis-use by running errors through this method.
+   */
+  static String stripCommonTypePrefixes(String type) {
+    // Do regex magic to remove common packages we care to shorten.
+    Matcher matcher = COMMON_PACKAGE_PATTERN.matcher(type);
+    StringBuilder result = new StringBuilder();
+    int index = 0;
+    while (matcher.find()) {
+      result.append(type.subSequence(index, matcher.start(1)));
+      index = matcher.end(1); // Skip the matched pattern content.
+    }
+    result.append(type.subSequence(index, type.length()));
+    return result.toString();
+  }
+
+  private DiagnosticFormatting() {}
+}
diff --git a/java/dagger/internal/codegen/DiagnosticReporterFactory.java b/java/dagger/internal/codegen/DiagnosticReporterFactory.java
new file mode 100644
index 0000000..f657cee
--- /dev/null
+++ b/java/dagger/internal/codegen/DiagnosticReporterFactory.java
@@ -0,0 +1,519 @@
+/*
+ * 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.asTypeElement;
+import static com.google.common.base.Predicates.equalTo;
+import static com.google.common.base.Verify.verify;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.getLast;
+import static com.google.common.collect.Iterables.indexOf;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Lists.asList;
+import static dagger.internal.codegen.DaggerGraphs.shortestPath;
+import static dagger.internal.codegen.DaggerStreams.instancesOf;
+import static dagger.internal.codegen.DaggerStreams.presentValues;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.ElementFormatter.elementToString;
+import static dagger.internal.codegen.ValidationType.NONE;
+import static dagger.internal.codegen.langmodel.DaggerElements.DECLARATION_ORDER;
+import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
+import static dagger.internal.codegen.langmodel.DaggerElements.elementEncloses;
+import static java.util.Collections.min;
+import static java.util.Comparator.comparing;
+import static java.util.Comparator.comparingInt;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Table;
+import com.google.errorprone.annotations.FormatMethod;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.BindingGraph;
+import dagger.model.BindingGraph.ChildFactoryMethodEdge;
+import dagger.model.BindingGraph.ComponentNode;
+import dagger.model.BindingGraph.DependencyEdge;
+import dagger.model.BindingGraph.Edge;
+import dagger.model.BindingGraph.MaybeBinding;
+import dagger.model.BindingGraph.Node;
+import dagger.model.ComponentPath;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import java.util.Comparator;
+import java.util.Set;
+import java.util.function.Function;
+import javax.annotation.processing.Messager;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import org.checkerframework.checker.nullness.compatqual.NullableDecl;
+
+/** A factory for {@link DiagnosticReporter}s. */
+// TODO(ronshapiro): If multiple plugins print errors on the same node/edge, should we condense the
+// messages and only print the dependency trace once?
+final class DiagnosticReporterFactory {
+  private final DaggerTypes types;
+  private final Messager messager;
+  private final DependencyRequestFormatter dependencyRequestFormatter;
+  private final ElementFormatter elementFormatter;
+  private final CompilerOptions compilerOptions;
+
+  @Inject
+  DiagnosticReporterFactory(
+      DaggerTypes types,
+      Messager messager,
+      DependencyRequestFormatter dependencyRequestFormatter,
+      ElementFormatter elementFormatter,
+      CompilerOptions compilerOptions) {
+    this.types = types;
+    this.messager = messager;
+    this.dependencyRequestFormatter = dependencyRequestFormatter;
+    this.elementFormatter = elementFormatter;
+    this.compilerOptions = compilerOptions;
+  }
+
+  /** Creates a reporter for a binding graph and a plugin. */
+  DiagnosticReporterImpl reporter(BindingGraph graph, BindingGraphPlugin plugin) {
+    return new DiagnosticReporterImpl(graph, plugin.pluginName());
+  }
+
+  private static <K, V> Function<K, V> memoize(Function<K, V> uncached) {
+    // If Android Guava is on the processor path, then c.g.c.b.Function (which LoadingCache
+    // implements) does not extend j.u.f.Function.
+
+    // First, explicitly convert uncached to c.g.c.b.Function because CacheLoader.from() expects
+    // one.
+    com.google.common.base.Function<K, V> uncachedAsBaseFunction = uncached::apply;
+
+    LoadingCache<K, V> cache =
+        CacheBuilder.newBuilder().build(CacheLoader.from(uncachedAsBaseFunction));
+
+    // Second, explicitly convert LoadingCache to j.u.f.Function.
+    @SuppressWarnings("deprecation") // uncachedAsBaseFunction throws only unchecked exceptions
+    Function<K, V> memoized = cache::apply;
+
+    return memoized;
+  }
+
+  /**
+   * A {@link DiagnosticReporter} that keeps track of which {@linkplain Diagnostic.Kind kinds} of
+   * diagnostics were reported.
+   */
+  final class DiagnosticReporterImpl implements DiagnosticReporter {
+
+    /** A cached function from type to all of its supertypes in breadth-first order. */
+    private final Function<TypeElement, Iterable<TypeElement>> supertypes =
+        memoize(
+            component ->
+                transform(types.supertypes(component.asType()), type -> asTypeElement(type)));
+
+    /** The shortest path (value) from an entry point (column) to a binding (row). */
+    private final Table<MaybeBinding, DependencyEdge, ImmutableList<Node>> shortestPaths =
+        HashBasedTable.create();
+
+    private final BindingGraph graph;
+    private final String plugin;
+    private final TypeElement rootComponent;
+    private final ImmutableSet.Builder<Diagnostic.Kind> reportedDiagnosticKinds =
+        ImmutableSet.builder();
+
+    DiagnosticReporterImpl(BindingGraph graph, String plugin) {
+      this.graph = graph;
+      this.plugin = plugin;
+      this.rootComponent = graph.rootComponentNode().componentPath().currentComponent();
+    }
+
+    /** Returns which {@linkplain Diagnostic.Kind kinds} of diagnostics were reported. */
+    ImmutableSet<Diagnostic.Kind> reportedDiagnosticKinds() {
+      return reportedDiagnosticKinds.build();
+    }
+
+    @Override
+    public void reportComponent(
+        Diagnostic.Kind diagnosticKind, ComponentNode componentNode, String messageFormat) {
+      StringBuilder message = new StringBuilder(messageFormat);
+      appendComponentPathUnlessAtRoot(message, componentNode);
+      // TODO(dpb): Report at the component node component.
+      printMessage(diagnosticKind, message, rootComponent);
+    }
+
+    @Override
+    @FormatMethod
+    public void reportComponent(
+        Diagnostic.Kind diagnosticKind,
+        ComponentNode componentNode,
+        String messageFormat,
+        Object firstArg,
+        Object... moreArgs) {
+      reportComponent(
+          diagnosticKind, componentNode, formatMessage(messageFormat, firstArg, moreArgs));
+    }
+
+    // TODO(ronshapiro): should this also include the binding element?
+    @Override
+    public void reportBinding(
+        Diagnostic.Kind diagnosticKind, MaybeBinding binding, String message) {
+      printMessage(diagnosticKind, message + new DiagnosticInfo(binding), rootComponent);
+    }
+
+    @Override
+    public void reportBinding(
+        Diagnostic.Kind diagnosticKind,
+        MaybeBinding binding,
+        String messageFormat,
+        Object firstArg,
+        Object... moreArgs) {
+      reportBinding(diagnosticKind, binding, formatMessage(messageFormat, firstArg, moreArgs));
+    }
+
+    @Override
+    public void reportDependency(
+        Diagnostic.Kind diagnosticKind, DependencyEdge dependencyEdge, String message) {
+      printMessage(diagnosticKind, message + new DiagnosticInfo(dependencyEdge), rootComponent);
+    }
+
+    @Override
+    public void reportDependency(
+        Diagnostic.Kind diagnosticKind,
+        DependencyEdge dependencyEdge,
+        String messageFormat,
+        Object firstArg,
+        Object... moreArgs) {
+      reportDependency(
+          diagnosticKind, dependencyEdge, formatMessage(messageFormat, firstArg, moreArgs));
+    }
+
+    @Override
+    public void reportSubcomponentFactoryMethod(
+        Diagnostic.Kind diagnosticKind,
+        ChildFactoryMethodEdge childFactoryMethodEdge,
+        String message) {
+      printMessage(diagnosticKind, 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());
+    }
+
+    private Node source(Edge edge) {
+      return graph.network().incidentNodes(edge).source();
+    }
+
+    void printMessage(
+        Diagnostic.Kind diagnosticKind,
+        CharSequence message,
+        @NullableDecl Element elementToReport) {
+      if (graph.isFullBindingGraph()) {
+        ValidationType validationType =
+            compilerOptions.fullBindingGraphValidationType(rootComponent);
+        if (validationType.equals(NONE)) {
+          return;
+        }
+        if (diagnosticKind.equals(ERROR)) {
+          diagnosticKind = validationType.diagnosticKind().get();
+        }
+      }
+      reportedDiagnosticKinds.add(diagnosticKind);
+      StringBuilder fullMessage = new StringBuilder();
+      appendBracketPrefix(fullMessage, plugin);
+
+      // TODO(ronshapiro): should we create a HashSet out of elementEncloses() so we don't
+      // need to do an O(n) contains() each time?
+      if (elementToReport != null && !elementEncloses(rootComponent, elementToReport)) {
+        appendBracketPrefix(fullMessage, elementToString(elementToReport));
+        elementToReport = rootComponent;
+      }
+
+      messager.printMessage(diagnosticKind, fullMessage.append(message), elementToReport);
+    }
+
+    private void appendComponentPathUnlessAtRoot(StringBuilder message, Node node) {
+      if (!node.componentPath().equals(graph.rootComponentNode().componentPath())) {
+        message.append(String.format(" [%s]", node.componentPath()));
+      }
+    }
+
+    private void appendBracketPrefix(StringBuilder message, String prefix) {
+      message.append(String.format("[%s] ", prefix));
+    }
+
+    /** The diagnostic information associated with an error. */
+    private final class DiagnosticInfo {
+      final ImmutableList<DependencyEdge> dependencyTrace;
+      final ImmutableSet<DependencyEdge> requests;
+      final ImmutableSet<DependencyEdge> entryPoints;
+
+      DiagnosticInfo(MaybeBinding binding) {
+        entryPoints = graph.entryPointEdgesDependingOnBinding(binding);
+        requests = requests(binding);
+        dependencyTrace = dependencyTrace(binding, entryPoints);
+      }
+
+      DiagnosticInfo(DependencyEdge dependencyEdge) {
+        requests = ImmutableSet.of(dependencyEdge);
+        ImmutableList.Builder<DependencyEdge> dependencyTraceBuilder = ImmutableList.builder();
+        dependencyTraceBuilder.add(dependencyEdge);
+
+        if (dependencyEdge.isEntryPoint()) {
+          entryPoints = ImmutableSet.of(dependencyEdge);
+        } else {
+          // It's not an entry point, so it's part of a binding
+          dagger.model.Binding binding = (dagger.model.Binding) source(dependencyEdge);
+          entryPoints = graph.entryPointEdgesDependingOnBinding(binding);
+          dependencyTraceBuilder.addAll(dependencyTrace(binding, entryPoints));
+        }
+        dependencyTrace = dependencyTraceBuilder.build();
+      }
+
+      @Override
+      public String toString() {
+        StringBuilder message =
+            graph.isFullBindingGraph()
+                ? new StringBuilder()
+                : new StringBuilder(dependencyTrace.size() * 100 /* a guess heuristic */);
+
+        // Print the dependency trace unless it's a full binding graph
+        if (!graph.isFullBindingGraph()) {
+          dependencyTrace.forEach(
+              edge ->
+                  dependencyRequestFormatter.appendFormatLine(message, edge.dependencyRequest()));
+          if (!dependencyTrace.isEmpty()) {
+            appendComponentPathUnlessAtRoot(message, source(getLast(dependencyTrace)));
+          }
+        }
+
+        // Print any dependency requests that aren't shown as part of the dependency trace.
+        ImmutableSet<Element> requestsToPrint =
+            requests.stream()
+                // if printing entry points, skip entry points and the traced request
+                .filter(
+                    request ->
+                        graph.isFullBindingGraph()
+                            || (!request.isEntryPoint() && !isTracedRequest(request)))
+                .map(request -> request.dependencyRequest().requestElement())
+                .flatMap(presentValues())
+                .collect(toImmutableSet());
+        if (!requestsToPrint.isEmpty()) {
+          message
+              .append("\nIt is")
+              .append(graph.isFullBindingGraph() ? " " : " also ")
+              .append("requested at:");
+          elementFormatter.formatIndentedList(message, requestsToPrint, 1);
+        }
+
+        // Print the remaining entry points, showing which component they're in, unless it's a full
+        // binding graph
+        if (!graph.isFullBindingGraph() && entryPoints.size() > 1) {
+          message.append("\nThe following other entry points also depend on it:");
+          entryPointFormatter.formatIndentedList(
+              message,
+              entryPoints.stream()
+                  .filter(entryPoint -> !entryPoint.equals(getLast(dependencyTrace)))
+                  .sorted(
+                      // 1. List entry points in components closest to the root first.
+                      // 2. List entry points declared in a component before those in a supertype.
+                      // 3. List entry points in declaration order in their declaring type.
+                      rootComponentFirst()
+                          .thenComparing(nearestComponentSupertypeFirst())
+                          .thenComparing(requestElementDeclarationOrder()))
+                  .collect(toImmutableList()),
+              1);
+        }
+        return message.toString();
+      }
+
+      private final Formatter<DependencyEdge> entryPointFormatter =
+          new Formatter<DependencyEdge>() {
+            @Override
+            public String format(DependencyEdge object) {
+              Element requestElement = object.dependencyRequest().requestElement().get();
+              StringBuilder element = new StringBuilder(elementToString(requestElement));
+
+              // For entry points declared in subcomponents or supertypes of the root component,
+              // append the component path to make clear to the user which component it's in.
+              ComponentPath componentPath = source(object).componentPath();
+              if (!componentPath.atRoot()
+                  || !requestElement.getEnclosingElement().equals(rootComponent)) {
+                element.append(String.format(" [%s]", componentPath));
+              }
+              return element.toString();
+            }
+          };
+
+      private boolean isTracedRequest(DependencyEdge request) {
+        return !dependencyTrace.isEmpty() && request.equals(dependencyTrace.get(0));
+      }
+
+      /**
+       * Returns the dependency trace from one of the {@code entryPoints} to {@code binding} to
+       * {@code message} as a list <i>ending with</i> the entry point.
+       */
+      // TODO(ronshapiro): Adding a DependencyPath type to dagger.model could be useful, i.e.
+      // bindingGraph.shortestPathFromEntryPoint(DependencyEdge, MaybeBindingNode)
+      ImmutableList<DependencyEdge> dependencyTrace(
+          MaybeBinding binding, ImmutableSet<DependencyEdge> entryPoints) {
+        // Module binding graphs may have bindings unreachable from any entry points. If there are
+        // no entry points for this DiagnosticInfo, don't try to print a dependency trace.
+        if (entryPoints.isEmpty()) {
+          return ImmutableList.of();
+        }
+        // Show the full dependency trace for one entry point.
+        DependencyEdge entryPointForTrace =
+            min(
+                entryPoints,
+                // prefer entry points in components closest to the root
+                rootComponentFirst()
+                    // then prefer entry points with a short dependency path to the error
+                    .thenComparing(shortestDependencyPathFirst(binding))
+                    // then prefer entry points declared in the component to those declared in a
+                    // supertype
+                    .thenComparing(nearestComponentSupertypeFirst())
+                    // finally prefer entry points declared first in their enclosing type
+                    .thenComparing(requestElementDeclarationOrder()));
+
+        ImmutableList<Node> shortestBindingPath =
+            shortestPathFromEntryPoint(entryPointForTrace, binding);
+        verify(
+            !shortestBindingPath.isEmpty(),
+            "no dependency path from %s to %s in %s",
+            entryPointForTrace,
+            binding,
+            graph);
+
+        ImmutableList.Builder<DependencyEdge> dependencyTrace = ImmutableList.builder();
+        dependencyTrace.add(entryPointForTrace);
+        for (int i = 0; i < shortestBindingPath.size() - 1; i++) {
+          Set<Edge> dependenciesBetween =
+              graph
+                  .network()
+                  .edgesConnecting(shortestBindingPath.get(i), shortestBindingPath.get(i + 1));
+          // If a binding requests a key more than once, any of them should be fine to get to the
+          // shortest path
+          dependencyTrace.add((DependencyEdge) Iterables.get(dependenciesBetween, 0));
+        }
+        return dependencyTrace.build().reverse();
+      }
+
+      /** Returns all the nonsynthetic dependency requests for a binding. */
+      ImmutableSet<DependencyEdge> requests(MaybeBinding binding) {
+        return graph.network().inEdges(binding).stream()
+            .flatMap(instancesOf(DependencyEdge.class))
+            .filter(edge -> edge.dependencyRequest().requestElement().isPresent())
+            .sorted(requestEnclosingTypeName().thenComparing(requestElementDeclarationOrder()))
+            .collect(toImmutableSet());
+      }
+
+      /**
+       * Returns a comparator that sorts entry points in components whose paths from the root are
+       * shorter first.
+       */
+      Comparator<DependencyEdge> rootComponentFirst() {
+        return comparingInt(entryPoint -> source(entryPoint).componentPath().components().size());
+      }
+
+      /**
+       * Returns a comparator that puts entry points whose shortest dependency path to {@code
+       * binding} is shortest first.
+       */
+      Comparator<DependencyEdge> shortestDependencyPathFirst(MaybeBinding binding) {
+        return comparing(entryPoint -> shortestPathFromEntryPoint(entryPoint, binding).size());
+      }
+
+      ImmutableList<Node> shortestPathFromEntryPoint(
+          DependencyEdge entryPoint, MaybeBinding binding) {
+        return shortestPaths
+            .row(binding)
+            .computeIfAbsent(
+                entryPoint,
+                ep ->
+                    shortestPath(
+                        node ->
+                            filter(
+                                graph.network().successors(node), MaybeBinding.class::isInstance),
+                        graph.network().incidentNodes(ep).target(),
+                        binding));
+      }
+
+      /**
+       * Returns a comparator that sorts entry points in by the distance of the type that declares
+       * them from the type of the component that contains them.
+       *
+       * <p>For instance, an entry point declared directly in the component type would sort before
+       * one declared in a direct supertype, which would sort before one declared in a supertype of
+       * a supertype.
+       */
+      Comparator<DependencyEdge> nearestComponentSupertypeFirst() {
+        return comparingInt(
+            entryPoint ->
+                indexOf(
+                    supertypes.apply(componentContainingEntryPoint(entryPoint)),
+                    equalTo(typeDeclaringEntryPoint(entryPoint))));
+      }
+
+      TypeElement componentContainingEntryPoint(DependencyEdge entryPoint) {
+        return source(entryPoint).componentPath().currentComponent();
+      }
+
+      TypeElement typeDeclaringEntryPoint(DependencyEdge entryPoint) {
+        return MoreElements.asType(
+            entryPoint.dependencyRequest().requestElement().get().getEnclosingElement());
+      }
+
+      /**
+       * Returns a comparator that sorts dependency edges lexicographically by the qualified name of
+       * the type that contains them. Only appropriate for edges with request elements.
+       */
+      Comparator<DependencyEdge> requestEnclosingTypeName() {
+        return comparing(
+            edge ->
+                closestEnclosingTypeElement(edge.dependencyRequest().requestElement().get())
+                    .getQualifiedName()
+                    .toString());
+      }
+
+      /**
+       * Returns a comparator that sorts edges in the order in which their request elements were
+       * declared in their declaring type.
+       *
+       * <p>Only useful to compare edges whose request elements were declared in the same type.
+       */
+      Comparator<DependencyEdge> requestElementDeclarationOrder() {
+        return comparing(
+            edge -> edge.dependencyRequest().requestElement().get(), DECLARATION_ORDER);
+      }
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DuplicateBindingsValidator.java b/java/dagger/internal/codegen/DuplicateBindingsValidator.java
new file mode 100644
index 0000000..3eed45f
--- /dev/null
+++ b/java/dagger/internal/codegen/DuplicateBindingsValidator.java
@@ -0,0 +1,332 @@
+/*
+ * 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.common.base.Verify.verify;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSetMultimap;
+import static dagger.internal.codegen.Formatter.INDENT;
+import static dagger.internal.codegen.Optionals.emptiesLast;
+import static dagger.model.BindingKind.INJECTION;
+import static dagger.model.BindingKind.MEMBERS_INJECTION;
+import static java.util.Comparator.comparing;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMultiset;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.Sets;
+import dagger.model.Binding;
+import dagger.model.BindingGraph;
+import dagger.model.BindingKind;
+import dagger.model.ComponentPath;
+import dagger.model.Key;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Predicate;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic.Kind;
+
+/** Reports errors for conflicting bindings with the same key. */
+final class DuplicateBindingsValidator implements BindingGraphPlugin {
+
+  // 1. contributing module or enclosing type
+  // 2. binding element's simple name
+  // 3. binding element's type
+  private static final Comparator<BindingDeclaration> BINDING_DECLARATION_COMPARATOR =
+      comparing(
+              (BindingDeclaration declaration) ->
+                  declaration.contributingModule().isPresent()
+                      ? declaration.contributingModule()
+                      : declaration.bindingTypeElement(),
+              emptiesLast(comparing((TypeElement type) -> type.getQualifiedName().toString())))
+          .thenComparing(
+              (BindingDeclaration declaration) -> declaration.bindingElement(),
+              emptiesLast(
+                  comparing((Element element) -> element.getSimpleName().toString())
+                      .thenComparing((Element element) -> element.asType().toString())));
+
+  private static final Comparator<Binding> BY_LENGTH_OF_COMPONENT_PATH =
+      comparing(binding -> binding.componentPath().components().size());
+
+  private final BindingDeclarationFormatter bindingDeclarationFormatter;
+  private final CompilerOptions compilerOptions;
+
+  @Inject
+  DuplicateBindingsValidator(
+      BindingDeclarationFormatter bindingDeclarationFormatter, CompilerOptions compilerOptions) {
+    this.bindingDeclarationFormatter = bindingDeclarationFormatter;
+    this.compilerOptions = compilerOptions;
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/DuplicateBindings";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    // If two unrelated subcomponents have the same duplicate bindings only because they install the
+    // same two modules, then fixing the error in one subcomponent will uncover the second
+    // subcomponent to fix.
+    // TODO(ronshapiro): Explore ways to address such underreporting without overreporting.
+    Set<ImmutableSet<BindingElement>> reportedDuplicateBindingSets = new HashSet<>();
+    duplicateBindingSets(bindingGraph)
+        .forEach(
+            duplicateBindings -> {
+              // Only report each set of duplicate bindings once, ignoring the installed component.
+              if (reportedDuplicateBindingSets.add(duplicateBindings.keySet())) {
+                reportDuplicateBindings(duplicateBindings, bindingGraph, diagnosticReporter);
+              }
+            });
+  }
+
+  /**
+   * Returns sets of duplicate bindings. Bindings are duplicates if they bind the same key and are
+   * visible from the same component. Two bindings that differ only in the component that owns them
+   * are not considered to be duplicates, because that means the same binding was "copied" down to a
+   * descendant component because it depends on local multibindings or optional bindings. Hence each
+   * "set" is represented as a multimap from binding element (ignoring component path) to binding.
+   */
+  private ImmutableSet<ImmutableSetMultimap<BindingElement, Binding>> duplicateBindingSets(
+      BindingGraph bindingGraph) {
+    return groupBindingsByKey(bindingGraph).stream()
+        .flatMap(bindings -> mutuallyVisibleSubsets(bindings).stream())
+        .map(BindingElement::index)
+        .filter(duplicates -> duplicates.keySet().size() > 1)
+        .collect(toImmutableSet());
+  }
+
+  private static ImmutableSet<ImmutableSet<Binding>> groupBindingsByKey(BindingGraph bindingGraph) {
+    return valueSetsForEachKey(
+        bindingGraph.bindings().stream()
+            .filter(binding -> !binding.kind().equals(MEMBERS_INJECTION))
+            .collect(toImmutableSetMultimap(Binding::key, binding -> binding)));
+  }
+
+  /**
+   * Returns the subsets of the input set that contain bindings that are all visible from the same
+   * component. A binding is visible from its component and all its descendants.
+   */
+  private static ImmutableSet<ImmutableSet<Binding>> mutuallyVisibleSubsets(
+      Set<Binding> duplicateBindings) {
+    ImmutableListMultimap<ComponentPath, Binding> bindingsByComponentPath =
+        Multimaps.index(duplicateBindings, Binding::componentPath);
+    ImmutableSetMultimap.Builder<ComponentPath, Binding> mutuallyVisibleBindings =
+        ImmutableSetMultimap.builder();
+    bindingsByComponentPath
+        .asMap()
+        .forEach(
+            (componentPath, bindings) -> {
+              mutuallyVisibleBindings.putAll(componentPath, bindings);
+              for (ComponentPath ancestor = componentPath; !ancestor.atRoot(); ) {
+                ancestor = ancestor.parent();
+                ImmutableList<Binding> bindingsInAncestor = bindingsByComponentPath.get(ancestor);
+                mutuallyVisibleBindings.putAll(componentPath, bindingsInAncestor);
+              }
+            });
+    return valueSetsForEachKey(mutuallyVisibleBindings.build());
+  }
+
+  private void reportDuplicateBindings(
+      ImmutableSetMultimap<BindingElement, Binding> duplicateBindings,
+      BindingGraph bindingGraph,
+      DiagnosticReporter diagnosticReporter) {
+    if (explicitBindingConfictsWithInject(duplicateBindings.keySet())) {
+      compilerOptions
+          .explicitBindingConflictsWithInjectValidationType()
+          .diagnosticKind()
+          .ifPresent(
+              diagnosticKind ->
+                  reportExplicitBindingConflictsWithInject(
+                      duplicateBindings, diagnosticReporter, diagnosticKind));
+      return;
+    }
+    ImmutableSet<Binding> bindings = ImmutableSet.copyOf(duplicateBindings.values());
+    Binding oneBinding = bindings.asList().get(0);
+    diagnosticReporter.reportBinding(
+        ERROR,
+        oneBinding,
+        Iterables.any(bindings, binding -> binding.kind().isMultibinding())
+            ? incompatibleBindingsMessage(oneBinding.key(), bindings, bindingGraph)
+            : duplicateBindingMessage(oneBinding.key(), bindings, bindingGraph));
+  }
+
+  /**
+   * Returns {@code true} if the bindings contain one {@code @Inject} binding and one that isn't.
+   */
+  private static boolean explicitBindingConfictsWithInject(
+      ImmutableSet<BindingElement> duplicateBindings) {
+    ImmutableMultiset<BindingKind> bindingKinds =
+        Multimaps.index(duplicateBindings, BindingElement::bindingKind).keys();
+    return bindingKinds.count(INJECTION) == 1 && bindingKinds.size() == 2;
+  }
+
+  private void reportExplicitBindingConflictsWithInject(
+      ImmutableSetMultimap<BindingElement, Binding> duplicateBindings,
+      DiagnosticReporter diagnosticReporter,
+      Kind diagnosticKind) {
+    Binding injectBinding =
+        rootmostBindingWithKind(k -> k.equals(INJECTION), duplicateBindings.values());
+    Binding explicitBinding =
+        rootmostBindingWithKind(k -> !k.equals(INJECTION), duplicateBindings.values());
+    StringBuilder message =
+        new StringBuilder()
+            .append(explicitBinding.key())
+            .append(" is bound multiple times:")
+            .append(formatWithComponentPath(injectBinding))
+            .append(formatWithComponentPath(explicitBinding))
+            .append(
+                "\nThis condition was never validated before, and will soon be an error. "
+                    + "See https://dagger.dev/conflicting-inject.");
+
+    diagnosticReporter.reportBinding(diagnosticKind, explicitBinding, message.toString());
+  }
+
+  private String formatWithComponentPath(Binding binding) {
+    return String.format(
+        "\n%s%s [%s]",
+        Formatter.INDENT,
+        bindingDeclarationFormatter.format(((BindingNode) binding).delegate()),
+        binding.componentPath());
+  }
+
+  private String duplicateBindingMessage(
+      Key key, ImmutableSet<Binding> duplicateBindings, BindingGraph graph) {
+    StringBuilder message = new StringBuilder().append(key).append(" is bound multiple times:");
+    formatDeclarations(message, 1, declarations(graph, duplicateBindings));
+    return message.toString();
+  }
+
+  private String incompatibleBindingsMessage(
+      Key key, ImmutableSet<Binding> duplicateBindings, BindingGraph graph) {
+    ImmutableSet<dagger.model.Binding> multibindings =
+        duplicateBindings.stream()
+            .filter(binding -> binding.kind().isMultibinding())
+            .collect(toImmutableSet());
+    verify(
+        multibindings.size() == 1, "expected only one multibinding for %s: %s", key, multibindings);
+    StringBuilder message = new StringBuilder();
+    java.util.Formatter messageFormatter = new java.util.Formatter(message);
+    messageFormatter.format("%s has incompatible bindings or declarations:\n", key);
+    message.append(INDENT);
+    dagger.model.Binding multibinding = getOnlyElement(multibindings);
+    messageFormatter.format("%s bindings and declarations:", multibindingTypeString(multibinding));
+    formatDeclarations(message, 2, declarations(graph, multibindings));
+
+    Set<dagger.model.Binding> uniqueBindings =
+        Sets.filter(duplicateBindings, binding -> !binding.equals(multibinding));
+    message.append('\n').append(INDENT).append("Unique bindings and declarations:");
+    formatDeclarations(
+        message,
+        2,
+        Sets.filter(
+            declarations(graph, uniqueBindings),
+            declaration -> !(declaration instanceof MultibindingDeclaration)));
+    return message.toString();
+  }
+
+  private void formatDeclarations(
+      StringBuilder builder,
+      int indentLevel,
+      Iterable<? extends BindingDeclaration> bindingDeclarations) {
+    bindingDeclarationFormatter.formatIndentedList(
+        builder, ImmutableList.copyOf(bindingDeclarations), indentLevel);
+  }
+
+  private ImmutableSet<BindingDeclaration> declarations(
+      BindingGraph graph, Set<dagger.model.Binding> bindings) {
+    return bindings.stream()
+        .flatMap(binding -> declarations(graph, binding).stream())
+        .distinct()
+        .sorted(BINDING_DECLARATION_COMPARATOR)
+        .collect(toImmutableSet());
+  }
+
+  private ImmutableSet<BindingDeclaration> declarations(
+      BindingGraph graph, dagger.model.Binding binding) {
+    ImmutableSet.Builder<BindingDeclaration> declarations = ImmutableSet.builder();
+    BindingNode bindingNode = (BindingNode) binding;
+    bindingNode.associatedDeclarations().forEach(declarations::add);
+    if (bindingDeclarationFormatter.canFormat(bindingNode.delegate())) {
+      declarations.add(bindingNode.delegate());
+    } else {
+      graph.requestedBindings(binding).stream()
+          .flatMap(requestedBinding -> declarations(graph, requestedBinding).stream())
+          .forEach(declarations::add);
+    }
+    return declarations.build();
+  }
+
+  private String multibindingTypeString(dagger.model.Binding multibinding) {
+    switch (multibinding.kind()) {
+      case MULTIBOUND_MAP:
+        return "Map";
+      case MULTIBOUND_SET:
+        return "Set";
+      default:
+        throw new AssertionError(multibinding);
+    }
+  }
+
+  private static <E> ImmutableSet<ImmutableSet<E>> valueSetsForEachKey(Multimap<?, E> multimap) {
+    return multimap.asMap().values().stream().map(ImmutableSet::copyOf).collect(toImmutableSet());
+  }
+
+  /** Returns the binding of the given kind that is closest to the root component. */
+  private static Binding rootmostBindingWithKind(
+      Predicate<BindingKind> bindingKindPredicate, ImmutableCollection<Binding> bindings) {
+    return bindings.stream()
+        .filter(b -> bindingKindPredicate.test(b.kind()))
+        .min(BY_LENGTH_OF_COMPONENT_PATH)
+        .get();
+  }
+
+  /** The identifying information about a binding, excluding its {@link Binding#componentPath()}. */
+  @AutoValue
+  abstract static class BindingElement {
+
+    abstract BindingKind bindingKind();
+
+    abstract Optional<Element> bindingElement();
+
+    abstract Optional<TypeElement> contributingModule();
+
+    static ImmutableSetMultimap<BindingElement, Binding> index(Set<Binding> bindings) {
+      return bindings.stream().collect(toImmutableSetMultimap(BindingElement::forBinding, b -> b));
+    }
+
+    private static BindingElement forBinding(Binding binding) {
+      return new AutoValue_DuplicateBindingsValidator_BindingElement(
+          binding.kind(), binding.bindingElement(), binding.contributingModule());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ElementFormatter.java b/java/dagger/internal/codegen/ElementFormatter.java
new file mode 100644
index 0000000..40d7606
--- /dev/null
+++ b/java/dagger/internal/codegen/ElementFormatter.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 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.MoreElements.asExecutable;
+import static java.util.stream.Collectors.joining;
+
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.ElementKindVisitor8;
+
+/**
+ * Formats elements into a useful string representation.
+ *
+ * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
+ *
+ * <p>Parameters are given with their enclosing executable, with other parameters elided.
+ */
+final class ElementFormatter extends Formatter<Element> {
+  @Inject
+  ElementFormatter() {}
+
+  @Override
+  public String format(Element element) {
+    return elementToString(element);
+  }
+
+  /**
+   * Returns a useful string form for an element.
+   *
+   * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
+   *
+   * <p>Parameters are given with their enclosing executable, with other parameters elided.
+   */
+  static String elementToString(Element element) {
+    return element.accept(ELEMENT_TO_STRING, null);
+  }
+
+  private static final ElementVisitor<String, Void> ELEMENT_TO_STRING =
+      new ElementKindVisitor8<String, Void>() {
+        @Override
+        public String visitExecutable(ExecutableElement executableElement, Void aVoid) {
+          return enclosingTypeAndMemberName(executableElement)
+              .append(
+                  executableElement.getParameters().stream()
+                      .map(parameter -> parameter.asType().toString())
+                      .collect(joining(", ", "(", ")")))
+              .toString();
+        }
+
+        @Override
+        public String visitVariableAsParameter(VariableElement parameter, Void aVoid) {
+          ExecutableElement methodOrConstructor = asExecutable(parameter.getEnclosingElement());
+          return enclosingTypeAndMemberName(methodOrConstructor)
+              .append('(')
+              .append(
+                  formatArgumentInList(
+                      methodOrConstructor.getParameters().indexOf(parameter),
+                      methodOrConstructor.getParameters().size(),
+                      parameter.getSimpleName()))
+              .append(')')
+              .toString();
+        }
+
+        @Override
+        public String visitVariableAsField(VariableElement field, Void aVoid) {
+          return enclosingTypeAndMemberName(field).toString();
+        }
+
+        @Override
+        public String visitType(TypeElement type, Void aVoid) {
+          return type.getQualifiedName().toString();
+        }
+
+        @Override
+        protected String defaultAction(Element element, Void aVoid) {
+          throw new UnsupportedOperationException(
+              "Can't determine string for " + element.getKind() + " element " + element);
+        }
+
+        private StringBuilder enclosingTypeAndMemberName(Element element) {
+          StringBuilder name = new StringBuilder(element.getEnclosingElement().accept(this, null));
+          if (!element.getSimpleName().contentEquals("<init>")) {
+            name.append('.').append(element.getSimpleName());
+          }
+          return name;
+        }
+      };
+}
diff --git a/java/dagger/internal/codegen/ErrorMessages.java b/java/dagger/internal/codegen/ErrorMessages.java
new file mode 100644
index 0000000..4195e1a
--- /dev/null
+++ b/java/dagger/internal/codegen/ErrorMessages.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2014 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.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/** The collection of error messages to be reported back to users. */
+final class ErrorMessages {
+
+  private static final UnaryOperator<String> PRODUCTION =
+      s ->
+          s.replace("component", "production component")
+              .replace("Component", "ProductionComponent");
+
+  private static final UnaryOperator<String> SUBCOMPONENT =
+      s -> s.replace("component", "subcomponent").replace("Component", "Subcomponent");
+
+  private static final UnaryOperator<String> FACTORY = s -> s.replace("Builder", "Factory");
+
+  private static final ImmutableMap<ComponentKind, Function<String, String>>
+      COMPONENT_TRANSFORMATIONS =
+          ImmutableMap.of(
+              ComponentKind.COMPONENT, UnaryOperator.identity(),
+              ComponentKind.SUBCOMPONENT, SUBCOMPONENT,
+              ComponentKind.PRODUCTION_COMPONENT, PRODUCTION,
+              ComponentKind.PRODUCTION_SUBCOMPONENT, PRODUCTION.andThen(SUBCOMPONENT));
+
+  static ComponentMessages componentMessagesFor(ComponentKind componentKind) {
+    return new ComponentMessages(COMPONENT_TRANSFORMATIONS.get(componentKind));
+  }
+
+  static ComponentMessages componentMessagesFor(ComponentAnnotation componentAnnotation) {
+    return new ComponentMessages(
+        transformation(componentAnnotation.isProduction(), componentAnnotation.isSubcomponent()));
+  }
+
+  static ComponentCreatorMessages creatorMessagesFor(ComponentCreatorAnnotation creatorAnnotation) {
+    Function<String, String> transformation =
+        transformation(
+            creatorAnnotation.isProductionCreatorAnnotation(),
+            creatorAnnotation.isSubcomponentCreatorAnnotation());
+    switch (creatorAnnotation.creatorKind()) {
+      case BUILDER:
+        return new BuilderMessages(transformation);
+      case FACTORY:
+        return new FactoryMessages(transformation);
+    }
+    throw new AssertionError(creatorAnnotation);
+  }
+
+  private static Function<String, String> transformation(
+      boolean isProduction, boolean isSubcomponent) {
+    Function<String, String> transformation = isProduction ? PRODUCTION : UnaryOperator.identity();
+    return isSubcomponent ? transformation.andThen(SUBCOMPONENT) : transformation;
+  }
+
+  private abstract static class Messages {
+    private final Function<String, String> transformation;
+
+    Messages(Function<String, String> transformation) {
+      this.transformation = transformation;
+    }
+
+    protected final String process(String s) {
+      return transformation.apply(s);
+    }
+  }
+
+  /** Errors for components. */
+  static final class ComponentMessages extends Messages {
+    ComponentMessages(Function<String, String> transformation) {
+      super(transformation);
+    }
+
+    final String moreThanOne() {
+      return process("@Component has more than one @Component.Builder or @Component.Factory: %s");
+    }
+  }
+
+  /** Errors for component creators. */
+  abstract static class ComponentCreatorMessages extends Messages {
+    ComponentCreatorMessages(Function<String, String> transformation) {
+      super(transformation);
+    }
+
+    static String builderMethodRequiresNoArgs() {
+      return "Methods returning a @Component.Builder must have no arguments";
+    }
+
+    static String moreThanOneRefToSubcomponent() {
+      return "Only one method can create a given subcomponent. %s is created by: %s";
+    }
+
+    final String invalidConstructor() {
+      return process("@Component.Builder classes must have exactly one constructor,"
+          + " and it must not be private or have any parameters");
+    }
+
+    final String generics() {
+      return process("@Component.Builder types must not have any generic types");
+    }
+
+    final String mustBeInComponent() {
+      return process("@Component.Builder types must be nested within a @Component");
+    }
+
+    final String mustBeClassOrInterface() {
+      return process("@Component.Builder types must be abstract classes or interfaces");
+    }
+
+    final String isPrivate() {
+      return process("@Component.Builder types must not be private");
+    }
+
+    final String mustBeStatic() {
+      return process("@Component.Builder types must be static");
+    }
+
+    final String mustBeAbstract() {
+      return process("@Component.Builder types must be abstract");
+    }
+
+    abstract String missingFactoryMethod();
+
+    abstract String multipleSettersForModuleOrDependencyType();
+
+    abstract String extraSetters();
+
+    abstract String missingSetters();
+
+    abstract String twoFactoryMethods();
+
+    abstract String inheritedTwoFactoryMethods();
+
+    abstract String factoryMethodMustReturnComponentType();
+
+    final String inheritedFactoryMethodMustReturnComponentType() {
+      return factoryMethodMustReturnComponentType() + ". Inherited method: %s";
+    }
+
+    abstract String factoryMethodMayNotBeAnnotatedWithBindsInstance();
+
+    final String inheritedFactoryMethodMayNotBeAnnotatedWithBindsInstance() {
+      return factoryMethodMayNotBeAnnotatedWithBindsInstance() + ". Inherited method: %s";
+    }
+
+    final String setterMethodsMustTakeOneArg() {
+      return process("@Component.Builder methods must not have more than one argument");
+    }
+
+    final String inheritedSetterMethodsMustTakeOneArg() {
+      return setterMethodsMustTakeOneArg() + ". Inherited method: %s";
+    }
+
+    final String setterMethodsMustReturnVoidOrBuilder() {
+      return process("@Component.Builder setter methods must return void, the builder,"
+          + " or a supertype of the builder");
+    }
+
+    final String inheritedSetterMethodsMustReturnVoidOrBuilder() {
+      return setterMethodsMustReturnVoidOrBuilder() + ". Inherited method: %s";
+    }
+
+    final String methodsMayNotHaveTypeParameters() {
+      return process("@Component.Builder methods must not have type parameters");
+    }
+
+    final String inheritedMethodsMayNotHaveTypeParameters() {
+      return methodsMayNotHaveTypeParameters() + ". Inherited method: %s";
+    }
+
+    abstract String nonBindsInstanceParametersMayNotBePrimitives();
+
+    final String inheritedNonBindsInstanceParametersMayNotBePrimitives() {
+      return nonBindsInstanceParametersMayNotBePrimitives() + ". Inherited method: %s";
+    }
+
+    final String factoryMethodReturnsSupertypeWithMissingMethods(
+        TypeElement component,
+        TypeElement componentBuilder,
+        TypeMirror returnType,
+        ExecutableElement buildMethod,
+        Set<ExecutableElement> additionalMethods) {
+      return String.format(
+          "%1$s.%2$s() returns %3$s, but %4$s declares additional component method(s): %5$s. In "
+              + "order to provide type-safe access to these methods, override %2$s() to return "
+              + "%4$s",
+          componentBuilder.getQualifiedName(),
+          buildMethod.getSimpleName(),
+          returnType,
+          component.getQualifiedName(),
+          Joiner.on(", ").join(additionalMethods));
+    }
+
+    final String bindsInstanceNotAllowedOnBothSetterMethodAndParameter() {
+      return process("@Component.Builder setter methods may not have @BindsInstance on both the "
+          + "method and its parameter; choose one or the other");
+    }
+
+    final String inheritedBindsInstanceNotAllowedOnBothSetterMethodAndParameter() {
+      return bindsInstanceNotAllowedOnBothSetterMethodAndParameter() + ". Inherited method: %s";
+    }
+  }
+
+  private static final class BuilderMessages extends ComponentCreatorMessages {
+    BuilderMessages(Function<String, String> transformation) {
+      super(transformation);
+    }
+
+    @Override
+    String missingFactoryMethod() {
+      return process(
+          "@Component.Builder types must have exactly one no-args method that "
+              + " returns the @Component type");
+    }
+
+    @Override
+    String multipleSettersForModuleOrDependencyType() {
+      return process(
+          "@Component.Builder types must not have more than one setter method per module or "
+              + "dependency, but %s is set by %s");
+    }
+
+    @Override
+    String extraSetters() {
+      return process(
+          "@Component.Builder has setters for modules or components that aren't required: %s");
+    }
+
+    @Override
+    String missingSetters() {
+      return process(
+          "@Component.Builder is missing setters for required modules or components: %s");
+    }
+
+    @Override
+    String twoFactoryMethods() {
+      return process(
+          "@Component.Builder types must have exactly one zero-arg method, and that"
+              + " method must return the @Component type. Already found: %s");
+    }
+
+    @Override
+    String inheritedTwoFactoryMethods() {
+      return process(
+          "@Component.Builder types must have exactly one zero-arg method, and that"
+              + " method must return the @Component type. Found %s and %s");
+    }
+
+    @Override
+    String factoryMethodMustReturnComponentType() {
+      return process(
+          "@Component.Builder methods that have no arguments must return the @Component type or a "
+              + "supertype of the @Component");
+    }
+
+    @Override
+    String factoryMethodMayNotBeAnnotatedWithBindsInstance() {
+      return process(
+          "@Component.Builder no-arg build methods may not be annotated with @BindsInstance");
+    }
+
+    @Override
+    String nonBindsInstanceParametersMayNotBePrimitives() {
+      return process(
+          "@Component.Builder methods that are not annotated with @BindsInstance "
+              + "must take either a module or a component dependency, not a primitive");
+    }
+  }
+
+  private static final class FactoryMessages extends ComponentCreatorMessages {
+    FactoryMessages(Function<String, String> transformation) {
+      super(transformation.andThen(FACTORY));
+    }
+
+    @Override
+    String missingFactoryMethod() {
+      return process(
+          "@Component.Factory types must have exactly one method that "
+              + "returns the @Component type");
+    }
+
+    @Override
+    String multipleSettersForModuleOrDependencyType() {
+      return process(
+          "@Component.Factory methods must not have more than one parameter per module or "
+              + "dependency, but %s is set by %s");
+    }
+
+    @Override
+    String extraSetters() {
+      return process(
+          "@Component.Factory method has parameters for modules or components that aren't "
+              + "required: %s");
+    }
+
+    @Override
+    String missingSetters() {
+      return process(
+          "@Component.Factory method is missing parameters for required modules or components: %s");
+    }
+
+    @Override
+    String twoFactoryMethods() {
+      return process(
+          "@Component.Factory types must have exactly one abstract method. Already found: %s");
+    }
+
+    @Override
+    String inheritedTwoFactoryMethods() {
+      return twoFactoryMethods();
+    }
+
+    @Override
+    String factoryMethodMustReturnComponentType() {
+      return process(
+          "@Component.Factory abstract methods must return the @Component type or a "
+              + "supertype of the @Component");
+    }
+
+    @Override
+    String factoryMethodMayNotBeAnnotatedWithBindsInstance() {
+      return process("@Component.Factory method may not be annotated with @BindsInstance");
+    }
+
+    @Override
+    String nonBindsInstanceParametersMayNotBePrimitives() {
+      return process(
+          "@Component.Factory method parameters that are not annotated with @BindsInstance "
+              + "must be either a module or a component dependency, not a primitive");
+    }
+  }
+
+  private ErrorMessages() {}
+}
diff --git a/java/dagger/internal/codegen/FactoryGenerator.java b/java/dagger/internal/codegen/FactoryGenerator.java
new file mode 100644
index 0000000..d367bc5
--- /dev/null
+++ b/java/dagger/internal/codegen/FactoryGenerator.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Maps.transformValues;
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.DELEGATE;
+import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
+import static dagger.internal.codegen.GwtCompatibility.gwtIncompatibleAnnotation;
+import static dagger.internal.codegen.SourceFiles.bindingTypeElementTypeVariableNames;
+import static dagger.internal.codegen.SourceFiles.frameworkFieldUsages;
+import static dagger.internal.codegen.SourceFiles.frameworkTypeUsageStatement;
+import static dagger.internal.codegen.SourceFiles.generateBindingFieldsForDependencies;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+import static dagger.internal.codegen.SourceFiles.parameterizedGeneratedTypeNameForBinding;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.factoryOf;
+import static dagger.model.BindingKind.PROVISION;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.Factory;
+import dagger.internal.Preconditions;
+import dagger.internal.codegen.InjectionMethods.InjectionSiteMethod;
+import dagger.internal.codegen.InjectionMethods.ProvisionMethod;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+
+/**
+ * Generates {@link Factory} implementations from {@link ProvisionBinding} instances for
+ * {@link Inject} constructors.
+ */
+final class FactoryGenerator extends SourceFileGenerator<ProvisionBinding> {
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+  private final CompilerOptions compilerOptions;
+
+  @Inject
+  FactoryGenerator(
+      Filer filer,
+      SourceVersion sourceVersion,
+      DaggerTypes types,
+      DaggerElements elements,
+      CompilerOptions compilerOptions) {
+    super(filer, elements, sourceVersion);
+    this.types = types;
+    this.elements = elements;
+    this.compilerOptions = compilerOptions;
+  }
+
+  @Override
+  ClassName nameGeneratedType(ProvisionBinding binding) {
+    return generatedClassNameForBinding(binding);
+  }
+
+  @Override
+  Element originatingElement(ProvisionBinding binding) {
+    // we only create factories for bindings that have a binding element
+    return binding.bindingElement().get();
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, ProvisionBinding binding) {
+    // We don't want to write out resolved bindings -- we want to write out the generic version.
+    checkArgument(!binding.unresolved().isPresent());
+    checkArgument(binding.bindingElement().isPresent());
+
+    return binding.factoryCreationStrategy().equals(DELEGATE)
+        ? Optional.empty()
+        : Optional.of(factoryBuilder(binding));
+  }
+
+  private TypeSpec.Builder factoryBuilder(ProvisionBinding binding) {
+    TypeSpec.Builder factoryBuilder =
+        classBuilder(nameGeneratedType(binding))
+            .addModifiers(PUBLIC, FINAL)
+            .addSuperinterface(factoryTypeName(binding))
+            .addTypeVariables(bindingTypeElementTypeVariableNames(binding));
+
+    addConstructorAndFields(binding, factoryBuilder);
+    factoryBuilder.addMethod(getMethod(binding));
+    addCreateMethod(binding, factoryBuilder);
+
+    factoryBuilder.addMethod(
+        ProvisionMethod.create(binding, compilerOptions, elements).toMethodSpec());
+    gwtIncompatibleAnnotation(binding).ifPresent(factoryBuilder::addAnnotation);
+
+    return factoryBuilder;
+  }
+
+  private void addConstructorAndFields(ProvisionBinding binding, TypeSpec.Builder factoryBuilder) {
+    if (binding.factoryCreationStrategy().equals(SINGLETON_INSTANCE)) {
+      return;
+    }
+    // TODO(user): Make the constructor private?
+    MethodSpec.Builder constructor = constructorBuilder().addModifiers(PUBLIC);
+    constructorParams(binding).forEach(
+        param -> {
+          constructor.addParameter(param).addStatement("this.$1N = $1N", param);
+          factoryBuilder.addField(
+              FieldSpec.builder(param.type, param.name, PRIVATE, FINAL).build());
+        });
+    factoryBuilder.addMethod(constructor.build());
+  }
+
+  private ImmutableList<ParameterSpec> constructorParams(ProvisionBinding binding) {
+    ImmutableList.Builder<ParameterSpec> params = ImmutableList.builder();
+    moduleParameter(binding).ifPresent(params::add);
+    frameworkFields(binding).values().forEach(field -> params.add(toParameter(field)));
+    return params.build();
+  }
+
+  private Optional<ParameterSpec> moduleParameter(ProvisionBinding binding) {
+    if (binding.requiresModuleInstance()) {
+      // TODO(user, dpb): Should this use contributingModule()?
+      TypeName type = TypeName.get(binding.bindingTypeElement().get().asType());
+      return Optional.of(ParameterSpec.builder(type, "module").build());
+    }
+    return Optional.empty();
+  }
+
+  private ImmutableMap<Key, FieldSpec> frameworkFields(ProvisionBinding binding) {
+    UniqueNameSet uniqueFieldNames = new UniqueNameSet();
+    // TODO(user, dpb): Add a test for the case when a Factory parameter is named "module".
+    if (binding.requiresModuleInstance()) {
+      uniqueFieldNames.claim("module");
+    }
+    return ImmutableMap.copyOf(
+        transformValues(
+            generateBindingFieldsForDependencies(binding),
+            field ->
+                FieldSpec.builder(
+                        field.type(), uniqueFieldNames.getUniqueName(field.name()), PRIVATE, FINAL)
+                    .build()));
+  }
+
+  private void addCreateMethod(ProvisionBinding binding, TypeSpec.Builder factoryBuilder) {
+    // If constructing a factory for @Inject or @Provides bindings, we use a static create method
+    // so that generated components can avoid having to refer to the generic types
+    // of the factory.  (Otherwise they may have visibility problems referring to the types.)
+    MethodSpec.Builder createMethodBuilder =
+        methodBuilder("create")
+            .addModifiers(PUBLIC, STATIC)
+            .returns(parameterizedGeneratedTypeNameForBinding(binding))
+            .addTypeVariables(bindingTypeElementTypeVariableNames(binding));
+
+    switch (binding.factoryCreationStrategy()) {
+      case SINGLETON_INSTANCE:
+        FieldSpec.Builder instanceFieldBuilder =
+            FieldSpec.builder(nameGeneratedType(binding), "INSTANCE", PRIVATE, STATIC, FINAL)
+                .initializer("new $T()", nameGeneratedType(binding));
+
+        if (!bindingTypeElementTypeVariableNames(binding).isEmpty()) {
+          // If the factory has type parameters, ignore them in the field declaration & initializer
+          instanceFieldBuilder.addAnnotation(suppressWarnings(RAWTYPES));
+
+          createMethodBuilder.addAnnotation(suppressWarnings(UNCHECKED));
+        }
+        createMethodBuilder.addStatement("return INSTANCE");
+        factoryBuilder.addField(instanceFieldBuilder.build());
+        break;
+      case CLASS_CONSTRUCTOR:
+        List<ParameterSpec> params = constructorParams(binding);
+        createMethodBuilder.addParameters(params);
+        createMethodBuilder.addStatement(
+            "return new $T($L)",
+            parameterizedGeneratedTypeNameForBinding(binding),
+            makeParametersCodeBlock(Lists.transform(params, input -> CodeBlock.of("$N", input))));
+        break;
+      default:
+        throw new AssertionError();
+    }
+    factoryBuilder.addMethod(createMethodBuilder.build());
+  }
+
+  private MethodSpec getMethod(ProvisionBinding binding) {
+    TypeName providedTypeName = providedTypeName(binding);
+    MethodSpec.Builder getMethod =
+        methodBuilder("get")
+            .addAnnotation(Override.class)
+            .addModifiers(PUBLIC)
+            .returns(providedTypeName);
+
+    ImmutableMap<Key, FieldSpec> frameworkFields = frameworkFields(binding);
+    CodeBlock parametersCodeBlock =
+        makeParametersCodeBlock(
+            frameworkFieldUsages(binding.provisionDependencies(), frameworkFields).values());
+
+    if (binding.kind().equals(PROVISION)) {
+      binding
+          .nullableType()
+          .ifPresent(nullableType -> CodeBlocks.addAnnotation(getMethod, nullableType));
+      getMethod.addStatement(
+          "return $L",
+          ProvisionMethod.invoke(
+              binding,
+              request ->
+                  frameworkTypeUsageStatement(
+                      CodeBlock.of("$N", frameworkFields.get(request.key())), request.kind()),
+              nameGeneratedType(binding),
+              binding.requiresModuleInstance()
+                  ? Optional.of(CodeBlock.of("module"))
+                  : Optional.empty(),
+              compilerOptions,
+              elements));
+    } else if (!binding.injectionSites().isEmpty()) {
+      CodeBlock instance = CodeBlock.of("instance");
+      getMethod
+          .addStatement("$1T $2L = new $1T($3L)", providedTypeName, instance, parametersCodeBlock)
+          .addCode(
+              InjectionSiteMethod.invokeAll(
+                  binding.injectionSites(),
+                  nameGeneratedType(binding),
+                  instance,
+                  binding.key().type(),
+                  types,
+                  frameworkFieldUsages(binding.dependencies(), frameworkFields)::get,
+                  elements))
+          .addStatement("return $L", instance);
+    } else {
+      getMethod.addStatement(
+          "return new $T($L)", providedTypeName, parametersCodeBlock);
+    }
+    return getMethod.build();
+  }
+
+  private static TypeName providedTypeName(ProvisionBinding binding) {
+    return TypeName.get(binding.contributedType());
+  }
+
+  private static TypeName factoryTypeName(ProvisionBinding binding) {
+    return factoryOf(providedTypeName(binding));
+  }
+
+  private static ParameterSpec toParameter(FieldSpec field) {
+    return ParameterSpec.builder(field.type, field.name).build();
+  }
+
+  /**
+   * Returns {@code Preconditions.checkNotNull(providesMethodInvocation)} with a message suitable
+   * for {@code @Provides} methods.
+   */
+  static CodeBlock checkNotNullProvidesMethod(CodeBlock providesMethodInvocation) {
+    return CodeBlock.of(
+        "$T.checkNotNull($L, $S)",
+        Preconditions.class,
+        providesMethodInvocation,
+        "Cannot return null from a non-@Nullable @Provides method");
+  }
+}
diff --git a/java/dagger/internal/codegen/FeatureStatus.java b/java/dagger/internal/codegen/FeatureStatus.java
new file mode 100644
index 0000000..9ff254e
--- /dev/null
+++ b/java/dagger/internal/codegen/FeatureStatus.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 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;
+
+/** Allows options to control how features in component processing are enabled. */
+enum FeatureStatus {
+  ENABLED,
+  DISABLED;
+}
diff --git a/java/dagger/internal/codegen/Formatter.java b/java/dagger/internal/codegen/Formatter.java
new file mode 100644
index 0000000..53d4f9a
--- /dev/null
+++ b/java/dagger/internal/codegen/Formatter.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkElementIndex;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+
+/**
+ * A formatter which transforms an instance of a particular type into a string
+ * representation.
+ *
+ * @param <T> the type of the object to be transformed.
+ */
+abstract class Formatter<T> implements Function<T, String> {
+
+  static final String INDENT = "    ";
+  static final String DOUBLE_INDENT = INDENT + INDENT;
+  private static final int LIST_LIMIT = 10;
+
+  /**
+   * Performs the transformation of an object into a string representation.
+   */
+  public abstract String format(T object);
+
+  /**
+   * Performs the transformation of an object into a string representation in conformity with the
+   * {@link Function}{@code <T, String>} contract, delegating to {@link #format(Object)}.
+   *
+   * @deprecated Call {@link #format(Object)} instead. This method exists to make formatters easy to
+   *     use when functions are required, but shouldn't be called directly.
+   */
+  @SuppressWarnings("javadoc")
+  @Deprecated
+  @Override
+  public final String apply(T object) {
+    return format(object);
+  }
+
+  /** Formats {@code items}, one per line. Stops after {@value #LIST_LIMIT} items. */
+  public void formatIndentedList(
+      StringBuilder builder, Iterable<? extends T> items, int indentLevel) {
+    for (T item : Iterables.limit(items, LIST_LIMIT)) {
+      String formatted = format(item);
+      if (formatted.isEmpty()) {
+        continue;
+      }
+      builder.append('\n');
+      appendIndent(builder, indentLevel);
+      builder.append(formatted);
+    }
+    int numberOfOtherItems = Iterables.size(items) - LIST_LIMIT;
+    if (numberOfOtherItems > 0) {
+      builder.append('\n');
+      appendIndent(builder, indentLevel);
+      builder.append("and ").append(numberOfOtherItems).append(" other");
+    }
+    if (numberOfOtherItems > 1) {
+      builder.append('s');
+    }
+  }
+
+  private void appendIndent(StringBuilder builder, int indentLevel) {
+    for (int i = 0; i < indentLevel; i++) {
+      builder.append(INDENT);
+    }
+  }
+
+  static String formatArgumentInList(int index, int size, CharSequence name) {
+    checkElementIndex(index, size);
+    StringBuilder builder = new StringBuilder();
+    if (index > 0) {
+      builder.append("…, ");
+    }
+    builder.append(name);
+    if (index < size - 1) {
+      builder.append(", …");
+    }
+    return builder.toString();
+  }
+}
diff --git a/java/dagger/internal/codegen/ForwardingCompilerOptions.java b/java/dagger/internal/codegen/ForwardingCompilerOptions.java
new file mode 100644
index 0000000..4a1deda
--- /dev/null
+++ b/java/dagger/internal/codegen/ForwardingCompilerOptions.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 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.common.base.Preconditions.checkNotNull;
+
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+/** A {@link CompilerOptions} object that delegates to another one. */
+class ForwardingCompilerOptions extends CompilerOptions {
+
+  private final CompilerOptions delegate;
+
+  ForwardingCompilerOptions(CompilerOptions delegate) {
+    this.delegate = checkNotNull(delegate);
+  }
+
+  @Override
+  boolean usesProducers() {
+    return delegate.usesProducers();
+  }
+
+  @Override
+  boolean fastInit() {
+    return delegate.fastInit();
+  }
+
+  @Override
+  boolean formatGeneratedSource() {
+    return delegate.formatGeneratedSource();
+  }
+
+  @Override
+  boolean writeProducerNameInToken() {
+    return delegate.writeProducerNameInToken();
+  }
+
+  @Override
+  Diagnostic.Kind nullableValidationKind() {
+    return delegate.nullableValidationKind();
+  }
+
+  @Override
+  Diagnostic.Kind privateMemberValidationKind() {
+    return delegate.privateMemberValidationKind();
+  }
+
+  @Override
+  Diagnostic.Kind staticMemberValidationKind() {
+    return delegate.staticMemberValidationKind();
+  }
+
+  @Override
+  boolean ignorePrivateAndStaticInjectionForComponent() {
+    return delegate.ignorePrivateAndStaticInjectionForComponent();
+  }
+
+  @Override
+  ValidationType scopeCycleValidationType() {
+    return delegate.scopeCycleValidationType();
+  }
+
+  @Override
+  boolean warnIfInjectionFactoryNotGeneratedUpstream() {
+    return delegate.warnIfInjectionFactoryNotGeneratedUpstream();
+  }
+
+  @Override
+  boolean headerCompilation() {
+    return delegate.headerCompilation();
+  }
+
+  @Override
+  boolean aheadOfTimeSubcomponents() {
+    return delegate.aheadOfTimeSubcomponents();
+  }
+
+  @Override
+  boolean forceUseSerializedComponentImplementations() {
+    return delegate.forceUseSerializedComponentImplementations();
+  }
+
+  @Override
+  boolean emitModifiableMetadataAnnotations() {
+    return delegate.emitModifiableMetadataAnnotations();
+  }
+
+  @Override
+  boolean useGradleIncrementalProcessing() {
+    return delegate.useGradleIncrementalProcessing();
+  }
+
+  @Override
+  ValidationType fullBindingGraphValidationType(TypeElement element) {
+    return delegate.fullBindingGraphValidationType(element);
+  }
+
+  @Override
+  Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind() {
+    return delegate.moduleHasDifferentScopesDiagnosticKind();
+  }
+
+  @Override
+  ValidationType explicitBindingConflictsWithInjectValidationType() {
+    return delegate.explicitBindingConflictsWithInjectValidationType();
+  }
+}
diff --git a/java/dagger/internal/codegen/FrameworkDependency.java b/java/dagger/internal/codegen/FrameworkDependency.java
new file mode 100644
index 0000000..feea7a0
--- /dev/null
+++ b/java/dagger/internal/codegen/FrameworkDependency.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 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 dagger.model.Key;
+
+/**
+ * The framework class and binding key for a resolved dependency of a binding. If a binding has
+ * several dependencies for a key, then only one instance of this class will represent them all.
+ *
+ * <p>In the following example, the binding {@code provideFoo()} has two dependency requests:
+ *
+ * <ol>
+ *   <li>{@code Bar bar}
+ *   <li>{@code Provider<Bar> barProvider}
+ * </ol>
+ *
+ * But they both can be satisfied with the same instance of {@code Provider<Bar>}. So one instance
+ * of {@code FrameworkDependency} will be used for both. Its {@link #key()} will be for {@code Bar},
+ * and its {@link #frameworkType()} will be {@link FrameworkType#PROVIDER}.
+ *
+ * <pre><code>
+ *   {@literal @Provides} static Foo provideFoo(Bar bar, {@literal Provider<Bar>} barProvider) {
+ *     return new Foo(…);
+ *   }
+ * </code></pre>
+ */
+@AutoValue
+abstract class FrameworkDependency {
+
+  /** The fully-resolved key shared by all the dependency requests. */
+  abstract Key key();
+
+  /** The type of the framework dependency. */
+  abstract FrameworkType frameworkType();
+
+  /** The framework class to use for this dependency. */
+  final Class<?> frameworkClass() {
+    return frameworkType().frameworkClass();
+  }
+
+  /** Returns a new instance with the given key and type. */
+  static FrameworkDependency create(Key key, FrameworkType frameworkType) {
+    return new AutoValue_FrameworkDependency(key, frameworkType);
+  }
+}
diff --git a/java/dagger/internal/codegen/FrameworkField.java b/java/dagger/internal/codegen/FrameworkField.java
new file mode 100644
index 0000000..de2ada0
--- /dev/null
+++ b/java/dagger/internal/codegen/FrameworkField.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2014 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 dagger.model.BindingKind.MEMBERS_INJECTOR;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.CaseFormat;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import java.util.Optional;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementKindVisitor8;
+
+/**
+ * A value object that represents a field in the generated Component class.
+ *
+ * <p>Examples:
+ * <ul>
+ *   <li>{@code Provider<String>}
+ *   <li>{@code Producer<Widget>}
+ *   <li>{@code Provider<Map<SomeMapKey, MapValue>>}.
+ * </ul>
+ */
+@AutoValue
+abstract class FrameworkField {
+
+  /**
+   * Creates a framework field.
+   * 
+   * @param frameworkClassName the name of the framework class (e.g., {@link javax.inject.Provider})
+   * @param valueTypeName the name of the type parameter of the framework class (e.g., {@code Foo}
+   *     for {@code Provider<Foo>}
+   * @param fieldName the name of the field
+   */
+  static FrameworkField create(
+      ClassName frameworkClassName, TypeName valueTypeName, String fieldName) {
+    String suffix = frameworkClassName.simpleName();
+    return new AutoValue_FrameworkField(
+        ParameterizedTypeName.get(frameworkClassName, valueTypeName),
+        fieldName.endsWith(suffix) ? fieldName : fieldName + suffix);
+  }
+
+  /**
+   * A framework field for a {@link ResolvedBindings}.
+   * 
+   * @param frameworkClass if present, the field will use this framework class instead of the normal
+   *     one for the bindings
+   */
+  static FrameworkField forResolvedBindings(
+      ResolvedBindings resolvedBindings, Optional<ClassName> frameworkClass) {
+    return create(
+        frameworkClass.orElse(
+            ClassName.get(
+                FrameworkType.forBindingType(resolvedBindings.bindingType()).frameworkClass())),
+        TypeName.get(fieldValueType(resolvedBindings)),
+        frameworkFieldName(resolvedBindings));
+  }
+
+  private static TypeMirror fieldValueType(ResolvedBindings resolvedBindings) {
+    return resolvedBindings.isMultibindingContribution()
+        ? resolvedBindings.contributionBinding().contributedType()
+        : resolvedBindings.key().type();
+  }
+
+  private static String frameworkFieldName(ResolvedBindings resolvedBindings) {
+    if (!resolvedBindings.contributionBindings().isEmpty()) {
+      ContributionBinding binding = resolvedBindings.contributionBinding();
+      if (binding.bindingElement().isPresent()) {
+        String name = BINDING_ELEMENT_NAME.visit(binding.bindingElement().get(), binding);
+        return binding.kind().equals(MEMBERS_INJECTOR)
+            ? name + "MembersInjector"
+            : name;
+      }
+    }
+    return KeyVariableNamer.name(resolvedBindings.key());
+  }
+
+  private static final ElementVisitor<String, Binding> BINDING_ELEMENT_NAME =
+      new ElementKindVisitor8<String, Binding>() {
+
+        @Override
+        protected String defaultAction(Element e, Binding p) {
+          throw new IllegalArgumentException("Unexpected binding " + p);
+        }
+
+        @Override
+        public String visitExecutableAsConstructor(ExecutableElement e, Binding p) {
+          return visit(e.getEnclosingElement(), p);
+        }
+
+        @Override
+        public String visitExecutableAsMethod(ExecutableElement e, Binding p) {
+          return e.getSimpleName().toString();
+        }
+
+        @Override
+        public String visitType(TypeElement e, Binding p) {
+          return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, e.getSimpleName().toString());
+        }
+
+        @Override
+        public String visitVariableAsParameter(VariableElement e, Binding p) {
+          return e.getSimpleName().toString();
+        }
+      };
+
+  abstract ParameterizedTypeName type();
+  abstract String name();
+}
diff --git a/java/dagger/internal/codegen/FrameworkFieldInitializer.java b/java/dagger/internal/codegen/FrameworkFieldInitializer.java
new file mode 100644
index 0000000..a3de083
--- /dev/null
+++ b/java/dagger/internal/codegen/FrameworkFieldInitializer.java
@@ -0,0 +1,217 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.ComponentImplementation.FieldSpecKind.FRAMEWORK_FIELD;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.DelegateFactory;
+import dagger.internal.codegen.javapoet.AnnotationSpecs;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.producers.internal.DelegateProducer;
+import java.util.Optional;
+
+/**
+ * An object that can initialize a framework-type component field for a binding. An instance should
+ * be created for each field.
+ */
+class FrameworkFieldInitializer implements FrameworkInstanceSupplier {
+
+  /**
+   * An object that can determine the expression to use to assign to the component field for a
+   * binding.
+   */
+  interface FrameworkInstanceCreationExpression {
+    /** Returns the expression to use to assign to the component field for the binding. */
+    CodeBlock creationExpression();
+
+    /**
+     * Returns the framework class to use for the field, if different from the one implied by the
+     * binding. This implementation returns {@link Optional#empty()}.
+     */
+    default Optional<ClassName> alternativeFrameworkClass() {
+      return Optional.empty();
+    }
+
+    /**
+     * Returns {@code true} if instead of using {@link #creationExpression()} to create a framework
+     * instance, a case in {@link InnerSwitchingProviders} should be created for this binding.
+     */
+    // TODO(ronshapiro): perhaps this isn't the right approach. Instead of saying "Use
+    // SetFactory.EMPTY because you will only get 1 class for all types of bindings that use
+    // SetFactory", maybe we should still use an inner switching provider but the same switching
+    // provider index for all cases.
+    default boolean useInnerSwitchingProvider() {
+      return true;
+    }
+  }
+
+  private final ComponentImplementation componentImplementation;
+  private final ResolvedBindings resolvedBindings;
+  private final FrameworkInstanceCreationExpression frameworkInstanceCreationExpression;
+  private FieldSpec fieldSpec;
+  private InitializationState fieldInitializationState = InitializationState.UNINITIALIZED;
+
+  FrameworkFieldInitializer(
+      ComponentImplementation componentImplementation,
+      ResolvedBindings resolvedBindings,
+      FrameworkInstanceCreationExpression frameworkInstanceCreationExpression) {
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.resolvedBindings = checkNotNull(resolvedBindings);
+    this.frameworkInstanceCreationExpression = checkNotNull(frameworkInstanceCreationExpression);
+  }
+
+  /**
+   * Returns the {@link MemberSelect} for the framework field, and adds the field and its
+   * initialization code to the component if it's needed and not already added.
+   */
+  @Override
+  public final MemberSelect memberSelect() {
+    initializeField();
+    return MemberSelect.localField(componentImplementation.name(), checkNotNull(fieldSpec).name);
+  }
+
+  /** Adds the field and its initialization code to the component. */
+  private void initializeField() {
+    switch (fieldInitializationState) {
+      case UNINITIALIZED:
+        // Change our state in case we are recursively invoked via initializeBindingExpression
+        fieldInitializationState = InitializationState.INITIALIZING;
+        CodeBlock.Builder codeBuilder = CodeBlock.builder();
+        CodeBlock fieldInitialization = frameworkInstanceCreationExpression.creationExpression();
+        CodeBlock initCode = CodeBlock.of("this.$N = $L;", getOrCreateField(), fieldInitialization);
+
+        if (isReplacingSuperclassFrameworkInstance()
+            || fieldInitializationState == InitializationState.DELEGATED) {
+          codeBuilder.add(
+              "$T.setDelegate($N, $L);", delegateType(), fieldSpec, fieldInitialization);
+        } else {
+          codeBuilder.add(initCode);
+        }
+        componentImplementation.addInitialization(codeBuilder.build());
+
+        fieldInitializationState = InitializationState.INITIALIZED;
+        break;
+
+      case INITIALIZING:
+        // We were recursively invoked, so create a delegate factory instead
+        fieldInitializationState = InitializationState.DELEGATED;
+        componentImplementation.addInitialization(
+            CodeBlock.of("this.$N = new $T<>();", getOrCreateField(), delegateType()));
+        break;
+
+      case DELEGATED:
+      case INITIALIZED:
+        break;
+    }
+  }
+
+  /**
+   * Adds a field representing the resolved bindings, optionally forcing it to use a particular
+   * binding type (instead of the type the resolved bindings would typically use).
+   */
+  private FieldSpec getOrCreateField() {
+    if (fieldSpec != null) {
+      return fieldSpec;
+    }
+    boolean useRawType = !componentImplementation.isTypeAccessible(resolvedBindings.key().type());
+    FrameworkField contributionBindingField =
+        FrameworkField.forResolvedBindings(
+            resolvedBindings, frameworkInstanceCreationExpression.alternativeFrameworkClass());
+
+    TypeName fieldType =
+        useRawType ? contributionBindingField.type().rawType : contributionBindingField.type();
+
+    FieldSpec.Builder contributionField =
+        FieldSpec.builder(
+            fieldType, componentImplementation.getUniqueFieldName(contributionBindingField.name()));
+    contributionField.addModifiers(PRIVATE);
+    if (useRawType) {
+      contributionField.addAnnotation(AnnotationSpecs.suppressWarnings(RAWTYPES));
+    }
+
+    if (isReplacingSuperclassFrameworkInstance()) {
+      // If a binding is modified in a subclass, the framework instance will be replaced in the
+      // subclass implementation. The superclass framework instance initialization will run first,
+      // however, and may refer to the modifiable binding method returning this type's modified
+      // framework instance before it is initialized, so we use a delegate factory as a placeholder
+      // until it has properly been initialized.
+      contributionField.initializer("new $T<>()", delegateType());
+    }
+
+    fieldSpec = contributionField.build();
+    componentImplementation.addField(FRAMEWORK_FIELD, fieldSpec);
+
+    return fieldSpec;
+  }
+
+  /**
+   * Returns true if this framework field is replacing a superclass's implementation of the
+   * framework field.
+   */
+  private boolean isReplacingSuperclassFrameworkInstance() {
+    return componentImplementation
+        .superclassImplementation()
+        .flatMap(
+            superclassImplementation ->
+                // TODO(b/117833324): can we constrain this further?
+                superclassImplementation.getModifiableBindingMethod(
+                    BindingRequest.bindingRequest(
+                        resolvedBindings.key(),
+                        isProvider() ? FrameworkType.PROVIDER : FrameworkType.PRODUCER_NODE)))
+        .isPresent();
+  }
+
+  private Class<?> delegateType() {
+    return isProvider() ? DelegateFactory.class : DelegateProducer.class;
+  }
+
+  private boolean isProvider() {
+    return resolvedBindings.bindingType().equals(BindingType.PROVISION)
+        && frameworkInstanceCreationExpression
+            .alternativeFrameworkClass()
+            .map(TypeNames.PROVIDER::equals)
+            .orElse(true);
+  }
+
+  /** Initialization state for a factory field. */
+  private enum InitializationState {
+    /** The field is {@code null}. */
+    UNINITIALIZED,
+
+    /**
+     * The field's dependencies are being set up. If the field is needed in this state, use a {@link
+     * DelegateFactory}.
+     */
+    INITIALIZING,
+
+    /**
+     * The field's dependencies are being set up, but the field can be used because it has already
+     * been set to a {@link DelegateFactory}.
+     */
+    DELEGATED,
+
+    /** The field is set to an undelegated factory. */
+    INITIALIZED;
+  }
+}
diff --git a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
new file mode 100644
index 0000000..6f62d66
--- /dev/null
+++ b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/** A binding expression that uses a {@link FrameworkType} field. */
+abstract class FrameworkInstanceBindingExpression extends BindingExpression {
+  private final ResolvedBindings resolvedBindings;
+  private final FrameworkInstanceSupplier frameworkInstanceSupplier;
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+
+  FrameworkInstanceBindingExpression(
+      ResolvedBindings resolvedBindings,
+      FrameworkInstanceSupplier frameworkInstanceSupplier,
+      DaggerTypes types,
+      DaggerElements elements) {
+    this.resolvedBindings = checkNotNull(resolvedBindings);
+    this.frameworkInstanceSupplier = checkNotNull(frameworkInstanceSupplier);
+    this.types = checkNotNull(types);
+    this.elements = checkNotNull(elements);
+  }
+
+  /**
+   * The expression for the framework instance for this binding. The field will be {@link
+   * ComponentImplementation#addInitialization(CodeBlock) initialized} and {@link
+   * ComponentImplementation#addField(ComponentImplementation.FieldSpecKind, FieldSpec) added} to
+   * the component the first time this method is invoked.
+   */
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    MemberSelect memberSelect = frameworkInstanceSupplier.memberSelect();
+    TypeMirror contributedType = resolvedBindings.contributionBinding().contributedType();
+    TypeMirror expressionType =
+        isTypeAccessibleFrom(contributedType, requestingClass.packageName())
+                || isInlinedFactoryCreation(memberSelect)
+            ? types.wrapType(contributedType, frameworkType().frameworkClass())
+            : rawFrameworkType();
+    return Expression.create(expressionType, memberSelect.getExpressionFor(requestingClass));
+  }
+
+  /** Returns the framework type for the binding. */
+  protected abstract FrameworkType frameworkType();
+
+  /**
+   * Returns {@code true} if a factory is created inline each time it is requested. For example, in
+   * the initialization {@code this.fooProvider = Foo_Factory.create(Bar_Factory.create());}, {@code
+   * Bar_Factory} is considered to be inline.
+   *
+   * <p>This is used in {@link #getDependencyExpression(ClassName)} when determining the type of a
+   * factory. Normally if the {@link ContributionBinding#contributedType()} is not accessible from
+   * the component, the type of the expression will be a raw {@link javax.inject.Provider}. However,
+   * if the factory is created inline, even if contributed type is not accessible, javac will still
+   * be able to determine the type that is returned from the {@code Foo_Factory.create()} method.
+   */
+  private static boolean isInlinedFactoryCreation(MemberSelect memberSelect) {
+    return memberSelect.staticMember();
+  }
+
+  private DeclaredType rawFrameworkType() {
+    return types.getDeclaredType(elements.getTypeElement(frameworkType().frameworkClass()));
+  }
+}
diff --git a/java/dagger/internal/codegen/FrameworkInstanceSupplier.java b/java/dagger/internal/codegen/FrameworkInstanceSupplier.java
new file mode 100644
index 0000000..4c45630
--- /dev/null
+++ b/java/dagger/internal/codegen/FrameworkInstanceSupplier.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 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;
+
+/** An object that supplies a {@link MemberSelect} for a framework instance. */
+interface FrameworkInstanceSupplier {
+  /** Returns a {@link MemberSelect}, with possible side effects on the first call. */
+  MemberSelect memberSelect();
+}
diff --git a/java/dagger/internal/codegen/FrameworkType.java b/java/dagger/internal/codegen/FrameworkType.java
new file mode 100644
index 0000000..f4e3779
--- /dev/null
+++ b/java/dagger/internal/codegen/FrameworkType.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2016 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.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static dagger.model.RequestKind.INSTANCE;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import dagger.Lazy;
+import dagger.internal.DoubleCheck;
+import dagger.internal.ProviderOfLazy;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import dagger.model.RequestKind;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import dagger.producers.internal.Producers;
+import java.util.Optional;
+import javax.inject.Provider;
+import javax.lang.model.type.TypeMirror;
+
+/** One of the core types initialized as fields in a generated component. */
+enum FrameworkType {
+  /** A {@link Provider}. */
+  PROVIDER {
+    @Override
+    Class<?> frameworkClass() {
+      return Provider.class;
+    }
+
+    @Override
+    Optional<RequestKind> requestKind() {
+      return Optional.of(RequestKind.PROVIDER);
+    }
+
+    @Override
+    CodeBlock to(RequestKind requestKind, CodeBlock from) {
+      switch (requestKind) {
+        case INSTANCE:
+          return CodeBlock.of("$L.get()", from);
+
+        case LAZY:
+          return CodeBlock.of("$T.lazy($L)", DoubleCheck.class, from);
+
+        case PROVIDER:
+          return from;
+
+        case PROVIDER_OF_LAZY:
+          return CodeBlock.of("$T.create($L)", ProviderOfLazy.class, from);
+
+        case PRODUCER:
+          return CodeBlock.of("$T.producerFromProvider($L)", Producers.class, from);
+
+        case FUTURE:
+          return CodeBlock.of("$T.immediateFuture($L)", Futures.class, to(INSTANCE, from));
+
+        case PRODUCED:
+          return CodeBlock.of("$T.successful($L)", Produced.class, to(INSTANCE, from));
+
+        default:
+          throw new IllegalArgumentException(
+              String.format("Cannot request a %s from a %s", requestKind, this));
+      }
+    }
+
+    @Override
+    Expression to(RequestKind requestKind, Expression from, DaggerTypes types) {
+      CodeBlock codeBlock = to(requestKind, from.codeBlock());
+      switch (requestKind) {
+        case INSTANCE:
+          return Expression.create(types.unwrapTypeOrObject(from.type()), codeBlock);
+
+        case PROVIDER:
+          return from;
+
+        case PROVIDER_OF_LAZY:
+          TypeMirror lazyType = types.rewrapType(from.type(), Lazy.class);
+          return Expression.create(types.wrapType(lazyType, Provider.class), codeBlock);
+
+        case FUTURE:
+          return Expression.create(
+              types.rewrapType(from.type(), ListenableFuture.class), codeBlock);
+
+        default:
+          return Expression.create(
+              types.rewrapType(from.type(), RequestKinds.frameworkClass(requestKind)), codeBlock);
+      }
+    }
+  },
+
+  /** A {@link Producer}. */
+  PRODUCER_NODE {
+    @Override
+    Class<?> frameworkClass() {
+      // TODO(cgdecker): Replace this with new class for representing internal producer nodes.
+      // Currently the new class is CancellableProducer, but it may be changed to ProducerNode and
+      // made to not implement Producer.
+      return Producer.class;
+    }
+
+    @Override
+    Optional<RequestKind> requestKind() {
+      return Optional.empty();
+    }
+
+    @Override
+    CodeBlock to(RequestKind requestKind, CodeBlock from) {
+      switch (requestKind) {
+        case FUTURE:
+          return CodeBlock.of("$L.get()", from);
+
+        case PRODUCER:
+          return from;
+
+        default:
+          throw new IllegalArgumentException(
+              String.format("Cannot request a %s from a %s", requestKind, this));
+      }
+    }
+
+    @Override
+    Expression to(RequestKind requestKind, Expression from, DaggerTypes types) {
+      switch (requestKind) {
+        case FUTURE:
+          return Expression.create(
+              types.rewrapType(from.type(), ListenableFuture.class),
+              to(requestKind, from.codeBlock()));
+
+        case PRODUCER:
+          return Expression.create(from.type(), to(requestKind, from.codeBlock()));
+
+        default:
+          throw new IllegalArgumentException(
+              String.format("Cannot request a %s from a %s", requestKind, this));
+      }
+    }
+  },
+  ;
+
+  /** Returns the framework type appropriate for fields for a given binding type. */
+  static FrameworkType forBindingType(BindingType bindingType) {
+    switch (bindingType) {
+      case PROVISION:
+        return PROVIDER;
+      case PRODUCTION:
+        return PRODUCER_NODE;
+      case MEMBERS_INJECTION:
+    }
+    throw new AssertionError(bindingType);
+  }
+
+  /** Returns the framework type that exactly matches the given request kind, if one exists. */
+  static Optional<FrameworkType> forRequestKind(RequestKind requestKind) {
+    switch (requestKind) {
+      case PROVIDER:
+        return Optional.of(FrameworkType.PROVIDER);
+      default:
+        return Optional.empty();
+    }
+  }
+
+  /** The class of fields of this type. */
+  abstract Class<?> frameworkClass();
+
+  /** Returns the {@link #frameworkClass()} parameterized with a type. */
+  ParameterizedTypeName frameworkClassOf(TypeName valueType) {
+    return ParameterizedTypeName.get(ClassName.get(frameworkClass()), valueType);
+  }
+
+  /** The request kind that an instance of this framework type can satisfy directly, if any. */
+  abstract Optional<RequestKind> requestKind();
+
+  /**
+   * Returns a {@link CodeBlock} that evaluates to a requested object given an expression that
+   * evaluates to an instance of this framework type.
+   *
+   * @param requestKind the kind of {@link DependencyRequest} that the returned expression can
+   *     satisfy
+   * @param from a {@link CodeBlock} that evaluates to an instance of this framework type
+   * @throws IllegalArgumentException if a valid expression cannot be generated for {@code
+   *     requestKind}
+   */
+  abstract CodeBlock to(RequestKind requestKind, CodeBlock from);
+
+  /**
+   * Returns an {@link Expression} that evaluates to a requested object given an expression that
+   * evaluates to an instance of this framework type.
+   *
+   * @param requestKind the kind of {@link DependencyRequest} that the returned expression can
+   *     satisfy
+   * @param from an expression that evaluates to an instance of this framework type
+   * @throws IllegalArgumentException if a valid expression cannot be generated for {@code
+   *     requestKind}
+   */
+  abstract Expression to(RequestKind requestKind, Expression from, DaggerTypes types);
+
+  @Override
+  public String toString() {
+    return UPPER_UNDERSCORE.to(UPPER_CAMEL, super.toString());
+  }
+}
diff --git a/java/dagger/internal/codegen/FrameworkTypeMapper.java b/java/dagger/internal/codegen/FrameworkTypeMapper.java
new file mode 100644
index 0000000..7746692
--- /dev/null
+++ b/java/dagger/internal/codegen/FrameworkTypeMapper.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 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.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingType.PRODUCTION;
+import static java.util.stream.Collectors.toSet;
+
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import dagger.producers.Producer;
+import java.util.Set;
+import javax.inject.Provider;
+
+/**
+ * A mapper for associating a {@link RequestKind} to a {@link FrameworkType}, dependent on the type
+ * of code to be generated (e.g., for {@link Provider} or {@link Producer}).
+ */
+enum FrameworkTypeMapper {
+  FOR_PROVIDER() {
+    @Override
+    public FrameworkType getFrameworkType(RequestKind requestKind) {
+      switch (requestKind) {
+        case INSTANCE:
+        case PROVIDER:
+        case PROVIDER_OF_LAZY:
+        case LAZY:
+          return FrameworkType.PROVIDER;
+        case PRODUCED:
+        case PRODUCER:
+          throw new IllegalArgumentException(requestKind.toString());
+        default:
+          throw new AssertionError(requestKind);
+      }
+    }
+  },
+  FOR_PRODUCER() {
+    @Override
+    public FrameworkType getFrameworkType(RequestKind requestKind) {
+      switch (requestKind) {
+        case INSTANCE:
+        case PRODUCED:
+        case PRODUCER:
+          return FrameworkType.PRODUCER_NODE;
+        case PROVIDER:
+        case PROVIDER_OF_LAZY:
+        case LAZY:
+          return FrameworkType.PROVIDER;
+        default:
+          throw new AssertionError(requestKind);
+      }
+    }
+  };
+
+  static FrameworkTypeMapper forBindingType(BindingType bindingType) {
+    return bindingType.equals(PRODUCTION) ? FOR_PRODUCER : FOR_PROVIDER;
+  }
+
+  abstract FrameworkType getFrameworkType(RequestKind requestKind);
+
+  /**
+   * Returns the {@link FrameworkType} to use for a collection of requests of the same {@link Key}.
+   * This allows factories to only take a single argument for multiple requests of the same key.
+   */
+  FrameworkType getFrameworkType(Set<DependencyRequest> requests) {
+    Set<FrameworkType> frameworkTypes =
+        requests.stream().map(request -> getFrameworkType(request.kind())).collect(toSet());
+    return frameworkTypes.size() == 1 ? getOnlyElement(frameworkTypes) : FrameworkType.PROVIDER;
+  }
+}
diff --git a/java/dagger/internal/codegen/FrameworkTypes.java b/java/dagger/internal/codegen/FrameworkTypes.java
new file mode 100644
index 0000000..19d2eda
--- /dev/null
+++ b/java/dagger/internal/codegen/FrameworkTypes.java
@@ -0,0 +1,66 @@
+/*
+ * 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.isType;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import dagger.Lazy;
+import dagger.MembersInjector;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import java.util.Set;
+import javax.inject.Provider;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A collection of utility methods for dealing with Dagger framework types. A framework type is any
+ * type that the framework itself defines.
+ */
+final class FrameworkTypes {
+  private static final ImmutableSet<Class<?>> PROVISION_TYPES =
+      ImmutableSet.of(Provider.class, Lazy.class, MembersInjector.class);
+
+  // NOTE(beder): ListenableFuture is not considered a producer framework type because it is not
+  // defined by the framework, so we can't treat it specially in ordinary Dagger.
+  private static final ImmutableSet<Class<?>> PRODUCTION_TYPES =
+      ImmutableSet.of(Produced.class, Producer.class);
+
+  /** Returns true if the type represents a producer-related framework type. */
+  static boolean isProducerType(TypeMirror type) {
+    return isType(type) && typeIsOneOf(PRODUCTION_TYPES, type);
+  }
+
+  /** Returns true if the type represents a framework type. */
+  static boolean isFrameworkType(TypeMirror type) {
+    return isType(type)
+        && (typeIsOneOf(PROVISION_TYPES, type)
+            || typeIsOneOf(PRODUCTION_TYPES, type));
+  }
+
+  private static boolean typeIsOneOf(Set<Class<?>> classes, TypeMirror type) {
+    for (Class<?> clazz : classes) {
+      if (MoreTypes.isTypeOf(clazz, type)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private FrameworkTypes() {}
+}
diff --git a/java/dagger/internal/codegen/GenerationCompilerOptions.java b/java/dagger/internal/codegen/GenerationCompilerOptions.java
new file mode 100644
index 0000000..1b14a7e
--- /dev/null
+++ b/java/dagger/internal/codegen/GenerationCompilerOptions.java
@@ -0,0 +1,30 @@
+/*
+ * 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 java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import javax.inject.Qualifier;
+
+/**
+ * A {@link Qualifier} for bindings associated with the serialization/deserialization of {@link
+ * dagger.internal.GenerationOptions}.
+ */
+@Retention(RUNTIME)
+@Qualifier
+@interface GenerationCompilerOptions {}
diff --git a/java/dagger/internal/codegen/GenerationOptionsModule.java b/java/dagger/internal/codegen/GenerationOptionsModule.java
new file mode 100644
index 0000000..aa3c461
--- /dev/null
+++ b/java/dagger/internal/codegen/GenerationOptionsModule.java
@@ -0,0 +1,55 @@
+/*
+ * 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 dagger.Module;
+import dagger.Provides;
+import dagger.internal.GenerationOptions;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.Optional;
+
+/** Adds bindings for serializing and rereading {@link GenerationOptions}. */
+@Module
+interface GenerationOptionsModule {
+  @Provides
+  @PerComponentImplementation
+  @GenerationCompilerOptions
+  static CompilerOptions generationOptions(
+      CompilerOptions defaultOptions,
+      ComponentImplementation componentImplementation,
+      DaggerElements elements) {
+    // Avoid looking up types that don't exist. Performance improves for large components.
+    if (!defaultOptions.aheadOfTimeSubcomponents()) {
+      return defaultOptions;
+    }
+    // Inspect the base implementation for the @GenerationOptions annotation. Even if
+    // componentImplementation is the base implementation, inspect it for the case where we are
+    // recomputing the ComponentImplementation from a previous compilation.
+    // TODO(b/117833324): consider adding a method that returns baseImplementation.orElse(this).
+    // The current state of the world is a little confusing and maybe not intuitive: the base
+    // implementation has no base implementation, but it _is_ a base implementation.
+    return Optional.of(componentImplementation.baseImplementation().orElse(componentImplementation))
+        .map(baseImplementation -> elements.getTypeElement(baseImplementation.name()))
+        // If this returns null, the type has not been generated yet and Optional will switch to an
+        // empty state. This means that we're currently generating componentImplementation, or that
+        // the base implementation is being generated in this round, and thus the options passed to
+        // this compilation are applicable
+        .map(typeElement -> typeElement.getAnnotation(GenerationOptions.class))
+        .map(defaultOptions::withGenerationOptions)
+        .orElse(defaultOptions);
+  }
+}
diff --git a/java/dagger/internal/codegen/GwtCompatibility.java b/java/dagger/internal/codegen/GwtCompatibility.java
new file mode 100644
index 0000000..34d8f6d
--- /dev/null
+++ b/java/dagger/internal/codegen/GwtCompatibility.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkArgument;
+
+import com.squareup.javapoet.AnnotationSpec;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Name;
+
+final class GwtCompatibility {
+
+  /**
+   * Returns a {@code @GwtIncompatible} annotation that is applied to {@code binding}'s {@link
+   * Binding#bindingElement()} or any enclosing type.
+   */
+  static Optional<AnnotationSpec> gwtIncompatibleAnnotation(Binding binding) {
+    checkArgument(binding.bindingElement().isPresent());
+    Element element = binding.bindingElement().get();
+    while (element != null) {
+      Optional<AnnotationSpec> gwtIncompatible =
+          element
+              .getAnnotationMirrors()
+              .stream()
+              .filter(annotation -> isGwtIncompatible(annotation))
+              .map(AnnotationSpec::get)
+              .findFirst();
+      if (gwtIncompatible.isPresent()) {
+        return gwtIncompatible;
+      }
+      element = element.getEnclosingElement();
+    }
+    return Optional.empty();
+  }
+
+  private static boolean isGwtIncompatible(AnnotationMirror annotation) {
+    Name simpleName = annotation.getAnnotationType().asElement().getSimpleName();
+    return simpleName.contentEquals("GwtIncompatible");
+  }
+}
diff --git a/java/dagger/internal/codegen/HjarSourceFileGenerator.java b/java/dagger/internal/codegen/HjarSourceFileGenerator.java
new file mode 100644
index 0000000..5c36322
--- /dev/null
+++ b/java/dagger/internal/codegen/HjarSourceFileGenerator.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2017 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.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeSpec;
+import java.util.Optional;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
+
+/**
+ * A source file generator that only writes the relevant code necessary for Bazel to create a
+ * correct header (ABI) jar.
+ */
+final class HjarSourceFileGenerator<T> extends SourceFileGenerator<T> {
+  private final SourceFileGenerator<T> delegate;
+
+  private HjarSourceFileGenerator(SourceFileGenerator<T> delegate) {
+    super(delegate);
+    this.delegate = delegate;
+  }
+
+  static <T> SourceFileGenerator<T> wrap(SourceFileGenerator<T> delegate) {
+    return new HjarSourceFileGenerator<>(delegate);
+  }
+
+  @Override
+  ClassName nameGeneratedType(T input) {
+    return delegate.nameGeneratedType(input);
+  }
+
+  @Override
+  Element originatingElement(T input) {
+    return delegate.originatingElement(input);
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, T input) {
+    return delegate
+        .write(generatedTypeName, input)
+        .map(completeType -> skeletonType(completeType.build()));
+  }
+
+  private TypeSpec.Builder skeletonType(TypeSpec completeType) {
+    TypeSpec.Builder skeleton =
+        classBuilder(completeType.name)
+            .addSuperinterfaces(completeType.superinterfaces)
+            .addTypeVariables(completeType.typeVariables)
+            .addModifiers(completeType.modifiers.toArray(new Modifier[0]))
+            .addAnnotations(completeType.annotations);
+
+    if (!completeType.superclass.equals(ClassName.OBJECT)) {
+      skeleton.superclass(completeType.superclass);
+    }
+
+    completeType.methodSpecs.stream()
+        .filter(method -> !method.modifiers.contains(PRIVATE) || method.isConstructor())
+        .map(this::skeletonMethod)
+        .forEach(skeleton::addMethod);
+
+    completeType.fieldSpecs.stream()
+        .filter(field -> !field.modifiers.contains(PRIVATE))
+        .map(this::skeletonField)
+        .forEach(skeleton::addField);
+
+    completeType.typeSpecs.stream()
+        .map(type -> skeletonType(type).build())
+        .forEach(skeleton::addType);
+
+    return skeleton;
+  }
+
+  private MethodSpec skeletonMethod(MethodSpec completeMethod) {
+    MethodSpec.Builder skeleton =
+        completeMethod.isConstructor()
+            ? constructorBuilder()
+            : methodBuilder(completeMethod.name).returns(completeMethod.returnType);
+
+    if (completeMethod.isConstructor()) {
+      // Code in Turbine must (for technical reasons in javac) have a valid super() call for
+      // constructors, otherwise javac will bark, and Turbine has no way to avoid this. So we retain
+      // constructor method bodies if they do exist
+      skeleton.addCode(completeMethod.code);
+    }
+
+    return skeleton
+        .addModifiers(completeMethod.modifiers)
+        .addTypeVariables(completeMethod.typeVariables)
+        .addParameters(completeMethod.parameters)
+        .addExceptions(completeMethod.exceptions)
+        .varargs(completeMethod.varargs)
+        .addAnnotations(completeMethod.annotations)
+        .build();
+  }
+
+  private FieldSpec skeletonField(FieldSpec completeField) {
+    return FieldSpec.builder(
+            completeField.type,
+            completeField.name,
+            completeField.modifiers.toArray(new Modifier[0]))
+        .addAnnotations(completeField.annotations)
+        .build();
+  }
+}
diff --git a/java/dagger/internal/codegen/ImmediateFutureBindingExpression.java b/java/dagger/internal/codegen/ImmediateFutureBindingExpression.java
new file mode 100644
index 0000000..69b107c
--- /dev/null
+++ b/java/dagger/internal/codegen/ImmediateFutureBindingExpression.java
@@ -0,0 +1,74 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import javax.lang.model.SourceVersion;
+
+final class ImmediateFutureBindingExpression extends BindingExpression {
+
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final DaggerTypes types;
+  private final SourceVersion sourceVersion;
+  private final Key key;
+
+  ImmediateFutureBindingExpression(
+      ResolvedBindings resolvedBindings,
+      ComponentBindingExpressions componentBindingExpressions,
+      DaggerTypes types,
+      SourceVersion sourceVersion) {
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+    this.types = checkNotNull(types);
+    this.sourceVersion = checkNotNull(sourceVersion);
+    this.key = resolvedBindings.key();
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    return Expression.create(
+        types.wrapType(key.type(), ListenableFuture.class),
+        CodeBlock.of("$T.immediateFuture($L)", Futures.class, instanceExpression(requestingClass)));
+  }
+
+  private CodeBlock instanceExpression(ClassName requestingClass) {
+    Expression expression =
+        componentBindingExpressions.getDependencyExpression(
+            bindingRequest(key, RequestKind.INSTANCE), requestingClass);
+    if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
+      // Java 7 type inference is not as strong as in Java 8, and therefore some generated code must
+      // cast.
+      //
+      // For example, javac7 cannot detect that Futures.immediateFuture(ImmutableSet.of("T"))
+      // can safely be assigned to ListenableFuture<Set<T>>.
+      if (!types.isSameType(expression.type(), key.type())) {
+        return CodeBlock.of(
+            "($T) $L", types.accessibleType(key.type(), requestingClass), expression.codeBlock());
+      }
+    }
+    return expression.codeBlock();
+  }
+}
diff --git a/java/dagger/internal/codegen/InaccessibleMapKeyProxyGenerator.java b/java/dagger/internal/codegen/InaccessibleMapKeyProxyGenerator.java
new file mode 100644
index 0000000..19c4d19
--- /dev/null
+++ b/java/dagger/internal/codegen/InaccessibleMapKeyProxyGenerator.java
@@ -0,0 +1,72 @@
+/*
+ * 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.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.Optional;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+
+/**
+ * Generates a class that exposes a non-{@code public} {@link
+ * ContributionBinding#mapKeyAnnotation()} @MapKey} annotation.
+ */
+final class InaccessibleMapKeyProxyGenerator extends SourceFileGenerator<ContributionBinding> {
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+
+  @Inject
+  InaccessibleMapKeyProxyGenerator(
+      Filer filer, DaggerTypes types, DaggerElements elements, SourceVersion sourceVersion) {
+    super(filer, elements, sourceVersion);
+    this.types = types;
+    this.elements = elements;
+  }
+
+  @Override
+  ClassName nameGeneratedType(ContributionBinding binding) {
+    return MapKeys.mapKeyProxyClassName(binding);
+  }
+
+  @Override
+  Element originatingElement(ContributionBinding binding) {
+    // a map key is only ever present on bindings that have a binding element
+    return binding.bindingElement().get();
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName generatedName, ContributionBinding binding) {
+    return MapKeys.mapKeyFactoryMethod(binding, types, elements)
+        .map(
+            method ->
+                classBuilder(generatedName)
+                    .addModifiers(PUBLIC, FINAL)
+                    .addMethod(constructorBuilder().addModifiers(PRIVATE).build())
+                    .addMethod(method));
+  }
+}
diff --git a/java/dagger/internal/codegen/IncompatiblyScopedBindingsValidator.java b/java/dagger/internal/codegen/IncompatiblyScopedBindingsValidator.java
new file mode 100644
index 0000000..d649e46
--- /dev/null
+++ b/java/dagger/internal/codegen/IncompatiblyScopedBindingsValidator.java
@@ -0,0 +1,142 @@
+/*
+ * 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 dagger.internal.codegen.Formatter.INDENT;
+import static dagger.internal.codegen.Scopes.getReadableSource;
+import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
+import static dagger.model.BindingKind.INJECTION;
+import static java.util.stream.Collectors.joining;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Multimaps;
+import dagger.model.Binding;
+import dagger.model.BindingGraph;
+import dagger.model.BindingGraph.ComponentNode;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.tools.Diagnostic;
+
+/**
+ * Reports an error for any component that uses bindings with scopes that are not assigned to the
+ * component.
+ */
+final class IncompatiblyScopedBindingsValidator implements BindingGraphPlugin {
+
+  private final MethodSignatureFormatter methodSignatureFormatter;
+  private final CompilerOptions compilerOptions;
+
+  @Inject
+  IncompatiblyScopedBindingsValidator(
+      MethodSignatureFormatter methodSignatureFormatter, CompilerOptions compilerOptions) {
+    this.methodSignatureFormatter = methodSignatureFormatter;
+    this.compilerOptions = compilerOptions;
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/IncompatiblyScopedBindings";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    ImmutableSetMultimap.Builder<ComponentNode, dagger.model.Binding> incompatibleBindings =
+        ImmutableSetMultimap.builder();
+    for (dagger.model.Binding binding : bindingGraph.bindings()) {
+      binding
+          .scope()
+          .filter(scope -> !scope.isReusable())
+          .ifPresent(
+              scope -> {
+                ComponentNode componentNode =
+                    bindingGraph.componentNode(binding.componentPath()).get();
+                if (!componentNode.scopes().contains(scope)) {
+                  // @Inject bindings in module or subcomponent binding graphs will appear at the
+                  // properly scoped ancestor component, so ignore them here.
+                  if (binding.kind().equals(INJECTION)
+                      && (bindingGraph.rootComponentNode().isSubcomponent()
+                          || !bindingGraph.rootComponentNode().isRealComponent())) {
+                    return;
+                  }
+                  incompatibleBindings.put(componentNode, binding);
+                }
+              });
+    }
+    Multimaps.asMap(incompatibleBindings.build())
+        .forEach((componentNode, bindings) -> report(componentNode, bindings, diagnosticReporter));
+  }
+
+  private void report(
+      ComponentNode componentNode,
+      Set<Binding> bindings,
+      DiagnosticReporter diagnosticReporter) {
+    Diagnostic.Kind diagnosticKind = ERROR;
+    StringBuilder message =
+        new StringBuilder(componentNode.componentPath().currentComponent().getQualifiedName());
+
+    if (!componentNode.isRealComponent()) {
+      // If the "component" is really a module, it will have no scopes attached. We want to report
+      // if there is more than one scope in that component.
+      if (bindings.stream().map(Binding::scope).map(Optional::get).distinct().count() <= 1) {
+        return;
+      }
+      message.append(" contains bindings with different scopes:");
+      diagnosticKind = compilerOptions.moduleHasDifferentScopesDiagnosticKind();
+    } else if (componentNode.scopes().isEmpty()) {
+      message.append(" (unscoped) may not reference scoped bindings:");
+    } else {
+      message
+          .append(" scoped with ")
+          .append(
+              componentNode.scopes().stream().map(Scopes::getReadableSource).collect(joining(" ")))
+          .append(" may not reference bindings with different scopes:");
+    }
+
+    // TODO(ronshapiro): Should we group by scope?
+    for (Binding binding : bindings) {
+      message.append('\n').append(INDENT);
+
+      // TODO(dpb): Use BindingDeclarationFormatter.
+      // But that doesn't print scopes for @Inject-constructed types.
+      switch (binding.kind()) {
+        case DELEGATE:
+        case PROVISION:
+          message.append(
+              methodSignatureFormatter.format(
+                  MoreElements.asExecutable(binding.bindingElement().get())));
+          break;
+
+        case INJECTION:
+          message
+              .append(getReadableSource(binding.scope().get()))
+              .append(" class ")
+              .append(
+                  closestEnclosingTypeElement(binding.bindingElement().get()).getQualifiedName());
+          break;
+
+        default:
+          throw new AssertionError(binding);
+      }
+    }
+    diagnosticReporter.reportComponent(diagnosticKind, componentNode, message.toString());
+  }
+}
diff --git a/java/dagger/internal/codegen/InjectBindingRegistry.java b/java/dagger/internal/codegen/InjectBindingRegistry.java
new file mode 100644
index 0000000..2840d75
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectBindingRegistry.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 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.errorprone.annotations.CanIgnoreReturnValue;
+import dagger.Component;
+import dagger.Provides;
+import dagger.model.Key;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Maintains the collection of provision bindings from {@link Inject} constructors and members
+ * injection bindings from {@link Inject} fields and methods known to the annotation processor. Note
+ * that this registry <b>does not</b> handle any explicit bindings (those from {@link Provides}
+ * methods, {@link Component} dependencies, etc.).
+ */
+interface InjectBindingRegistry {
+  /**
+   * Returns a {@link ProvisionBinding} for {@code key}. If none has been registered yet, registers
+   * one.
+   */
+  Optional<ProvisionBinding> getOrFindProvisionBinding(Key key);
+
+  /**
+   * Returns a {@link MembersInjectionBinding} for {@code key}. If none has been registered yet,
+   * registers one, along with all necessary members injection bindings for superclasses.
+   */
+  Optional<MembersInjectionBinding> getOrFindMembersInjectionBinding(Key key);
+
+  /**
+   * Returns a {@link ProvisionBinding} for a {@link dagger.MembersInjector} of {@code key}. If none
+   * has been registered yet, registers one.
+   */
+  Optional<ProvisionBinding> getOrFindMembersInjectorProvisionBinding(Key key);
+
+  @CanIgnoreReturnValue
+  Optional<ProvisionBinding> tryRegisterConstructor(ExecutableElement constructorElement);
+
+  @CanIgnoreReturnValue
+  Optional<MembersInjectionBinding> tryRegisterMembersInjectedType(TypeElement typeElement);
+
+  /**
+   * This method ensures that sources for all registered {@link Binding bindings} (either explicitly
+   * or implicitly via {@link #getOrFindMembersInjectionBinding} or {@link
+   * #getOrFindProvisionBinding}) are generated.
+   */
+  void generateSourcesForRequiredBindings(
+      SourceFileGenerator<ProvisionBinding> factoryGenerator,
+      SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator)
+      throws SourceFileGenerationException;
+}
diff --git a/java/dagger/internal/codegen/InjectBindingRegistryImpl.java b/java/dagger/internal/codegen/InjectBindingRegistryImpl.java
new file mode 100644
index 0000000..45dc391
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectBindingRegistryImpl.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.InjectionAnnotations.injectedConstructors;
+import static dagger.internal.codegen.Keys.isValidImplicitProvisionKey;
+import static dagger.internal.codegen.Keys.isValidMembersInjectionKey;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.squareup.javapoet.ClassName;
+import dagger.Component;
+import dagger.MembersInjector;
+import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import javax.annotation.processing.Messager;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic.Kind;
+
+/**
+ * Maintains the collection of provision bindings from {@link Inject} constructors and members
+ * injection bindings from {@link Inject} fields and methods known to the annotation processor.
+ * Note that this registry <b>does not</b> handle any explicit bindings (those from {@link Provides}
+ * methods, {@link Component} dependencies, etc.).
+ */
+@Singleton
+final class InjectBindingRegistryImpl implements InjectBindingRegistry {
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+  private final Messager messager;
+  private final InjectValidator injectValidator;
+  private final InjectValidator injectValidatorWhenGeneratingCode;
+  private final KeyFactory keyFactory;
+  private final BindingFactory bindingFactory;
+  private final CompilerOptions compilerOptions;
+
+  final class BindingsCollection<B extends Binding> {
+    private final Class<?> factoryClass;
+    private final Map<Key, B> bindingsByKey = Maps.newLinkedHashMap();
+    private final Deque<B> bindingsRequiringGeneration = new ArrayDeque<>();
+    private final Set<Key> materializedBindingKeys = Sets.newLinkedHashSet();
+
+    BindingsCollection(Class<?> factoryClass) {
+      this.factoryClass = factoryClass;
+    }
+
+    void generateBindings(SourceFileGenerator<B> generator) throws SourceFileGenerationException {
+      for (B binding = bindingsRequiringGeneration.poll();
+          binding != null;
+          binding = bindingsRequiringGeneration.poll()) {
+        checkState(!binding.unresolved().isPresent());
+        if (injectValidatorWhenGeneratingCode.isValidType(binding.key().type())) {
+          generator.generate(binding);
+        }
+        materializedBindingKeys.add(binding.key());
+      }
+      // Because Elements instantiated across processing rounds are not guaranteed to be equals() to
+      // the logically same element, clear the cache after generating
+      bindingsByKey.clear();
+    }
+
+    /** Returns a previously cached binding. */
+    B getBinding(Key key) {
+      return bindingsByKey.get(key);
+    }
+
+    /** Caches the binding and generates it if it needs generation. */
+    void tryRegisterBinding(B binding, boolean warnIfNotAlreadyGenerated) {
+      tryToCacheBinding(binding);
+      tryToGenerateBinding(binding, warnIfNotAlreadyGenerated);
+    }
+
+    /**
+     * Tries to generate a binding, not generating if it already is generated. For resolved
+     * bindings, this will try to generate the unresolved version of the binding.
+     */
+    void tryToGenerateBinding(B binding, boolean warnIfNotAlreadyGenerated) {
+      if (shouldGenerateBinding(binding, generatedClassNameForBinding(binding))) {
+        bindingsRequiringGeneration.offer(binding);
+        if (compilerOptions.warnIfInjectionFactoryNotGeneratedUpstream()
+            && warnIfNotAlreadyGenerated) {
+          messager.printMessage(
+              Kind.NOTE,
+              String.format(
+                  "Generating a %s for %s. "
+                      + "Prefer to run the dagger processor over that class instead.",
+                  factoryClass.getSimpleName(),
+                  types.erasure(binding.key().type()))); // erasure to strip <T> from msgs.
+        }
+      }
+    }
+
+    /** Returns true if the binding needs to be generated. */
+    private boolean shouldGenerateBinding(B binding, ClassName factoryName) {
+      return !binding.unresolved().isPresent()
+          && !materializedBindingKeys.contains(binding.key())
+          && !bindingsRequiringGeneration.contains(binding)
+          && elements.getTypeElement(factoryName) == null;
+    }
+
+    /** Caches the binding for future lookups by key. */
+    private void tryToCacheBinding(B binding) {
+      // We only cache resolved bindings or unresolved bindings w/o type arguments.
+      // Unresolved bindings w/ type arguments aren't valid for the object graph.
+      if (binding.unresolved().isPresent()
+          || binding.bindingTypeElement().get().getTypeParameters().isEmpty()) {
+        Key key = binding.key();
+        Binding previousValue = bindingsByKey.put(key, binding);
+        checkState(previousValue == null || binding.equals(previousValue),
+            "couldn't register %s. %s was already registered for %s",
+            binding, previousValue, key);
+      }
+    }
+  }
+
+  private final BindingsCollection<ProvisionBinding> provisionBindings =
+      new BindingsCollection<>(Provider.class);
+  private final BindingsCollection<MembersInjectionBinding> membersInjectionBindings =
+      new BindingsCollection<>(MembersInjector.class);
+
+  @Inject
+  InjectBindingRegistryImpl(
+      DaggerElements elements,
+      DaggerTypes types,
+      Messager messager,
+      InjectValidator injectValidator,
+      KeyFactory keyFactory,
+      BindingFactory bindingFactory,
+      CompilerOptions compilerOptions) {
+    this.elements = elements;
+    this.types = types;
+    this.messager = messager;
+    this.injectValidator = injectValidator;
+    this.injectValidatorWhenGeneratingCode = injectValidator.whenGeneratingCode();
+    this.keyFactory = keyFactory;
+    this.bindingFactory = bindingFactory;
+    this.compilerOptions = compilerOptions;
+  }
+
+  // TODO(dpb): make the SourceFileGenerators fields so they don't have to be passed in
+  @Override
+  public void generateSourcesForRequiredBindings(
+      SourceFileGenerator<ProvisionBinding> factoryGenerator,
+      SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator)
+      throws SourceFileGenerationException {
+    provisionBindings.generateBindings(factoryGenerator);
+    membersInjectionBindings.generateBindings(membersInjectorGenerator);
+  }
+
+  /**
+   * Registers the binding for generation and later lookup. If the binding is resolved, we also
+   * attempt to register an unresolved version of it.
+   */
+  private void registerBinding(ProvisionBinding binding, boolean warnIfNotAlreadyGenerated) {
+    provisionBindings.tryRegisterBinding(binding, warnIfNotAlreadyGenerated);
+    if (binding.unresolved().isPresent()) {
+      provisionBindings.tryToGenerateBinding(binding.unresolved().get(), warnIfNotAlreadyGenerated);
+    }
+  }
+
+  /**
+   * Registers the binding for generation and later lookup. If the binding is resolved, we also
+   * attempt to register an unresolved version of it.
+   */
+  private void registerBinding(MembersInjectionBinding binding, boolean warnIfNotAlreadyGenerated) {
+    /*
+     * We generate MembersInjector classes for types with @Inject constructors only if they have any
+     * injection sites.
+     *
+     * We generate MembersInjector classes for types without @Inject constructors only if they have
+     * local (non-inherited) injection sites.
+     *
+     * Warn only when registering bindings post-hoc for those types.
+     */
+    warnIfNotAlreadyGenerated =
+        warnIfNotAlreadyGenerated
+            && (!injectedConstructors(binding.membersInjectedType()).isEmpty()
+                ? !binding.injectionSites().isEmpty()
+                : binding.hasLocalInjectionSites());
+    membersInjectionBindings.tryRegisterBinding(binding, warnIfNotAlreadyGenerated);
+    if (binding.unresolved().isPresent()) {
+      membersInjectionBindings.tryToGenerateBinding(
+          binding.unresolved().get(), warnIfNotAlreadyGenerated);
+    }
+  }
+
+  @Override
+  public Optional<ProvisionBinding> tryRegisterConstructor(ExecutableElement constructorElement) {
+    return tryRegisterConstructor(constructorElement, Optional.empty(), false);
+  }
+
+  @CanIgnoreReturnValue
+  private Optional<ProvisionBinding> tryRegisterConstructor(
+      ExecutableElement constructorElement,
+      Optional<TypeMirror> resolvedType,
+      boolean warnIfNotAlreadyGenerated) {
+    TypeElement typeElement = MoreElements.asType(constructorElement.getEnclosingElement());
+    DeclaredType type = MoreTypes.asDeclared(typeElement.asType());
+    Key key = keyFactory.forInjectConstructorWithResolvedType(type);
+    ProvisionBinding cachedBinding = provisionBindings.getBinding(key);
+    if (cachedBinding != null) {
+      return Optional.of(cachedBinding);
+    }
+
+    ValidationReport<TypeElement> report = injectValidator.validateConstructor(constructorElement);
+    report.printMessagesTo(messager);
+    if (report.isClean()) {
+      ProvisionBinding binding = bindingFactory.injectionBinding(constructorElement, resolvedType);
+      registerBinding(binding, warnIfNotAlreadyGenerated);
+      if (!binding.injectionSites().isEmpty()) {
+        tryRegisterMembersInjectedType(typeElement, resolvedType, warnIfNotAlreadyGenerated);
+      }
+      return Optional.of(binding);
+    }
+    return Optional.empty();
+  }
+
+  @Override
+  public Optional<MembersInjectionBinding> tryRegisterMembersInjectedType(TypeElement typeElement) {
+    return tryRegisterMembersInjectedType(typeElement, Optional.empty(), false);
+  }
+
+  @CanIgnoreReturnValue
+  private Optional<MembersInjectionBinding> tryRegisterMembersInjectedType(
+      TypeElement typeElement,
+      Optional<TypeMirror> resolvedType,
+      boolean warnIfNotAlreadyGenerated) {
+    DeclaredType type = MoreTypes.asDeclared(typeElement.asType());
+    Key key = keyFactory.forInjectConstructorWithResolvedType(type);
+    MembersInjectionBinding cachedBinding = membersInjectionBindings.getBinding(key);
+    if (cachedBinding != null) {
+      return Optional.of(cachedBinding);
+    }
+
+    ValidationReport<TypeElement> report =
+        injectValidator.validateMembersInjectionType(typeElement);
+    report.printMessagesTo(messager);
+    if (report.isClean()) {
+      MembersInjectionBinding binding = bindingFactory.membersInjectionBinding(type, resolvedType);
+      registerBinding(binding, warnIfNotAlreadyGenerated);
+      for (Optional<DeclaredType> supertype = types.nonObjectSuperclass(type);
+          supertype.isPresent();
+          supertype = types.nonObjectSuperclass(supertype.get())) {
+        getOrFindMembersInjectionBinding(keyFactory.forMembersInjectedType(supertype.get()));
+      }
+      return Optional.of(binding);
+    }
+    return Optional.empty();
+  }
+
+  @CanIgnoreReturnValue
+  @Override
+  public Optional<ProvisionBinding> getOrFindProvisionBinding(Key key) {
+    checkNotNull(key);
+    if (!isValidImplicitProvisionKey(key, types)) {
+      return Optional.empty();
+    }
+    ProvisionBinding binding = provisionBindings.getBinding(key);
+    if (binding != null) {
+      return Optional.of(binding);
+    }
+
+    // ok, let's see if we can find an @Inject constructor
+    TypeElement element = MoreElements.asType(types.asElement(key.type()));
+    ImmutableSet<ExecutableElement> injectConstructors = injectedConstructors(element);
+    switch (injectConstructors.size()) {
+      case 0:
+        // No constructor found.
+        return Optional.empty();
+      case 1:
+        return tryRegisterConstructor(
+            Iterables.getOnlyElement(injectConstructors), Optional.of(key.type()), true);
+      default:
+        throw new IllegalStateException("Found multiple @Inject constructors: "
+            + injectConstructors);
+    }
+  }
+
+  @CanIgnoreReturnValue
+  @Override
+  public Optional<MembersInjectionBinding> getOrFindMembersInjectionBinding(Key key) {
+    checkNotNull(key);
+    // TODO(gak): is checking the kind enough?
+    checkArgument(isValidMembersInjectionKey(key));
+    MembersInjectionBinding binding = membersInjectionBindings.getBinding(key);
+    if (binding != null) {
+      return Optional.of(binding);
+    }
+    Optional<MembersInjectionBinding> newBinding =
+        tryRegisterMembersInjectedType(
+            MoreTypes.asTypeElement(key.type()), Optional.of(key.type()), true);
+    return newBinding;
+  }
+
+  @Override
+  public Optional<ProvisionBinding> getOrFindMembersInjectorProvisionBinding(Key key) {
+    if (!isValidMembersInjectionKey(key)) {
+      return Optional.empty();
+    }
+    Key membersInjectionKey = keyFactory.forMembersInjectedType(types.unwrapType(key.type()));
+    return getOrFindMembersInjectionBinding(membersInjectionKey)
+        .map(binding -> bindingFactory.membersInjectorBinding(key, binding));
+  }
+}
diff --git a/java/dagger/internal/codegen/InjectBindingRegistryModule.java b/java/dagger/internal/codegen/InjectBindingRegistryModule.java
new file mode 100644
index 0000000..4563362
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectBindingRegistryModule.java
@@ -0,0 +1,26 @@
+/*
+ * 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 dagger.Binds;
+import dagger.Module;
+
+@Module
+interface InjectBindingRegistryModule {
+  @Binds
+  InjectBindingRegistry injectBindingRegistry(InjectBindingRegistryImpl impl);
+}
diff --git a/java/dagger/internal/codegen/InjectBindingValidator.java b/java/dagger/internal/codegen/InjectBindingValidator.java
new file mode 100644
index 0000000..183d162
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectBindingValidator.java
@@ -0,0 +1,59 @@
+/*
+ * 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 dagger.model.BindingKind.INJECTION;
+
+import com.google.auto.common.MoreTypes;
+import dagger.internal.codegen.ValidationReport.Item;
+import dagger.model.BindingGraph;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import javax.inject.Inject;
+import javax.lang.model.element.TypeElement;
+
+/** Validates bindings from {@code @Inject}-annotated constructors. */
+final class InjectBindingValidator implements BindingGraphPlugin {
+
+  private final InjectValidator injectValidator;
+
+  @Inject
+  InjectBindingValidator(InjectValidator injectValidator) {
+    this.injectValidator = injectValidator.whenGeneratingCode();
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/InjectBinding";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    bindingGraph.bindings().stream()
+        .filter(binding -> binding.kind().equals(INJECTION)) // TODO(dpb): Move to BindingGraph
+        .forEach(binding -> validateInjectionBinding(binding, diagnosticReporter));
+  }
+
+  private void validateInjectionBinding(
+      dagger.model.Binding node, DiagnosticReporter diagnosticReporter) {
+    ValidationReport<TypeElement> typeReport =
+        injectValidator.validateType(MoreTypes.asTypeElement(node.key().type()));
+    for (Item item : typeReport.allItems()) {
+      diagnosticReporter.reportBinding(item.kind(), node, item.message());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/InjectProcessingStep.java b/java/dagger/internal/codegen/InjectProcessingStep.java
index 5374592..be8c975 100644
--- a/java/dagger/internal/codegen/InjectProcessingStep.java
+++ b/java/dagger/internal/codegen/InjectProcessingStep.java
@@ -18,10 +18,6 @@
 
 import com.google.auto.common.MoreElements;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-import dagger.assisted.AssistedInject;
-import dagger.internal.codegen.binding.InjectBindingRegistry;
-import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
 import java.lang.annotation.Annotation;
 import java.util.Set;
 import javax.inject.Inject;
@@ -38,7 +34,6 @@
 // TODO(gak): add some error handling for bad source files
 final class InjectProcessingStep extends TypeCheckingProcessingStep<Element> {
   private final ElementVisitor<Void, Void> visitor;
-  private final Set<Element> processedElements = Sets.newLinkedHashSet();
 
   @Inject
   InjectProcessingStep(InjectBindingRegistry injectBindingRegistry) {
@@ -70,20 +65,12 @@
 
   @Override
   public Set<Class<? extends Annotation>> annotations() {
-    return ImmutableSet.of(Inject.class, AssistedInject.class);
+    return ImmutableSet.of(Inject.class);
   }
 
   @Override
   protected void process(
       Element injectElement, ImmutableSet<Class<? extends Annotation>> annotations) {
-    // Only process an element once to avoid getting duplicate errors when an element is annotated
-    // with multiple inject annotations.
-    if (processedElements.contains(injectElement)) {
-      return;
-    }
-
     injectElement.accept(visitor, null);
-
-    processedElements.add(injectElement);
   }
 }
diff --git a/java/dagger/internal/codegen/InjectValidator.java b/java/dagger/internal/codegen/InjectValidator.java
new file mode 100644
index 0000000..d3c4ce8
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectValidator.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2014 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.MoreElements.isAnnotationPresent;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifiers;
+import static dagger.internal.codegen.InjectionAnnotations.injectedConstructors;
+import static dagger.internal.codegen.Scopes.scopesOf;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.type.TypeKind.DECLARED;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import dagger.internal.codegen.langmodel.Accessibility;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Scope;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+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.element.VariableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import javax.tools.Diagnostic;
+import javax.tools.Diagnostic.Kind;
+
+/**
+ * A {@linkplain ValidationReport validator} for {@link Inject}-annotated elements and the types
+ * that contain them.
+ */
+final class InjectValidator {
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+  private final CompilerOptions compilerOptions;
+  private final DependencyRequestValidator dependencyRequestValidator;
+  private final Optional<Diagnostic.Kind> privateAndStaticInjectionDiagnosticKind;
+
+  @Inject
+  InjectValidator(
+      DaggerTypes types,
+      DaggerElements elements,
+      DependencyRequestValidator dependencyRequestValidator,
+      CompilerOptions compilerOptions) {
+    this(types, elements, compilerOptions, dependencyRequestValidator, Optional.empty());
+  }
+
+  private InjectValidator(
+      DaggerTypes types,
+      DaggerElements elements,
+      CompilerOptions compilerOptions,
+      DependencyRequestValidator dependencyRequestValidator,
+      Optional<Kind> privateAndStaticInjectionDiagnosticKind) {
+    this.types = types;
+    this.elements = elements;
+    this.compilerOptions = compilerOptions;
+    this.dependencyRequestValidator = dependencyRequestValidator;
+    this.privateAndStaticInjectionDiagnosticKind = privateAndStaticInjectionDiagnosticKind;
+  }
+
+  /**
+   * Returns a new validator that performs the same validation as this one, but is strict about
+   * rejecting optionally-specified JSR 330 behavior that Dagger doesn't support (unless {@code
+   * -Adagger.ignorePrivateAndStaticInjectionForComponent=enabled} was set in the javac options).
+   */
+  InjectValidator whenGeneratingCode() {
+    return compilerOptions.ignorePrivateAndStaticInjectionForComponent()
+        ? this
+        : new InjectValidator(
+            types,
+            elements,
+            compilerOptions,
+            dependencyRequestValidator,
+            Optional.of(Diagnostic.Kind.ERROR));
+  }
+
+  ValidationReport<TypeElement> validateConstructor(ExecutableElement constructorElement) {
+    ValidationReport.Builder<TypeElement> builder =
+        ValidationReport.about(MoreElements.asType(constructorElement.getEnclosingElement()));
+    if (constructorElement.getModifiers().contains(PRIVATE)) {
+      builder.addError(
+          "Dagger does not support injection into private constructors", constructorElement);
+    }
+
+    for (AnnotationMirror qualifier : getQualifiers(constructorElement)) {
+      builder.addError(
+          "@Qualifier annotations are not allowed on @Inject constructors",
+          constructorElement,
+          qualifier);
+    }
+
+    for (Scope scope : scopesOf(constructorElement)) {
+      builder.addError(
+          "@Scope annotations are not allowed on @Inject constructors; annotate the class instead",
+          constructorElement,
+          scope.scopeAnnotation());
+    }
+
+    for (VariableElement parameter : constructorElement.getParameters()) {
+      validateDependencyRequest(builder, parameter);
+    }
+
+    if (throwsCheckedExceptions(constructorElement)) {
+      builder.addItem(
+          "Dagger does not support checked exceptions on @Inject constructors",
+          privateMemberDiagnosticKind(),
+          constructorElement);
+    }
+
+    checkInjectIntoPrivateClass(constructorElement, builder);
+
+    TypeElement enclosingElement =
+        MoreElements.asType(constructorElement.getEnclosingElement());
+
+    Set<Modifier> typeModifiers = enclosingElement.getModifiers();
+    if (typeModifiers.contains(ABSTRACT)) {
+      builder.addError(
+          "@Inject is nonsense on the constructor of an abstract class", constructorElement);
+    }
+
+    if (enclosingElement.getNestingKind().isNested()
+        && !typeModifiers.contains(STATIC)) {
+      builder.addError(
+          "@Inject constructors are invalid on inner classes. "
+              + "Did you mean to make the class static?",
+          constructorElement);
+    }
+
+    // This is computationally expensive, but probably preferable to a giant index
+    ImmutableSet<ExecutableElement> injectConstructors = injectedConstructors(enclosingElement);
+
+    if (injectConstructors.size() > 1) {
+      builder.addError("Types may only contain one @Inject constructor", constructorElement);
+    }
+
+    ImmutableSet<Scope> scopes = scopesOf(enclosingElement);
+    if (scopes.size() > 1) {
+      for (Scope scope : scopes) {
+        builder.addError(
+            "A single binding may not declare more than one @Scope",
+            enclosingElement,
+            scope.scopeAnnotation());
+      }
+    }
+
+    return builder.build();
+  }
+
+  private ValidationReport<VariableElement> validateField(VariableElement fieldElement) {
+    ValidationReport.Builder<VariableElement> builder = ValidationReport.about(fieldElement);
+    Set<Modifier> modifiers = fieldElement.getModifiers();
+    if (modifiers.contains(FINAL)) {
+      builder.addError("@Inject fields may not be final", fieldElement);
+    }
+
+    if (modifiers.contains(PRIVATE)) {
+      builder.addItem(
+          "Dagger does not support injection into private fields",
+          privateMemberDiagnosticKind(),
+          fieldElement);
+    }
+
+    if (modifiers.contains(STATIC)) {
+      builder.addItem(
+          "Dagger does not support injection into static fields",
+          staticMemberDiagnosticKind(),
+          fieldElement);
+    }
+
+    validateDependencyRequest(builder, fieldElement);
+
+    return builder.build();
+  }
+
+  private ValidationReport<ExecutableElement> validateMethod(ExecutableElement methodElement) {
+    ValidationReport.Builder<ExecutableElement> builder = ValidationReport.about(methodElement);
+    Set<Modifier> modifiers = methodElement.getModifiers();
+    if (modifiers.contains(ABSTRACT)) {
+      builder.addError("Methods with @Inject may not be abstract", methodElement);
+    }
+
+    if (modifiers.contains(PRIVATE)) {
+      builder.addItem(
+          "Dagger does not support injection into private methods",
+          privateMemberDiagnosticKind(),
+          methodElement);
+    }
+
+    if (modifiers.contains(STATIC)) {
+      builder.addItem(
+          "Dagger does not support injection into static methods",
+          staticMemberDiagnosticKind(),
+          methodElement);
+    }
+
+    if (!methodElement.getTypeParameters().isEmpty()) {
+      builder.addError("Methods with @Inject may not declare type parameters", methodElement);
+    }
+
+    for (VariableElement parameter : methodElement.getParameters()) {
+      validateDependencyRequest(builder, parameter);
+    }
+
+    return builder.build();
+  }
+
+  private void validateDependencyRequest(
+      ValidationReport.Builder<?> builder, VariableElement parameter) {
+    dependencyRequestValidator.validateDependencyRequest(builder, parameter, parameter.asType());
+    dependencyRequestValidator.checkNotProducer(builder, parameter);
+  }
+
+  ValidationReport<TypeElement> validateMembersInjectionType(TypeElement typeElement) {
+    // TODO(beder): This element might not be currently compiled, so this error message could be
+    // left in limbo. Find an appropriate way to display the error message in that case.
+    ValidationReport.Builder<TypeElement> builder = ValidationReport.about(typeElement);
+    boolean hasInjectedMembers = false;
+    for (VariableElement element : ElementFilter.fieldsIn(typeElement.getEnclosedElements())) {
+      if (MoreElements.isAnnotationPresent(element, Inject.class)) {
+        hasInjectedMembers = true;
+        ValidationReport<VariableElement> report = validateField(element);
+        if (!report.isClean()) {
+          builder.addSubreport(report);
+        }
+      }
+    }
+    for (ExecutableElement element : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
+      if (MoreElements.isAnnotationPresent(element, Inject.class)) {
+        hasInjectedMembers = true;
+        ValidationReport<ExecutableElement> report = validateMethod(element);
+        if (!report.isClean()) {
+          builder.addSubreport(report);
+        }
+      }
+    }
+
+    if (hasInjectedMembers) {
+      checkInjectIntoPrivateClass(typeElement, builder);
+    }
+    TypeMirror superclass = typeElement.getSuperclass();
+    if (!superclass.getKind().equals(TypeKind.NONE)) {
+      ValidationReport<TypeElement> report = validateType(MoreTypes.asTypeElement(superclass));
+      if (!report.isClean()) {
+        builder.addSubreport(report);
+      }
+    }
+    return builder.build();
+  }
+
+  ValidationReport<TypeElement> validateType(TypeElement typeElement) {
+    ValidationReport.Builder<TypeElement> builder = ValidationReport.about(typeElement);
+    ValidationReport<TypeElement> membersInjectionReport =
+        validateMembersInjectionType(typeElement);
+    if (!membersInjectionReport.isClean()) {
+      builder.addSubreport(membersInjectionReport);
+    }
+    for (ExecutableElement element :
+        ElementFilter.constructorsIn(typeElement.getEnclosedElements())) {
+      if (isAnnotationPresent(element, Inject.class)) {
+        ValidationReport<TypeElement> report = validateConstructor(element);
+        if (!report.isClean()) {
+          builder.addSubreport(report);
+        }
+      }
+    }
+    return builder.build();
+  }
+
+  boolean isValidType(TypeMirror type) {
+    if (!type.getKind().equals(DECLARED)) {
+      return true;
+    }
+    return validateType(MoreTypes.asTypeElement(type)).isClean();
+  }
+
+  /** Returns true if the given method element declares a checked exception. */
+  private boolean throwsCheckedExceptions(ExecutableElement methodElement) {
+    TypeMirror runtimeExceptionType = elements.getTypeElement(RuntimeException.class).asType();
+    TypeMirror errorType = elements.getTypeElement(Error.class).asType();
+    for (TypeMirror thrownType : methodElement.getThrownTypes()) {
+      if (!types.isSubtype(thrownType, runtimeExceptionType)
+          && !types.isSubtype(thrownType, errorType)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private void checkInjectIntoPrivateClass(
+      Element element, ValidationReport.Builder<TypeElement> builder) {
+    if (!Accessibility.isElementAccessibleFromOwnPackage(
+        DaggerElements.closestEnclosingTypeElement(element))) {
+      builder.addItem(
+          "Dagger does not support injection into private classes",
+          privateMemberDiagnosticKind(),
+          element);
+    }
+  }
+
+  private Diagnostic.Kind privateMemberDiagnosticKind() {
+    return privateAndStaticInjectionDiagnosticKind.orElse(
+        compilerOptions.privateMemberValidationKind());
+  }
+
+  private Diagnostic.Kind staticMemberDiagnosticKind() {
+    return privateAndStaticInjectionDiagnosticKind.orElse(
+        compilerOptions.staticMemberValidationKind());
+  }
+}
diff --git a/java/dagger/internal/codegen/InjectionAnnotations.java b/java/dagger/internal/codegen/InjectionAnnotations.java
new file mode 100644
index 0000000..521ad43
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectionAnnotations.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 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.MoreElements.isAnnotationPresent;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static javax.lang.model.util.ElementFilter.constructorsIn;
+
+import com.google.auto.common.AnnotationMirrors;
+import com.google.auto.common.SuperficialValidation;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.inject.Qualifier;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Utilities relating to annotations defined in the {@code javax.inject} package.
+ */
+final class InjectionAnnotations {
+  static Optional<AnnotationMirror> getQualifier(Element e) {
+    if (!SuperficialValidation.validateElement(e)) {
+      throw new TypeNotPresentException(e.toString(), null);
+    }
+    checkNotNull(e);
+    ImmutableSet<? extends AnnotationMirror> qualifierAnnotations = getQualifiers(e);
+    switch (qualifierAnnotations.size()) {
+      case 0:
+        return Optional.empty();
+      case 1:
+        return Optional.<AnnotationMirror>of(qualifierAnnotations.iterator().next());
+      default:
+        throw new IllegalArgumentException(
+            e + " was annotated with more than one @Qualifier annotation");
+    }
+  }
+
+  static ImmutableSet<? extends AnnotationMirror> getQualifiers(Element element) {
+    return AnnotationMirrors.getAnnotatedAnnotations(element, Qualifier.class);
+  }
+
+  /** Returns the constructors in {@code type} that are annotated with {@link Inject}. */
+  static ImmutableSet<ExecutableElement> injectedConstructors(TypeElement type) {
+    return FluentIterable.from(constructorsIn(type.getEnclosedElements()))
+        .filter(constructor -> isAnnotationPresent(constructor, Inject.class))
+        .toSet();
+  }
+
+  private InjectionAnnotations() {}
+}
diff --git a/java/dagger/internal/codegen/InjectionMethod.java b/java/dagger/internal/codegen/InjectionMethod.java
new file mode 100644
index 0000000..2785b18
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectionMethod.java
@@ -0,0 +1,210 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypePubliclyAccessible;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.errorprone.annotations.CheckReturnValue;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.List;
+import java.util.Optional;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Parameterizable;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A static method that implements provision and/or injection in one step:
+ *
+ * <ul>
+ *   <li>methods that invoke {@code @Inject} constructors and do members injection if necessary
+ *   <li>methods that call {@code @Provides} module methods
+ *   <li>methods that perform members injection
+ * </ul>
+ *
+ * <p>Note that although this type uses {@code @AutoValue}, it uses instance equality. It uses
+ * {@code @AutoValue} to avoid the boilerplate of writing a correct builder, but is not intended to
+ * actually be a value type.
+ */
+@AutoValue
+abstract class InjectionMethod {
+  abstract String name();
+
+  abstract boolean varargs();
+
+  abstract ImmutableList<TypeVariableName> typeVariables();
+
+  abstract ImmutableMap<ParameterSpec, TypeMirror> parameters();
+
+  abstract Optional<TypeMirror> returnType();
+
+  abstract Optional<DeclaredType> nullableAnnotation();
+
+  abstract ImmutableList<TypeMirror> exceptions();
+
+  abstract CodeBlock methodBody();
+
+  abstract ClassName enclosingClass();
+
+  MethodSpec toMethodSpec() {
+    MethodSpec.Builder builder =
+        methodBuilder(name())
+            .addModifiers(PUBLIC, STATIC)
+            .varargs(varargs())
+            .addTypeVariables(typeVariables())
+            .addParameters(parameters().keySet())
+            .addCode(methodBody());
+    returnType().map(TypeName::get).ifPresent(builder::returns);
+    nullableAnnotation()
+        .ifPresent(nullableType -> CodeBlocks.addAnnotation(builder, nullableType));
+    exceptions().stream().map(TypeName::get).forEach(builder::addException);
+    return builder.build();
+  }
+
+  CodeBlock invoke(List<CodeBlock> arguments, ClassName requestingClass) {
+    checkArgument(arguments.size() == parameters().size());
+    CodeBlock.Builder invocation = CodeBlock.builder();
+    if (!enclosingClass().equals(requestingClass)) {
+      invocation.add("$T.", enclosingClass());
+    }
+    return invocation.add("$L($L)", name(), makeParametersCodeBlock(arguments)).build();
+  }
+
+  @Override
+  public final int hashCode() {
+    return System.identityHashCode(this);
+  }
+
+  @Override
+  public final boolean equals(Object obj) {
+    return this == obj;
+  }
+
+  static Builder builder(DaggerElements elements) {
+    Builder builder = new AutoValue_InjectionMethod.Builder();
+    builder.elements = elements;
+    builder.varargs(false).exceptions(ImmutableList.of()).nullableAnnotation(Optional.empty());
+    return builder;
+  }
+
+  @CanIgnoreReturnValue
+  @AutoValue.Builder
+  abstract static class Builder {
+    private final UniqueNameSet parameterNames = new UniqueNameSet();
+    private final CodeBlock.Builder methodBody = CodeBlock.builder();
+    private DaggerElements elements;
+
+    abstract ImmutableMap.Builder<ParameterSpec, TypeMirror> parametersBuilder();
+    abstract ImmutableList.Builder<TypeVariableName> typeVariablesBuilder();
+    abstract Builder name(String name);
+    abstract Builder varargs(boolean varargs);
+    abstract Builder returnType(TypeMirror returnType);
+    abstract Builder exceptions(Iterable<? extends TypeMirror> exceptions);
+    abstract Builder nullableAnnotation(Optional<DeclaredType> nullableAnnotation);
+    abstract Builder methodBody(CodeBlock methodBody);
+
+    final CodeBlock.Builder methodBodyBuilder() {
+      return methodBody;
+    }
+
+    abstract Builder enclosingClass(ClassName enclosingClass);
+
+    /**
+     * Adds a parameter for the given name and type. If another parameter has already been added
+     * with the same name, the name is disambiguated.
+     */
+    ParameterSpec addParameter(String name, TypeMirror type) {
+      ParameterSpec parameter =
+          ParameterSpec.builder(TypeName.get(type), parameterNames.getUniqueName(name)).build();
+      parametersBuilder().put(parameter, type);
+      return parameter;
+    }
+
+    /**
+     * Calls {@link #copyParameter(VariableElement)} for each parameter of of {@code method}, and
+     * concatenates the results of each call, {@link CodeBlocks#makeParametersCodeBlock(Iterable)
+     * separated with commas}.
+     */
+    CodeBlock copyParameters(ExecutableElement method) {
+      ImmutableList.Builder<CodeBlock> argumentsBuilder = ImmutableList.builder();
+      for (VariableElement parameter : method.getParameters()) {
+        argumentsBuilder.add(copyParameter(parameter));
+      }
+      varargs(method.isVarArgs());
+      return makeParametersCodeBlock(argumentsBuilder.build());
+    }
+
+    /**
+     * Adds {@code parameter} as a parameter of this method, using a publicly accessible version of
+     * the parameter's type. Returns a {@link CodeBlock} of the usage of this parameter within the
+     * injection method's {@link #methodBody()}.
+     */
+    CodeBlock copyParameter(VariableElement parameter) {
+      TypeMirror elementType = parameter.asType();
+      boolean useObject = !isRawTypePubliclyAccessible(elementType);
+      TypeMirror publicType =  useObject ? objectType() : elementType;
+      ParameterSpec parameterSpec = addParameter(parameter.getSimpleName().toString(), publicType);
+      return useObject
+          ? CodeBlock.of("($T) $N", elementType, parameterSpec)
+          : CodeBlock.of("$N", parameterSpec);
+    }
+
+    private TypeMirror objectType() {
+      return elements.getTypeElement(Object.class).asType();
+    }
+
+    /**
+     * Adds each type parameter of {@code parameterizable} as a type parameter of this injection
+     * method.
+     */
+    Builder copyTypeParameters(Parameterizable parameterizable) {
+      parameterizable.getTypeParameters().stream()
+          .map(TypeVariableName::get)
+          .forEach(typeVariablesBuilder()::add);
+      return this;
+    }
+
+    Builder copyThrows(ExecutableElement element) {
+      exceptions(element.getThrownTypes());
+      return this;
+    }
+
+    @CheckReturnValue
+    final InjectionMethod build() {
+      return methodBody(methodBody.build()).buildInternal();
+    }
+
+    abstract InjectionMethod buildInternal();
+  }
+}
diff --git a/java/dagger/internal/codegen/InjectionMethods.java b/java/dagger/internal/codegen/InjectionMethods.java
new file mode 100644
index 0000000..d61aaa5
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectionMethods.java
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2017 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.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.FactoryGenerator.checkNotNullProvidesMethod;
+import static dagger.internal.codegen.RequestKinds.requestTypeName;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toConcatenatedCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
+import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypePubliclyAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static java.util.stream.Collectors.toList;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.type.TypeKind.VOID;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import dagger.model.RequestKind;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+/** Convenience methods for creating and invoking {@link InjectionMethod}s. */
+final class InjectionMethods {
+
+  /**
+   * A method that returns an object from a {@code @Provides} method or an {@code @Inject}ed
+   * constructor. Its parameters match the dependency requests for constructor and members
+   * injection.
+   *
+   * <p>For {@code @Provides} methods named "foo", the method name is "proxyFoo". If the
+   * {@code @Provides} method and its raw parameter types are publicly accessible, no method is
+   * necessary and this method returns {@link Optional#empty()}.
+   *
+   * <p>Example:
+   *
+   * <pre><code>
+   * abstract class FooModule {
+   *   {@literal @Provides} static Foo provideFoo(Bar bar, Baz baz) { … }
+   * }
+   *
+   * public static proxyProvideFoo(Bar bar, Baz baz) { … }
+   * </code></pre>
+   *
+   * <p>For {@code @Inject}ed constructors, the method name is "newFoo". If the constructor and its
+   * raw parameter types are publicly accessible, no method is necessary and this method returns
+   * {@code Optional#empty()}.
+   *
+   * <p>Example:
+   *
+   * <pre><code>
+   * class Foo {
+   *   {@literal @Inject} Foo(Bar bar) {}
+   * }
+   *
+   * public static Foo newFoo(Bar bar) { … }
+   * </code></pre>
+   */
+  static final class ProvisionMethod {
+    /**
+     * Names of methods that are already defined in factories and shouldn't be used for the proxy
+     * method name.
+     */
+    private static final ImmutableSet<String> BANNED_PROXY_NAMES = ImmutableSet.of("get", "create");
+
+    /**
+     * Returns a method that invokes the binding's {@linkplain ProvisionBinding#bindingElement()
+     * constructor} and injects the instance's members.
+     */
+    static InjectionMethod create(
+        ProvisionBinding binding, CompilerOptions compilerOptions, DaggerElements elements) {
+      ClassName proxyEnclosingClass = generatedClassNameForBinding(binding);
+      ExecutableElement element = MoreElements.asExecutable(binding.bindingElement().get());
+      switch (element.getKind()) {
+        case CONSTRUCTOR:
+          return constructorProxy(proxyEnclosingClass, element, elements);
+        case METHOD:
+          return methodProxy(
+              proxyEnclosingClass,
+              element,
+              methodName(element),
+              ReceiverAccessibility.IGNORE,
+              CheckNotNullPolicy.get(binding, compilerOptions),
+              elements);
+        default:
+          throw new AssertionError(element);
+      }
+    }
+
+    /**
+     * Invokes the injection method for {@code binding}, with the dependencies transformed with the
+     * {@code dependencyUsage} function.
+     */
+    // TODO(ronshapiro): Further extract a ProvisionMethod type that composes an InjectionMethod, so
+    // users can write ProvisionMethod.create().invoke()
+    static CodeBlock invoke(
+        ProvisionBinding binding,
+        Function<DependencyRequest, CodeBlock> dependencyUsage,
+        ClassName requestingClass,
+        Optional<CodeBlock> moduleReference,
+        CompilerOptions compilerOptions,
+        DaggerElements elements) {
+      ImmutableList.Builder<CodeBlock> arguments = ImmutableList.builder();
+      moduleReference.ifPresent(arguments::add);
+      arguments.addAll(
+          injectionMethodArguments(
+              binding.provisionDependencies(), dependencyUsage, requestingClass));
+      // TODO(ronshapiro): make InjectionMethods @Injectable
+      return create(binding, compilerOptions, elements).invoke(arguments.build(), requestingClass);
+    }
+
+    private static InjectionMethod constructorProxy(
+        ClassName proxyEnclosingClass, ExecutableElement constructor, DaggerElements elements) {
+      TypeElement enclosingType = MoreElements.asType(constructor.getEnclosingElement());
+      InjectionMethod.Builder injectionMethod =
+          InjectionMethod.builder(elements)
+              .name(methodName(constructor))
+              .returnType(enclosingType.asType())
+              .enclosingClass(proxyEnclosingClass);
+
+      injectionMethod
+          .copyTypeParameters(enclosingType)
+          .copyThrows(constructor);
+
+      CodeBlock arguments = injectionMethod.copyParameters(constructor);
+      injectionMethod
+          .methodBodyBuilder()
+          .addStatement("return new $T($L)", enclosingType, arguments);
+      return injectionMethod.build();
+    }
+
+    /**
+     * Returns {@code true} if injecting an instance of {@code binding} from {@code callingPackage}
+     * requires the use of an injection method.
+     */
+    static boolean requiresInjectionMethod(
+        ProvisionBinding binding,
+        ImmutableList<Expression> arguments,
+        CompilerOptions compilerOptions,
+        String callingPackage,
+        DaggerTypes types) {
+      ExecutableElement method = MoreElements.asExecutable(binding.bindingElement().get());
+      return !binding.injectionSites().isEmpty()
+          || binding.shouldCheckForNull(compilerOptions)
+          || !isElementAccessibleFrom(method, callingPackage)
+          || !areParametersAssignable(method, arguments, types)
+          // This check should be removable once we drop support for -source 7
+          || method.getParameters().stream()
+              .map(VariableElement::asType)
+              .anyMatch(type -> !isRawTypeAccessible(type, callingPackage));
+    }
+
+    private static boolean areParametersAssignable(
+        ExecutableElement element, ImmutableList<Expression> arguments, DaggerTypes types) {
+      List<? extends VariableElement> parameters = element.getParameters();
+      checkArgument(parameters.size() == arguments.size());
+      for (int i = 0; i < parameters.size(); i++) {
+        if (!types.isAssignable(arguments.get(i).type(), parameters.get(i).asType())) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    /**
+     * Returns the name of the {@code static} method that wraps {@code method}. For methods that are
+     * associated with {@code @Inject} constructors, the method will also inject all {@link
+     * InjectionSite}s.
+     */
+    private static String methodName(ExecutableElement method) {
+      switch (method.getKind()) {
+        case CONSTRUCTOR:
+          return "newInstance";
+        case METHOD:
+          String methodName = method.getSimpleName().toString();
+          return BANNED_PROXY_NAMES.contains(methodName)
+              ? "proxy" + LOWER_CAMEL.to(UPPER_CAMEL, methodName)
+              : methodName;
+        default:
+          throw new AssertionError(method);
+      }
+    }
+  }
+
+  /**
+   * A static method that injects one member of an instance of a type. Its first parameter is an
+   * instance of the type to be injected. The remaining parameters match the dependency requests for
+   * the injection site.
+   *
+   * <p>Example:
+   *
+   * <pre><code>
+   * class Foo {
+   *   {@literal @Inject} Bar bar;
+   *   {@literal @Inject} void setThings(Baz baz, Qux qux) {}
+   * }
+   *
+   * public static injectBar(Foo instance, Bar bar) { … }
+   * public static injectSetThings(Foo instance, Baz baz, Qux qux) { … }
+   * </code></pre>
+   */
+  static final class InjectionSiteMethod {
+    /**
+     * When a type has an inaccessible member from a supertype (e.g. an @Inject field in a parent
+     * that's in a different package), a method in the supertype's package must be generated to give
+     * the subclass's members injector a way to inject it. Each potentially inaccessible member
+     * receives its own method, as the subclass may need to inject them in a different order from
+     * the parent class.
+     */
+    static InjectionMethod create(InjectionSite injectionSite, DaggerElements elements) {
+      String methodName = methodName(injectionSite);
+      ClassName proxyEnclosingClass = membersInjectorNameForType(
+          MoreElements.asType(injectionSite.element().getEnclosingElement()));
+      switch (injectionSite.kind()) {
+        case METHOD:
+          return methodProxy(
+              proxyEnclosingClass,
+              MoreElements.asExecutable(injectionSite.element()),
+              methodName,
+              ReceiverAccessibility.CAST_IF_NOT_PUBLIC,
+              CheckNotNullPolicy.IGNORE,
+              elements);
+        case FIELD:
+          return fieldProxy(
+              proxyEnclosingClass,
+              MoreElements.asVariable(injectionSite.element()),
+              methodName,
+              elements);
+      }
+      throw new AssertionError(injectionSite);
+    }
+
+    /**
+     * Invokes each of the injection methods for {@code injectionSites}, with the dependencies
+     * transformed using the {@code dependencyUsage} function.
+     *
+     * @param instanceType the type of the {@code instance} parameter
+     */
+    static CodeBlock invokeAll(
+        ImmutableSet<InjectionSite> injectionSites,
+        ClassName generatedTypeName,
+        CodeBlock instanceCodeBlock,
+        TypeMirror instanceType,
+        DaggerTypes types,
+        Function<DependencyRequest, CodeBlock> dependencyUsage,
+        DaggerElements elements) {
+      return injectionSites
+          .stream()
+          .map(
+              injectionSite -> {
+                TypeMirror injectSiteType =
+                    types.erasure(injectionSite.element().getEnclosingElement().asType());
+
+                // If instance has been declared as Object because it is not accessible from the
+                // component, but the injectionSite is in a supertype of instanceType that is
+                // publicly accessible, the InjectionSiteMethod will request the actual type and not
+                // Object as the first parameter. If so, cast to the supertype which is accessible
+                // from within generatedTypeName
+                CodeBlock maybeCastedInstance =
+                    !types.isSubtype(instanceType, injectSiteType)
+                            && isTypeAccessibleFrom(injectSiteType, generatedTypeName.packageName())
+                        ? CodeBlock.of("($T) $L", injectSiteType, instanceCodeBlock)
+                        : instanceCodeBlock;
+                return CodeBlock.of(
+                    "$L;",
+                    invoke(
+                        injectionSite,
+                        generatedTypeName,
+                        maybeCastedInstance,
+                        dependencyUsage,
+                        elements));
+              })
+          .collect(toConcatenatedCodeBlock());
+    }
+
+    /**
+     * Invokes the injection method for {@code injectionSite}, with the dependencies transformed
+     * using the {@code dependencyUsage} function.
+     */
+    private static CodeBlock invoke(
+        InjectionSite injectionSite,
+        ClassName generatedTypeName,
+        CodeBlock instanceCodeBlock,
+        Function<DependencyRequest, CodeBlock> dependencyUsage,
+        DaggerElements elements) {
+      List<CodeBlock> arguments = new ArrayList<>();
+      arguments.add(instanceCodeBlock);
+      if (!injectionSite.dependencies().isEmpty()) {
+        arguments.addAll(
+            injectionSite
+                .dependencies()
+                .stream()
+                .map(dependencyUsage)
+                .collect(toList()));
+      }
+      return create(injectionSite, elements).invoke(arguments, generatedTypeName);
+    }
+
+    /*
+     * TODO(ronshapiro): this isn't perfect, as collisions could still exist. Some examples:
+     *
+     *  - @Inject void members() {} will generate a method that conflicts with the instance
+     *    method `injectMembers(T)`
+     *  - Adding the index could conflict with another member:
+     *      @Inject void a(Object o) {}
+     *      @Inject void a(String s) {}
+     *      @Inject void a1(String s) {}
+     *
+     *    Here, Method a(String) will add the suffix "1", which will conflict with the method
+     *    generated for a1(String)
+     *  - Members named "members" or "methods" could also conflict with the {@code static} injection
+     *    method.
+     */
+    private static String methodName(InjectionSite injectionSite) {
+      int index = injectionSite.indexAmongAtInjectMembersWithSameSimpleName();
+      String indexString = index == 0 ? "" : String.valueOf(index + 1);
+      return "inject"
+          + LOWER_CAMEL.to(UPPER_CAMEL, injectionSite.element().getSimpleName().toString())
+          + indexString;
+    }
+  }
+
+  /**
+   * Returns an argument list suitable for calling an injection method. Down-casts any arguments
+   * that are {@code Object} (or {@code Provider<Object>}) at the caller but not the method.
+   *
+   * @param dependencies the dependencies used by the method
+   * @param dependencyUsage function to apply on each of {@code dependencies} before casting
+   * @param requestingClass the class calling the injection method
+   */
+  private static ImmutableList<CodeBlock> injectionMethodArguments(
+      ImmutableSet<DependencyRequest> dependencies,
+      Function<DependencyRequest, CodeBlock> dependencyUsage,
+      ClassName requestingClass) {
+    return dependencies.stream()
+        .map(dep -> injectionMethodArgument(dep, dependencyUsage.apply(dep), requestingClass))
+        .collect(toImmutableList());
+  }
+
+  private static CodeBlock injectionMethodArgument(
+      DependencyRequest dependency, CodeBlock argument, ClassName generatedTypeName) {
+    TypeMirror keyType = dependency.key().type();
+    CodeBlock.Builder codeBlock = CodeBlock.builder();
+    if (!isRawTypeAccessible(keyType, generatedTypeName.packageName())
+        && isTypeAccessibleFrom(keyType, generatedTypeName.packageName())) {
+      if (!dependency.kind().equals(RequestKind.INSTANCE)) {
+        TypeName usageTypeName = accessibleType(dependency);
+        codeBlock.add("($T) ($T)", usageTypeName, rawTypeName(usageTypeName));
+      } else if (dependency.requestElement().get().asType().getKind().equals(TypeKind.TYPEVAR)) {
+        codeBlock.add("($T)", keyType);
+      }
+    }
+    return codeBlock.add(argument).build();
+  }
+
+  /**
+   * Returns the parameter type for {@code dependency}. If the raw type is not accessible, returns
+   * {@link Object}.
+   */
+  private static TypeName accessibleType(DependencyRequest dependency) {
+    TypeName typeName = requestTypeName(dependency.kind(), accessibleType(dependency.key().type()));
+    return dependency
+            .requestElement()
+            .map(element -> element.asType().getKind().isPrimitive())
+            .orElse(false)
+        ? typeName.unbox()
+        : typeName;
+  }
+
+  /**
+   * Returns the accessible type for {@code type}. If the raw type is not accessible, returns {@link
+   * Object}.
+   */
+  private static TypeName accessibleType(TypeMirror type) {
+    return isRawTypePubliclyAccessible(type) ? TypeName.get(type) : TypeName.OBJECT;
+  }
+
+  /**
+   * Returns the accessible type for {@code type}. If the raw type is not accessible, returns {@link
+   * Object}.
+   */
+  // TODO(ronshapiro): Can we use DaggerTypes.publiclyAccessibleType in place of this method?
+  private static TypeMirror accessibleType(TypeMirror type, DaggerElements elements) {
+    return isRawTypePubliclyAccessible(type)
+        ? type
+        : elements.getTypeElement(Object.class).asType();
+  }
+
+  private enum ReceiverAccessibility {
+    CAST_IF_NOT_PUBLIC {
+      @Override
+      TypeMirror parameterType(TypeMirror type, DaggerElements elements) {
+        return accessibleType(type, elements);
+      }
+
+      @Override
+      CodeBlock potentiallyCast(CodeBlock instance, TypeMirror instanceType) {
+        return instanceWithPotentialCast(instance, instanceType);
+      }
+    },
+    IGNORE {
+      @Override
+      TypeMirror parameterType(TypeMirror type, DaggerElements elements) {
+        return type;
+      }
+
+      @Override
+      CodeBlock potentiallyCast(CodeBlock instance, TypeMirror instanceType) {
+        return instance;
+      }
+    },
+    ;
+
+    abstract TypeMirror parameterType(TypeMirror type, DaggerElements elements);
+    abstract CodeBlock potentiallyCast(CodeBlock instance, TypeMirror instanceType);
+  }
+
+  private static CodeBlock instanceWithPotentialCast(CodeBlock instance, TypeMirror instanceType) {
+    return isRawTypePubliclyAccessible(instanceType)
+        ? instance
+        : CodeBlock.of("(($T) $L)", instanceType, instance);
+  }
+
+  private enum CheckNotNullPolicy {
+    IGNORE, CHECK_FOR_NULL;
+    CodeBlock checkForNull(CodeBlock maybeNull) {
+      if (this.equals(IGNORE)) {
+        return maybeNull;
+      }
+      return checkNotNullProvidesMethod(maybeNull);
+    }
+
+    static CheckNotNullPolicy get(ProvisionBinding binding, CompilerOptions compilerOptions) {
+      return binding.shouldCheckForNull(compilerOptions) ? CHECK_FOR_NULL : IGNORE;
+    }
+  }
+
+  private static InjectionMethod methodProxy(
+      ClassName proxyEnclosingClass,
+      ExecutableElement method,
+      String methodName,
+      ReceiverAccessibility receiverAccessibility,
+      CheckNotNullPolicy checkNotNullPolicy,
+      DaggerElements elements) {
+    TypeElement enclosingType = MoreElements.asType(method.getEnclosingElement());
+    InjectionMethod.Builder injectionMethod =
+        InjectionMethod.builder(elements).name(methodName).enclosingClass(proxyEnclosingClass);
+    ParameterSpec instance = null;
+    if (!method.getModifiers().contains(STATIC)) {
+      instance =
+          injectionMethod.addParameter(
+              "instance", receiverAccessibility.parameterType(enclosingType.asType(), elements));
+    }
+
+    CodeBlock arguments = injectionMethod.copyParameters(method);
+    if (!method.getReturnType().getKind().equals(VOID)) {
+      injectionMethod
+          .returnType(method.getReturnType())
+          .nullableAnnotation(getNullableType(method));
+      injectionMethod.methodBodyBuilder().add("return ");
+    }
+    CodeBlock.Builder proxyInvocation = CodeBlock.builder();
+    if (method.getModifiers().contains(STATIC)) {
+      proxyInvocation.add("$T", rawTypeName(TypeName.get(enclosingType.asType())));
+    } else {
+      injectionMethod.copyTypeParameters(enclosingType);
+      proxyInvocation.add(
+          receiverAccessibility.potentiallyCast(
+              CodeBlock.of("$N", instance), enclosingType.asType()));
+    }
+
+    injectionMethod
+        .copyTypeParameters(method)
+        .copyThrows(method);
+
+    proxyInvocation.add(".$N($L)", method.getSimpleName(), arguments);
+    injectionMethod
+        .methodBodyBuilder()
+        .add(checkNotNullPolicy.checkForNull(proxyInvocation.build()))
+        .add(";\n");
+    return injectionMethod.build();
+  }
+
+  private static InjectionMethod fieldProxy(
+      ClassName proxyEnclosingClass,
+      VariableElement field,
+      String methodName,
+      DaggerElements elements) {
+    TypeElement enclosingType = MoreElements.asType(field.getEnclosingElement());
+    InjectionMethod.Builder injectionMethod =
+        InjectionMethod.builder(elements).name(methodName).enclosingClass(proxyEnclosingClass);
+    injectionMethod.copyTypeParameters(enclosingType);
+
+    ParameterSpec instance =
+        injectionMethod.addParameter("instance", accessibleType(enclosingType.asType(), elements));
+    CodeBlock parameter = injectionMethod.copyParameter(field);
+    injectionMethod
+        .methodBodyBuilder()
+        .addStatement(
+            "$L.$L = $L",
+            instanceWithPotentialCast(CodeBlock.of("$N", instance), enclosingType.asType()),
+            field.getSimpleName(),
+            parameter);
+    return injectionMethod.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java b/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java
new file mode 100644
index 0000000..2d2e8cb
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java
@@ -0,0 +1,63 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+import static dagger.model.BindingKind.INJECTION;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import javax.inject.Provider;
+
+/**
+ * A {@link Provider} creation expression for an {@link javax.inject.Inject @Inject}-constructed
+ * class or a {@link dagger.Provides @Provides}-annotated module method.
+ */
+// TODO(dpb): Resolve with ProducerCreationExpression.
+final class InjectionOrProvisionProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final ContributionBinding binding;
+  private final ComponentBindingExpressions componentBindingExpressions;
+
+  InjectionOrProvisionProviderCreationExpression(
+      ContributionBinding binding, ComponentBindingExpressions componentBindingExpressions) {
+    this.binding = checkNotNull(binding);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    CodeBlock createFactory =
+        CodeBlock.of(
+            "$T.create($L)",
+            generatedClassNameForBinding(binding),
+            componentBindingExpressions.getCreateMethodArgumentsCodeBlock(binding));
+
+    // When scoping a parameterized factory for an @Inject class, Java 7 cannot always infer the
+    // type properly, so cast to a raw framework type before scoping.
+    if (binding.kind().equals(INJECTION)
+        && binding.unresolved().isPresent()
+        && binding.scope().isPresent()) {
+      return CodeBlocks.cast(createFactory, Provider.class);
+    } else {
+      return createFactory;
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/InjectionSiteFactory.java b/java/dagger/internal/codegen/InjectionSiteFactory.java
new file mode 100644
index 0000000..d09f91d
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectionSiteFactory.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2017 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.MoreElements.isAnnotationPresent;
+import static dagger.internal.codegen.MembersInjectionBinding.InjectionSite.Kind.METHOD;
+import static dagger.internal.codegen.langmodel.DaggerElements.DECLARATION_ORDER;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.SetMultimap;
+import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementKindVisitor8;
+
+/** A factory for {@link Binding} objects. */
+final class InjectionSiteFactory {
+  private final ElementVisitor<Optional<InjectionSite>, DeclaredType> injectionSiteVisitor =
+      new ElementKindVisitor8<Optional<InjectionSite>, DeclaredType>(Optional.empty()) {
+        @Override
+        public Optional<InjectionSite> visitExecutableAsMethod(
+            ExecutableElement method, DeclaredType type) {
+          ExecutableType resolved = MoreTypes.asExecutable(types.asMemberOf(type, method));
+          return Optional.of(
+              InjectionSite.method(
+                  method,
+                  dependencyRequestFactory.forRequiredResolvedVariables(
+                      method.getParameters(), resolved.getParameterTypes())));
+        }
+
+        @Override
+        public Optional<InjectionSite> visitVariableAsField(
+            VariableElement field, DeclaredType type) {
+          if (!isAnnotationPresent(field, Inject.class)
+              || field.getModifiers().contains(PRIVATE)
+              || field.getModifiers().contains(STATIC)) {
+            return Optional.empty();
+          }
+          TypeMirror resolved = types.asMemberOf(type, field);
+          return Optional.of(
+              InjectionSite.field(
+                  field, dependencyRequestFactory.forRequiredResolvedVariable(field, resolved)));
+        }
+      };
+
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+  private final DependencyRequestFactory dependencyRequestFactory;
+
+  @Inject
+  InjectionSiteFactory(
+      DaggerTypes types,
+      DaggerElements elements,
+      DependencyRequestFactory dependencyRequestFactory) {
+    this.types = types;
+    this.elements = elements;
+    this.dependencyRequestFactory = dependencyRequestFactory;
+  }
+
+  /** Returns the injection sites for a type. */
+  ImmutableSortedSet<InjectionSite> getInjectionSites(DeclaredType declaredType) {
+    Set<InjectionSite> injectionSites = new HashSet<>();
+    List<TypeElement> ancestors = new ArrayList<>();
+    SetMultimap<String, ExecutableElement> overriddenMethodMap = LinkedHashMultimap.create();
+    for (Optional<DeclaredType> currentType = Optional.of(declaredType);
+        currentType.isPresent();
+        currentType = types.nonObjectSuperclass(currentType.get())) {
+      DeclaredType type = currentType.get();
+      ancestors.add(MoreElements.asType(type.asElement()));
+      for (Element enclosedElement : type.asElement().getEnclosedElements()) {
+        Optional<InjectionSite> maybeInjectionSite =
+            injectionSiteVisitor.visit(enclosedElement, type);
+        if (maybeInjectionSite.isPresent()) {
+          InjectionSite injectionSite = maybeInjectionSite.get();
+          if (shouldBeInjected(injectionSite.element(), overriddenMethodMap)) {
+            injectionSites.add(injectionSite);
+          }
+          if (injectionSite.kind().equals(METHOD)) {
+            ExecutableElement injectionSiteMethod =
+                MoreElements.asExecutable(injectionSite.element());
+            overriddenMethodMap.put(
+                injectionSiteMethod.getSimpleName().toString(), injectionSiteMethod);
+          }
+        }
+      }
+    }
+    return ImmutableSortedSet.copyOf(
+        // supertypes before subtypes
+        Comparator.comparing(
+                (InjectionSite injectionSite) ->
+                    ancestors.indexOf(injectionSite.element().getEnclosingElement()))
+            .reversed()
+            // fields before methods
+            .thenComparing(injectionSite -> injectionSite.element().getKind())
+            // then sort by whichever element comes first in the parent
+            // this isn't necessary, but makes the processor nice and predictable
+            .thenComparing(InjectionSite::element, DECLARATION_ORDER),
+        injectionSites);
+  }
+
+  private boolean shouldBeInjected(
+      Element injectionSite, SetMultimap<String, ExecutableElement> overriddenMethodMap) {
+    if (!isAnnotationPresent(injectionSite, Inject.class)
+        || injectionSite.getModifiers().contains(PRIVATE)
+        || injectionSite.getModifiers().contains(STATIC)) {
+      return false;
+    }
+
+    if (injectionSite.getKind().isField()) { // Inject all fields (self and ancestors)
+      return true;
+    }
+
+    // For each method with the same name belonging to any descendant class, return false if any
+    // method has already overridden the injectionSite method. To decrease the number of methods
+    // that are checked, we store the already injected methods in a SetMultimap and only
+    // check the methods with the same name.
+    ExecutableElement injectionSiteMethod = MoreElements.asExecutable(injectionSite);
+    TypeElement injectionSiteType = MoreElements.asType(injectionSite.getEnclosingElement());
+    for (ExecutableElement method :
+        overriddenMethodMap.get(injectionSiteMethod.getSimpleName().toString())) {
+      if (elements.overrides(method, injectionSiteMethod, injectionSiteType)) {
+        return false;
+      }
+    }
+    return true;
+  }
+}
diff --git a/java/dagger/internal/codegen/InnerSwitchingProviders.java b/java/dagger/internal/codegen/InnerSwitchingProviders.java
new file mode 100644
index 0000000..74c4366
--- /dev/null
+++ b/java/dagger/internal/codegen/InnerSwitchingProviders.java
@@ -0,0 +1,106 @@
+/*
+ * 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.squareup.javapoet.MethodSpec.constructorBuilder;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.model.RequestKind.INSTANCE;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import javax.inject.Provider;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Generates {@linkplain BindingExpression binding expressions} for a binding that is represented by
+ * an inner {@code SwitchingProvider} class.
+ */
+final class InnerSwitchingProviders extends SwitchingProviders {
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final DaggerTypes types;
+
+  InnerSwitchingProviders(
+      ComponentImplementation componentImplementation,
+      ComponentBindingExpressions componentBindingExpressions,
+      DaggerTypes types) {
+    super(componentImplementation, types);
+    this.componentBindingExpressions = componentBindingExpressions;
+    this.types = types;
+  }
+
+  /**
+   * Returns the binding expression for a binding that satisfies a {@link Provider} requests with a
+   * inner {@code SwitchingProvider} class.
+   */
+  BindingExpression newBindingExpression(ContributionBinding binding) {
+    return new BindingExpression() {
+      @Override
+      Expression getDependencyExpression(ClassName requestingClass) {
+        return getProviderExpression(new SwitchCase(binding, requestingClass));
+      }
+    };
+  }
+
+  @Override
+  protected TypeSpec createSwitchingProviderType(TypeSpec.Builder builder) {
+    return builder
+        .addModifiers(PRIVATE, FINAL)
+        .addField(TypeName.INT, "id", PRIVATE, FINAL)
+        .addMethod(
+            constructorBuilder()
+                .addParameter(TypeName.INT, "id")
+                .addStatement("this.id = id")
+                .build())
+        .build();
+  }
+
+  private final class SwitchCase implements SwitchingProviders.SwitchCase {
+    private final ContributionBinding binding;
+    private final ClassName requestingClass;
+
+    SwitchCase(ContributionBinding binding, ClassName requestingClass) {
+      this.binding = binding;
+      this.requestingClass = requestingClass;
+    }
+
+    @Override
+    public Key key() {
+      return binding.key();
+    }
+
+    @Override
+    public Expression getProviderExpression(ClassName switchingProviderClass, int switchId) {
+      TypeMirror instanceType = types.accessibleType(binding.contributedType(), requestingClass);
+      return Expression.create(
+          types.wrapType(instanceType, Provider.class),
+          CodeBlock.of("new $T<>($L)", switchingProviderClass, switchId));
+    }
+
+    @Override
+    public Expression getReturnExpression(ClassName switchingProviderClass) {
+      return componentBindingExpressions.getDependencyExpression(
+          bindingRequest(binding.key(), INSTANCE), switchingProviderClass);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/InstanceFactoryCreationExpression.java b/java/dagger/internal/codegen/InstanceFactoryCreationExpression.java
new file mode 100644
index 0000000..c9b26d7
--- /dev/null
+++ b/java/dagger/internal/codegen/InstanceFactoryCreationExpression.java
@@ -0,0 +1,57 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.InstanceFactory;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import java.util.function.Supplier;
+
+/**
+ * A {@link FrameworkInstanceCreationExpression} that creates an {@link InstanceFactory} for an
+ * instance.
+ */
+final class InstanceFactoryCreationExpression implements FrameworkInstanceCreationExpression {
+
+  private final boolean nullable;
+  private final Supplier<CodeBlock> instanceExpression;
+
+  InstanceFactoryCreationExpression(Supplier<CodeBlock> instanceExpression) {
+    this(false, instanceExpression);
+  }
+
+  InstanceFactoryCreationExpression(boolean nullable, Supplier<CodeBlock> instanceExpression) {
+    this.nullable = nullable;
+    this.instanceExpression = checkNotNull(instanceExpression);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    return CodeBlock.of(
+        "$T.$L($L)",
+        InstanceFactory.class,
+        nullable ? "createNullable" : "create",
+        instanceExpression.get());
+  }
+
+  @Override
+  public boolean useInnerSwitchingProvider() {
+    return false;
+  }
+}
diff --git a/java/dagger/internal/codegen/JavacPluginModule.java b/java/dagger/internal/codegen/JavacPluginModule.java
new file mode 100644
index 0000000..bc5b66e
--- /dev/null
+++ b/java/dagger/internal/codegen/JavacPluginModule.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2017 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 dagger.internal.codegen.ValidationType.NONE;
+import static javax.tools.Diagnostic.Kind.NOTE;
+
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.util.Context;
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import javax.annotation.processing.Messager;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Types;
+import javax.tools.Diagnostic;
+
+/**
+ * A module that provides a {@link BindingGraphFactory} and {@link ComponentDescriptorFactory} for
+ * use in {@code javac} plugins. Requires a binding for the {@code javac} {@link Context}.
+ */
+@Module(includes = InjectBindingRegistryModule.class)
+abstract class JavacPluginModule {
+  @Provides
+  static CompilerOptions compilerOptions() {
+    return new CompilerOptions() {
+      @Override
+      boolean usesProducers() {
+        return true;
+      }
+
+      @Override
+      boolean fastInit() {
+        return false;
+      }
+
+      @Override
+      boolean formatGeneratedSource() {
+        return false;
+      }
+
+      @Override
+      boolean writeProducerNameInToken() {
+        return true;
+      }
+
+      @Override
+      Diagnostic.Kind nullableValidationKind() {
+        return NOTE;
+      }
+
+      @Override
+      Diagnostic.Kind privateMemberValidationKind() {
+        return NOTE;
+      }
+
+      @Override
+      Diagnostic.Kind staticMemberValidationKind() {
+        return NOTE;
+      }
+
+      @Override
+      boolean ignorePrivateAndStaticInjectionForComponent() {
+        return false;
+      }
+
+      @Override
+      ValidationType scopeCycleValidationType() {
+        return NONE;
+      }
+
+      @Override
+      boolean warnIfInjectionFactoryNotGeneratedUpstream() {
+        return false;
+      }
+
+      @Override
+      boolean headerCompilation() {
+        return false;
+      }
+
+      @Override
+      boolean aheadOfTimeSubcomponents() {
+        return false;
+      }
+
+      @Override
+      boolean forceUseSerializedComponentImplementations() {
+        return false;
+      }
+
+      @Override
+      boolean emitModifiableMetadataAnnotations() {
+        return false;
+      }
+
+      @Override
+      boolean useGradleIncrementalProcessing() {
+        return false;
+      }
+
+      @Override
+      ValidationType fullBindingGraphValidationType(TypeElement element) {
+        return NONE;
+      }
+
+      @Override
+      Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind() {
+        return NOTE;
+      }
+
+      @Override
+      ValidationType explicitBindingConflictsWithInjectValidationType() {
+        return NONE;
+      }
+    };
+  }
+
+  @Binds
+  abstract Messager messager(NullMessager nullMessager);
+
+  static final class NullMessager implements Messager {
+
+    @Inject
+    NullMessager() {}
+
+    @Override
+    public void printMessage(Diagnostic.Kind kind, CharSequence charSequence) {}
+
+    @Override
+    public void printMessage(Diagnostic.Kind kind, CharSequence charSequence, Element element) {}
+
+    @Override
+    public void printMessage(
+        Diagnostic.Kind kind,
+        CharSequence charSequence,
+        Element element,
+        AnnotationMirror annotationMirror) {}
+
+    @Override
+    public void printMessage(
+        Diagnostic.Kind kind,
+        CharSequence charSequence,
+        Element element,
+        AnnotationMirror annotationMirror,
+        AnnotationValue annotationValue) {}
+  }
+
+  @Provides
+  static DaggerElements daggerElements(Context javaContext) {
+    return new DaggerElements(
+        JavacElements.instance(javaContext), JavacTypes.instance(javaContext));
+  }
+
+  @Provides
+  static DaggerTypes daggerTypes(Context javaContext, DaggerElements elements) {
+    return new DaggerTypes(JavacTypes.instance(javaContext), elements);
+  }
+
+  @Binds abstract Types types(DaggerTypes daggerTypes);
+
+  private JavacPluginModule() {}
+}
diff --git a/java/dagger/internal/codegen/KeyFactory.java b/java/dagger/internal/codegen/KeyFactory.java
new file mode 100644
index 0000000..b6ac27f
--- /dev/null
+++ b/java/dagger/internal/codegen/KeyFactory.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2014 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.MoreElements.isAnnotationPresent;
+import static com.google.auto.common.MoreTypes.asExecutable;
+import static com.google.auto.common.MoreTypes.isType;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifier;
+import static dagger.internal.codegen.MapKeys.getMapKey;
+import static dagger.internal.codegen.MapKeys.mapKeyType;
+import static dagger.internal.codegen.Optionals.firstPresent;
+import static dagger.internal.codegen.RequestKinds.extractKeyType;
+import static dagger.internal.codegen.RequestKinds.getRequestKind;
+import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
+import static java.util.Arrays.asList;
+import static javax.lang.model.element.ElementKind.METHOD;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import dagger.Binds;
+import dagger.BindsOptionalOf;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.KeyProto;
+import dagger.model.Key;
+import dagger.model.Key.MultibindingContributionIdentifier;
+import dagger.model.RequestKind;
+import dagger.multibindings.Multibinds;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import dagger.producers.Production;
+import dagger.producers.internal.ProductionImplementation;
+import dagger.producers.monitoring.ProductionComponentMonitor;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.stream.Stream;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeMirror;
+
+/** A factory for {@link Key}s. */
+final class KeyFactory {
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+  private final TypeProtoConverter typeProtoConverter;
+  private final AnnotationProtoConverter annotationProtoConverter;
+
+  @Inject
+  KeyFactory(
+      DaggerTypes types,
+      DaggerElements elements,
+      TypeProtoConverter typeProtoConverter,
+      AnnotationProtoConverter annotationProtoConverter) {
+    this.types = checkNotNull(types);
+    this.elements = checkNotNull(elements);
+    this.typeProtoConverter = typeProtoConverter;
+    this.annotationProtoConverter = annotationProtoConverter;
+  }
+
+  private TypeMirror boxPrimitives(TypeMirror type) {
+    return type.getKind().isPrimitive() ? types.boxedClass((PrimitiveType) type).asType() : type;
+  }
+
+  private DeclaredType setOf(TypeMirror elementType) {
+    return types.getDeclaredType(elements.getTypeElement(Set.class), boxPrimitives(elementType));
+  }
+
+  private DeclaredType mapOf(TypeMirror keyType, TypeMirror valueType) {
+    return types.getDeclaredType(
+        elements.getTypeElement(Map.class), boxPrimitives(keyType), boxPrimitives(valueType));
+  }
+
+  /** Returns {@code Map<KeyType, FrameworkType<ValueType>>}. */
+  private TypeMirror mapOfFrameworkType(
+      TypeMirror keyType, TypeElement frameworkType, TypeMirror valueType) {
+    return mapOf(keyType, types.getDeclaredType(frameworkType, boxPrimitives(valueType)));
+  }
+
+  Key forComponentMethod(ExecutableElement componentMethod) {
+    checkArgument(componentMethod.getKind().equals(METHOD));
+    return forMethod(componentMethod, componentMethod.getReturnType());
+  }
+
+  Key forProductionComponentMethod(ExecutableElement componentMethod) {
+    checkArgument(componentMethod.getKind().equals(METHOD));
+    TypeMirror returnType = componentMethod.getReturnType();
+    TypeMirror keyType =
+        isFutureType(returnType)
+            ? getOnlyElement(MoreTypes.asDeclared(returnType).getTypeArguments())
+            : returnType;
+    return forMethod(componentMethod, keyType);
+  }
+
+  Key forSubcomponentCreatorMethod(
+      ExecutableElement subcomponentCreatorMethod, DeclaredType declaredContainer) {
+    checkArgument(subcomponentCreatorMethod.getKind().equals(METHOD));
+    ExecutableType resolvedMethod =
+        asExecutable(types.asMemberOf(declaredContainer, subcomponentCreatorMethod));
+    return Key.builder(resolvedMethod.getReturnType()).build();
+  }
+
+  Key forSubcomponentCreator(TypeMirror creatorType) {
+    return Key.builder(creatorType).build();
+  }
+
+  Key forProvidesMethod(ExecutableElement method, TypeElement contributingModule) {
+    return forBindingMethod(
+        method, contributingModule, Optional.of(elements.getTypeElement(Provider.class)));
+  }
+
+  Key forProducesMethod(ExecutableElement method, TypeElement contributingModule) {
+    return forBindingMethod(
+        method, contributingModule, Optional.of(elements.getTypeElement(Producer.class)));
+  }
+
+  /** Returns the key bound by a {@link Binds} method. */
+  Key forBindsMethod(ExecutableElement method, TypeElement contributingModule) {
+    checkArgument(isAnnotationPresent(method, Binds.class));
+    return forBindingMethod(method, contributingModule, Optional.empty());
+  }
+
+  /** Returns the base key bound by a {@link BindsOptionalOf} method. */
+  Key forBindsOptionalOfMethod(ExecutableElement method, TypeElement contributingModule) {
+    checkArgument(isAnnotationPresent(method, BindsOptionalOf.class));
+    return forBindingMethod(method, contributingModule, Optional.empty());
+  }
+
+  private Key forBindingMethod(
+      ExecutableElement method,
+      TypeElement contributingModule,
+      Optional<TypeElement> frameworkType) {
+    checkArgument(method.getKind().equals(METHOD));
+    ExecutableType methodType =
+        MoreTypes.asExecutable(
+            types.asMemberOf(MoreTypes.asDeclared(contributingModule.asType()), method));
+    ContributionType contributionType = ContributionType.fromBindingElement(method);
+    TypeMirror returnType = methodType.getReturnType();
+    if (frameworkType.isPresent()
+        && frameworkType.get().equals(elements.getTypeElement(Producer.class))
+        && isType(returnType)) {
+      if (isFutureType(methodType.getReturnType())) {
+        returnType = getOnlyElement(MoreTypes.asDeclared(returnType).getTypeArguments());
+      } else if (contributionType.equals(ContributionType.SET_VALUES)
+          && SetType.isSet(returnType)) {
+        SetType setType = SetType.from(returnType);
+        if (isFutureType(setType.elementType())) {
+          returnType =
+              types.getDeclaredType(
+                  elements.getTypeElement(Set.class), types.unwrapType(setType.elementType()));
+        }
+      }
+    }
+    TypeMirror keyType = bindingMethodKeyType(returnType, method, contributionType, frameworkType);
+    Key key = forMethod(method, keyType);
+    return contributionType.equals(ContributionType.UNIQUE)
+        ? key
+        : key.toBuilder()
+            .multibindingContributionIdentifier(
+                new MultibindingContributionIdentifier(method, contributingModule))
+            .build();
+  }
+
+  /**
+   * Returns the key for a {@link Multibinds @Multibinds} method.
+   *
+   * <p>The key's type is either {@code Set<T>} or {@code Map<K, Provider<V>>}. The latter works
+   * even for maps used by {@code Producer}s.
+   */
+  Key forMultibindsMethod(ExecutableType executableType, ExecutableElement method) {
+    checkArgument(method.getKind().equals(METHOD), "%s must be a method", method);
+    TypeMirror returnType = executableType.getReturnType();
+    TypeMirror keyType =
+        MapType.isMap(returnType)
+            ? mapOfFrameworkType(
+                MapType.from(returnType).keyType(),
+                elements.getTypeElement(Provider.class),
+                MapType.from(returnType).valueType())
+            : returnType;
+    return forMethod(method, keyType);
+  }
+
+  private TypeMirror bindingMethodKeyType(
+      TypeMirror returnType,
+      ExecutableElement method,
+      ContributionType contributionType,
+      Optional<TypeElement> frameworkType) {
+    switch (contributionType) {
+      case UNIQUE:
+        return returnType;
+      case SET:
+        return setOf(returnType);
+      case MAP:
+        TypeMirror mapKeyType = mapKeyType(getMapKey(method).get(), types);
+        return frameworkType.isPresent()
+            ? mapOfFrameworkType(mapKeyType, frameworkType.get(), returnType)
+            : mapOf(mapKeyType, returnType);
+      case SET_VALUES:
+        // TODO(gak): do we want to allow people to use "covariant return" here?
+        checkArgument(SetType.isSet(returnType));
+        return returnType;
+    }
+    throw new AssertionError();
+  }
+
+  /**
+   * Returns the key for a binding associated with a {@link DelegateDeclaration}.
+   *
+   * <p>If {@code delegateDeclaration} is {@code @IntoMap}, transforms the {@code Map<K, V>} key
+   * from {@link DelegateDeclaration#key()} to {@code Map<K, FrameworkType<V>>}. If {@code
+   * delegateDeclaration} is not a map contribution, its key is returned.
+   */
+  Key forDelegateBinding(DelegateDeclaration delegateDeclaration, Class<?> frameworkType) {
+    return delegateDeclaration.contributionType().equals(ContributionType.MAP)
+        ? wrapMapValue(delegateDeclaration.key(), frameworkType)
+        : delegateDeclaration.key();
+  }
+
+  private Key forMethod(ExecutableElement method, TypeMirror keyType) {
+    return forQualifiedType(getQualifier(method), keyType);
+  }
+
+  Key forInjectConstructorWithResolvedType(TypeMirror type) {
+    return Key.builder(type).build();
+  }
+
+  // TODO(ronshapiro): Remove these conveniences which are simple wrappers around Key.Builder
+  Key forType(TypeMirror type) {
+    return Key.builder(type).build();
+  }
+
+  Key forMembersInjectedType(TypeMirror type) {
+    return Key.builder(type).build();
+  }
+
+  Key forQualifiedType(Optional<AnnotationMirror> qualifier, TypeMirror type) {
+    return Key.builder(boxPrimitives(type)).qualifier(qualifier).build();
+  }
+
+  Key forProductionExecutor() {
+    return Key.builder(elements.getTypeElement(Executor.class).asType())
+        .qualifier(SimpleAnnotationMirror.of(elements.getTypeElement(Production.class)))
+        .build();
+  }
+
+  Key forProductionImplementationExecutor() {
+    return Key.builder(elements.getTypeElement(Executor.class).asType())
+        .qualifier(SimpleAnnotationMirror.of(elements.getTypeElement(ProductionImplementation.class)))
+        .build();
+  }
+
+  Key forProductionComponentMonitor() {
+    return Key.builder(elements.getTypeElement(ProductionComponentMonitor.class).asType()).build();
+  }
+
+  /**
+   * If {@code requestKey} is for a {@code Map<K, V>} or {@code Map<K, Produced<V>>}, returns keys
+   * for {@code Map<K, Provider<V>>} and {@code Map<K, Producer<V>>} (if Dagger-Producers is on
+   * the classpath).
+   */
+  ImmutableSet<Key> implicitFrameworkMapKeys(Key requestKey) {
+    return Stream.of(implicitMapProviderKeyFrom(requestKey), implicitMapProducerKeyFrom(requestKey))
+        .filter(Optional::isPresent)
+        .map(Optional::get)
+        .collect(toImmutableSet());
+  }
+
+  /**
+   * Optionally extract a {@link Key} for the underlying provision binding(s) if such a valid key
+   * can be inferred from the given key. Specifically, if the key represents a {@link Map}{@code
+   * <K, V>} or {@code Map<K, Producer<V>>}, a key of {@code Map<K, Provider<V>>} will be
+   * returned.
+   */
+  Optional<Key> implicitMapProviderKeyFrom(Key possibleMapKey) {
+    return firstPresent(
+        rewrapMapKey(possibleMapKey, Produced.class, Provider.class),
+        wrapMapKey(possibleMapKey, Provider.class));
+  }
+
+  /**
+   * Optionally extract a {@link Key} for the underlying production binding(s) if such a
+   * valid key can be inferred from the given key.  Specifically, if the key represents a
+   * {@link Map}{@code <K, V>} or {@code Map<K, Produced<V>>}, a key of
+   * {@code Map<K, Producer<V>>} will be returned.
+   */
+  Optional<Key> implicitMapProducerKeyFrom(Key possibleMapKey) {
+    return firstPresent(
+        rewrapMapKey(possibleMapKey, Produced.class, Producer.class),
+        wrapMapKey(possibleMapKey, Producer.class));
+  }
+
+  /**
+   * If {@code key}'s type is {@code Map<K, Provider<V>>}, {@code Map<K, Producer<V>>}, or {@code
+   * Map<K, Produced<V>>}, returns a key with the same qualifier and {@link
+   * Key#multibindingContributionIdentifier()} whose type is simply {@code Map<K, V>}.
+   *
+   * <p>Otherwise, returns {@code key}.
+   */
+  Key unwrapMapValueType(Key key) {
+    if (MapType.isMap(key)) {
+      MapType mapType = MapType.from(key);
+      if (!mapType.isRawType()) {
+        for (Class<?> frameworkClass : asList(Provider.class, Producer.class, Produced.class)) {
+          if (mapType.valuesAreTypeOf(frameworkClass)) {
+            return key.toBuilder()
+                .type(mapOf(mapType.keyType(), mapType.unwrappedValueType(frameworkClass)))
+                .build();
+          }
+        }
+      }
+    }
+    return key;
+  }
+
+  /**
+   * Converts a {@link Key} of type {@code Map<K, V>} to {@code Map<K, Provider<V>>}.
+   */
+  private Key wrapMapValue(Key key, Class<?> newWrappingClass) {
+    checkArgument(
+        FrameworkTypes.isFrameworkType(elements.getTypeElement(newWrappingClass).asType()));
+    return wrapMapKey(key, newWrappingClass).get();
+  }
+
+  /**
+   * If {@code key}'s type is {@code Map<K, CurrentWrappingClass<Bar>>}, returns a key with type
+   * {@code Map<K, NewWrappingClass<Bar>>} with the same qualifier. Otherwise returns {@link
+   * Optional#empty()}.
+   *
+   * <p>Returns {@link Optional#empty()} if {@code newWrappingClass} is not in the classpath.
+   *
+   * @throws IllegalArgumentException if {@code newWrappingClass} is the same as {@code
+   *     currentWrappingClass}
+   */
+  Optional<Key> rewrapMapKey(
+      Key possibleMapKey, Class<?> currentWrappingClass, Class<?> newWrappingClass) {
+    checkArgument(!currentWrappingClass.equals(newWrappingClass));
+    if (MapType.isMap(possibleMapKey)) {
+      MapType mapType = MapType.from(possibleMapKey);
+      if (!mapType.isRawType() && mapType.valuesAreTypeOf(currentWrappingClass)) {
+        TypeElement wrappingElement = elements.getTypeElement(newWrappingClass);
+        if (wrappingElement == null) {
+          // This target might not be compiled with Producers, so wrappingClass might not have an
+          // associated element.
+          return Optional.empty();
+        }
+        DeclaredType wrappedValueType =
+            types.getDeclaredType(
+                wrappingElement, mapType.unwrappedValueType(currentWrappingClass));
+        return Optional.of(
+            possibleMapKey.toBuilder().type(mapOf(mapType.keyType(), wrappedValueType)).build());
+      }
+    }
+    return Optional.empty();
+  }
+
+  /**
+   * If {@code key}'s type is {@code Map<K, Foo>} and {@code Foo} is not {@code WrappingClass
+   * <Bar>}, returns a key with type {@code Map<K, WrappingClass<Foo>>} with the same qualifier.
+   * Otherwise returns {@link Optional#empty()}.
+   *
+   * <p>Returns {@link Optional#empty()} if {@code WrappingClass} is not in the classpath.
+   */
+  private Optional<Key> wrapMapKey(Key possibleMapKey, Class<?> wrappingClass) {
+    if (MapType.isMap(possibleMapKey)) {
+      MapType mapType = MapType.from(possibleMapKey);
+      if (!mapType.isRawType() && !mapType.valuesAreTypeOf(wrappingClass)) {
+        TypeElement wrappingElement = elements.getTypeElement(wrappingClass);
+        if (wrappingElement == null) {
+          // This target might not be compiled with Producers, so wrappingClass might not have an
+          // associated element.
+          return Optional.empty();
+        }
+        DeclaredType wrappedValueType = types.getDeclaredType(wrappingElement, mapType.valueType());
+        return Optional.of(
+            possibleMapKey.toBuilder().type(mapOf(mapType.keyType(), wrappedValueType)).build());
+      }
+    }
+    return Optional.empty();
+  }
+
+  /**
+   * If {@code key}'s type is {@code Set<WrappingClass<Bar>>}, returns a key with type {@code Set
+   * <Bar>} with the same qualifier. Otherwise returns {@link Optional#empty()}.
+   */
+  Optional<Key> unwrapSetKey(Key key, Class<?> wrappingClass) {
+    if (SetType.isSet(key)) {
+      SetType setType = SetType.from(key);
+      if (!setType.isRawType() && setType.elementsAreTypeOf(wrappingClass)) {
+        return Optional.of(
+            key.toBuilder().type(setOf(setType.unwrappedElementType(wrappingClass))).build());
+      }
+    }
+    return Optional.empty();
+  }
+
+  /**
+   * If {@code key}'s type is {@code Optional<T>} for some {@code T}, returns a key with the same
+   * qualifier whose type is {@linkplain RequestKinds#extractKeyType(RequestKind, TypeMirror)}
+   * extracted} from {@code T}.
+   */
+  Optional<Key> unwrapOptional(Key key) {
+    if (!OptionalType.isOptional(key)) {
+      return Optional.empty();
+    }
+
+    TypeMirror optionalValueType = OptionalType.from(key).valueType();
+    return Optional.of(
+        key.toBuilder()
+            .type(extractKeyType(getRequestKind(optionalValueType), optionalValueType))
+            .build());
+  }
+
+  /** Translates a {@link Key} to a proto representation. */
+  static KeyProto toProto(Key key) {
+    KeyProto.Builder builder =
+        KeyProto.newBuilder().setType(TypeProtoConverter.toProto(key.type()));
+    key.qualifier().map(AnnotationProtoConverter::toProto).ifPresent(builder::setQualifier);
+    key.multibindingContributionIdentifier()
+        .ifPresent(
+            mci ->
+                builder
+                    .getMultibindingContributionIdentifierBuilder()
+                    .setModule(mci.module())
+                    .setBindingElement(mci.bindingElement()));
+    return builder.build();
+  }
+
+  /** Creates a {@link Key} from its proto representation. */
+  Key fromProto(KeyProto key) {
+    Key.Builder builder = Key.builder(typeProtoConverter.fromProto(key.getType()));
+    if (key.hasQualifier()) {
+      builder.qualifier(annotationProtoConverter.fromProto(key.getQualifier()));
+    }
+    if (key.hasMultibindingContributionIdentifier()) {
+      KeyProto.MultibindingContributionIdentifier multibindingContributionIdentifier =
+          key.getMultibindingContributionIdentifier();
+      builder.multibindingContributionIdentifier(
+          new MultibindingContributionIdentifier(
+              multibindingContributionIdentifier.getBindingElement(),
+              multibindingContributionIdentifier.getModule()));
+    }
+    return builder.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/KeyVariableNamer.java b/java/dagger/internal/codegen/KeyVariableNamer.java
new file mode 100644
index 0000000..407f208
--- /dev/null
+++ b/java/dagger/internal/codegen/KeyVariableNamer.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2014 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.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static dagger.internal.codegen.SourceFiles.protectAgainstKeywords;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import java.util.Iterator;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVisitor;
+import javax.lang.model.util.SimpleTypeVisitor8;
+
+/**
+ * Suggests a variable name for a type based on a {@link Key}. Prefer {@link
+ * DependencyVariableNamer} for cases where a specific {@link DependencyRequest} is present.
+ */
+final class KeyVariableNamer {
+  /** Simple names that are very common. Inspired by https://errorprone.info/bugpattern/BadImport */
+  private static final ImmutableSet<String> VERY_SIMPLE_NAMES =
+      ImmutableSet.of(
+          "Builder",
+          "Factory",
+          "Component",
+          "Subcomponent",
+          "Injector");
+
+  private static final TypeVisitor<Void, StringBuilder> TYPE_NAMER =
+      new SimpleTypeVisitor8<Void, StringBuilder>() {
+        @Override
+        public Void visitDeclared(DeclaredType declaredType, StringBuilder builder) {
+          TypeElement element = MoreTypes.asTypeElement(declaredType);
+          if (element.getNestingKind().isNested()
+              && VERY_SIMPLE_NAMES.contains(element.getSimpleName().toString())) {
+            builder.append(element.getEnclosingElement().getSimpleName());
+          }
+
+          builder.append(element.getSimpleName());
+          Iterator<? extends TypeMirror> argumentIterator =
+              declaredType.getTypeArguments().iterator();
+          if (argumentIterator.hasNext()) {
+            builder.append("Of");
+            TypeMirror first = argumentIterator.next();
+            first.accept(this, builder);
+            while (argumentIterator.hasNext()) {
+              builder.append("And");
+              argumentIterator.next().accept(this, builder);
+            }
+          }
+          return null;
+        }
+
+        @Override
+        public Void visitPrimitive(PrimitiveType type, StringBuilder builder) {
+          builder.append(LOWER_CAMEL.to(UPPER_CAMEL, type.toString()));
+          return null;
+        }
+
+        @Override
+        public Void visitArray(ArrayType type, StringBuilder builder) {
+          type.getComponentType().accept(this, builder);
+          builder.append("Array");
+          return null;
+        }
+      };
+
+  private KeyVariableNamer() {}
+
+  static String name(Key key) {
+    if (key.multibindingContributionIdentifier().isPresent()) {
+      return key.multibindingContributionIdentifier().get().bindingElement();
+    }
+
+    StringBuilder builder = new StringBuilder();
+
+    if (key.qualifier().isPresent()) {
+      // TODO(gak): Use a better name for fields with qualifiers with members.
+      builder.append(key.qualifier().get().getAnnotationType().asElement().getSimpleName());
+    }
+
+    key.type().accept(TYPE_NAMER, builder);
+
+    return protectAgainstKeywords(UPPER_CAMEL.to(LOWER_CAMEL, builder.toString()));
+  }
+}
diff --git a/java/dagger/internal/codegen/Keys.java b/java/dagger/internal/codegen/Keys.java
new file mode 100644
index 0000000..670fda7
--- /dev/null
+++ b/java/dagger/internal/codegen/Keys.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 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.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleTypeVisitor6;
+
+/** Utility methods related to {@link Key}s. */
+final class Keys {
+  static boolean isValidMembersInjectionKey(Key key) {
+    return !key.qualifier().isPresent()
+        && !key.multibindingContributionIdentifier().isPresent()
+        && key.type().getKind().equals(TypeKind.DECLARED);
+  }
+
+  /**
+   * Returns {@code true} if this is valid as an implicit key (that is, if it's valid for a
+   * just-in-time binding by discovering an {@code @Inject} constructor).
+   */
+  static boolean isValidImplicitProvisionKey(Key key, DaggerTypes types) {
+    return isValidImplicitProvisionKey(key.qualifier(), key.type(), types);
+  }
+
+  /**
+   * Returns {@code true} if a key with {@code qualifier} and {@code type} is valid as an implicit
+   * key (that is, if it's valid for a just-in-time binding by discovering an {@code @Inject}
+   * constructor).
+   */
+  static boolean isValidImplicitProvisionKey(
+      Optional<? extends AnnotationMirror> qualifier, TypeMirror type, final DaggerTypes types) {
+    // Qualifiers disqualify implicit provisioning.
+    if (qualifier.isPresent()) {
+      return false;
+    }
+
+    return type.accept(
+        new SimpleTypeVisitor6<Boolean, Void>(false) {
+          @Override
+          public Boolean visitDeclared(DeclaredType type, Void ignored) {
+            // Non-classes or abstract classes aren't allowed.
+            TypeElement element = MoreElements.asType(type.asElement());
+            if (!element.getKind().equals(ElementKind.CLASS)
+                || element.getModifiers().contains(Modifier.ABSTRACT)) {
+              return false;
+            }
+
+            // If the key has type arguments, validate that each type argument is declared.
+            // Otherwise the type argument may be a wildcard (or other type), and we can't
+            // resolve that to actual types.
+            for (TypeMirror arg : type.getTypeArguments()) {
+              if (arg.getKind() != TypeKind.DECLARED) {
+                return false;
+              }
+            }
+
+            // Also validate that the key is not the erasure of a generic type.
+            // If it is, that means the user referred to Foo<T> as just 'Foo',
+            // which we don't allow.  (This is a judgement call -- we *could*
+            // allow it and instantiate the type bounds... but we don't.)
+            return MoreTypes.asDeclared(element.asType()).getTypeArguments().isEmpty()
+                || !types.isSameType(types.erasure(element.asType()), type);
+          }
+        },
+        null);
+  }
+}
diff --git a/java/dagger/internal/codegen/MapBindingExpression.java b/java/dagger/internal/codegen/MapBindingExpression.java
new file mode 100644
index 0000000..526c493
--- /dev/null
+++ b/java/dagger/internal/codegen/MapBindingExpression.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.MapKeys.getMapKeyExpression;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static dagger.model.BindingKind.MULTIBOUND_MAP;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.MapBuilder;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.BindingKind;
+import dagger.model.DependencyRequest;
+import java.util.Collections;
+import java.util.Optional;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/** A {@link BindingExpression} for multibound maps. */
+final class MapBindingExpression extends MultibindingExpression {
+  /** Maximum number of key-value pairs that can be passed to ImmutableMap.of(K, V, K, V, ...). */
+  private static final int MAX_IMMUTABLE_MAP_OF_KEY_VALUE_PAIRS = 5;
+
+  private final ProvisionBinding binding;
+  private final ImmutableMap<DependencyRequest, ContributionBinding> dependencies;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+
+  MapBindingExpression(
+      ResolvedBindings resolvedBindings,
+      ComponentImplementation componentImplementation,
+      BindingGraph graph,
+      ComponentBindingExpressions componentBindingExpressions,
+      DaggerTypes types,
+      DaggerElements elements) {
+    super(resolvedBindings, componentImplementation);
+    this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
+    BindingKind bindingKind = this.binding.kind();
+    checkArgument(bindingKind.equals(MULTIBOUND_MAP), bindingKind);
+    this.componentBindingExpressions = componentBindingExpressions;
+    this.types = types;
+    this.elements = elements;
+    this.dependencies =
+        Maps.toMap(
+            binding.dependencies(),
+            dep -> graph.contributionBindings().get(dep.key()).contributionBinding());
+  }
+
+  @Override
+  protected Expression buildDependencyExpression(ClassName requestingClass) {
+    Optional<CodeBlock> superMethodCall = superMethodCall();
+    // TODO(ronshapiro): We should also make an ImmutableMap version of MapFactory
+    boolean isImmutableMapAvailable = isImmutableMapAvailable();
+    // TODO(ronshapiro, gak): Use Maps.immutableEnumMap() if it's available?
+    if (isImmutableMapAvailable
+        && dependencies.size() <= MAX_IMMUTABLE_MAP_OF_KEY_VALUE_PAIRS
+        && !superMethodCall.isPresent()) {
+      return Expression.create(
+          immutableMapType(),
+          CodeBlock.builder()
+              .add("$T.", ImmutableMap.class)
+              .add(maybeTypeParameters(requestingClass))
+              .add(
+                  "of($L)",
+                  dependencies
+                      .keySet()
+                      .stream()
+                      .map(dependency -> keyAndValueExpression(dependency, requestingClass))
+                      .collect(toParametersCodeBlock()))
+              .build());
+    }
+    switch (dependencies.size()) {
+      case 0:
+        return collectionsStaticFactoryInvocation(requestingClass, CodeBlock.of("emptyMap()"));
+      case 1:
+        return collectionsStaticFactoryInvocation(
+            requestingClass,
+            CodeBlock.of(
+                "singletonMap($L)",
+                keyAndValueExpression(getOnlyElement(dependencies.keySet()), requestingClass)));
+      default:
+        CodeBlock.Builder instantiation = CodeBlock.builder();
+        instantiation
+            .add("$T.", isImmutableMapAvailable ? ImmutableMap.class : MapBuilder.class)
+            .add(maybeTypeParameters(requestingClass));
+        if (isImmutableMapBuilderWithExpectedSizeAvailable()) {
+          instantiation.add("builderWithExpectedSize($L)", dependencies.size());
+        } else if (isImmutableMapAvailable) {
+          instantiation.add("builder()");
+        } else {
+          instantiation.add("newMapBuilder($L)", dependencies.size());
+        }
+        for (DependencyRequest dependency : getNewContributions(dependencies.keySet())) {
+          instantiation.add(".put($L)", keyAndValueExpression(dependency, requestingClass));
+        }
+        if (superMethodCall.isPresent()) {
+          instantiation.add(CodeBlock.of(".putAll($L)", superMethodCall.get()));
+        }
+        return Expression.create(
+            isImmutableMapAvailable ? immutableMapType() : binding.key().type(),
+            instantiation.add(".build()").build());
+    }
+  }
+
+  private DeclaredType immutableMapType() {
+    MapType mapType = MapType.from(binding.key());
+    return types.getDeclaredType(
+        elements.getTypeElement(ImmutableMap.class), mapType.keyType(), mapType.valueType());
+  }
+
+  private CodeBlock keyAndValueExpression(DependencyRequest dependency, ClassName requestingClass) {
+    return CodeBlock.of(
+        "$L, $L",
+        getMapKeyExpression(dependencies.get(dependency), requestingClass, elements),
+        componentBindingExpressions
+            .getDependencyExpression(bindingRequest(dependency), requestingClass)
+            .codeBlock());
+  }
+
+  private Expression collectionsStaticFactoryInvocation(
+      ClassName requestingClass, CodeBlock methodInvocation) {
+    return Expression.create(
+        binding.key().type(),
+        CodeBlock.builder()
+            .add("$T.", Collections.class)
+            .add(maybeTypeParameters(requestingClass))
+            .add(methodInvocation)
+            .build());
+  }
+
+  private CodeBlock maybeTypeParameters(ClassName requestingClass) {
+    TypeMirror bindingKeyType = binding.key().type();
+    MapType mapType = MapType.from(binding.key());
+    return isTypeAccessibleFrom(bindingKeyType, requestingClass.packageName())
+        ? CodeBlock.of("<$T, $T>", mapType.keyType(), mapType.valueType())
+        : CodeBlock.of("");
+  }
+
+  private boolean isImmutableMapBuilderWithExpectedSizeAvailable() {
+    if (isImmutableMapAvailable()) {
+      return methodsIn(elements.getTypeElement(ImmutableMap.class).getEnclosedElements())
+          .stream()
+          .anyMatch(method -> method.getSimpleName().contentEquals("builderWithExpectedSize"));
+    }
+    return false;
+  }
+
+  private boolean isImmutableMapAvailable() {
+    return elements.getTypeElement(ImmutableMap.class) != null;
+  }
+}
diff --git a/java/dagger/internal/codegen/MapFactoryCreationExpression.java b/java/dagger/internal/codegen/MapFactoryCreationExpression.java
new file mode 100644
index 0000000..187b792
--- /dev/null
+++ b/java/dagger/internal/codegen/MapFactoryCreationExpression.java
@@ -0,0 +1,90 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.MapKeys.getMapKeyExpression;
+import static dagger.internal.codegen.SourceFiles.mapFactoryClassName;
+
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.model.DependencyRequest;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import javax.inject.Provider;
+import javax.lang.model.type.TypeMirror;
+
+/** A factory creation expression for a multibound map. */
+final class MapFactoryCreationExpression extends MultibindingFactoryCreationExpression {
+
+  private final ComponentImplementation componentImplementation;
+  private final BindingGraph graph;
+  private final ContributionBinding binding;
+  private final DaggerElements elements;
+
+  MapFactoryCreationExpression(
+      ContributionBinding binding,
+      ComponentImplementation componentImplementation,
+      ComponentBindingExpressions componentBindingExpressions,
+      BindingGraph graph,
+      DaggerElements elements) {
+    super(binding, componentImplementation, componentBindingExpressions);
+    this.binding = checkNotNull(binding);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.graph = checkNotNull(graph);
+    this.elements = checkNotNull(elements);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", mapFactoryClassName(binding));
+    if (!useRawType()) {
+      MapType mapType = MapType.from(binding.key().type());
+      // TODO(ronshapiro): either inline this into mapFactoryClassName, or add a
+      // mapType.unwrappedValueType() method that doesn't require a framework type
+      TypeMirror valueType = mapType.valueType();
+      for (Class<?> frameworkClass :
+          ImmutableSet.of(Provider.class, Producer.class, Produced.class)) {
+        if (mapType.valuesAreTypeOf(frameworkClass)) {
+          valueType = mapType.unwrappedValueType(frameworkClass);
+          break;
+        }
+      }
+      builder.add("<$T, $T>", mapType.keyType(), valueType);
+    }
+
+    builder.add("builder($L)", binding.dependencies().size());
+
+    superContributions()
+        .ifPresent(superContributions -> builder.add(".putAll($L)", superContributions));
+
+    for (DependencyRequest dependency : dependenciesToImplement()) {
+      ContributionBinding contributionBinding =
+          graph.contributionBindings().get(dependency.key()).contributionBinding();
+      builder.add(
+          ".put($L, $L)",
+          getMapKeyExpression(contributionBinding, componentImplementation.name(), elements),
+          multibindingDependencyExpression(dependency));
+    }
+    builder.add(".build()");
+
+    componentImplementation.registerImplementedMultibinding(binding, bindingRequest());
+
+    return builder.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/MapKeyAccessibility.java b/java/dagger/internal/codegen/MapKeyAccessibility.java
new file mode 100644
index 0000000..ce27877
--- /dev/null
+++ b/java/dagger/internal/codegen/MapKeyAccessibility.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 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 dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+
+import dagger.internal.codegen.langmodel.Accessibility;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Predicate;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleAnnotationValueVisitor8;
+
+final class MapKeyAccessibility extends SimpleAnnotationValueVisitor8<Boolean, Void> {
+  private final Predicate<TypeMirror> accessibilityChecker;
+
+  private MapKeyAccessibility(Predicate<TypeMirror> accessibilityChecker) {
+    this.accessibilityChecker = accessibilityChecker;
+  }
+
+  @Override
+  public Boolean visitAnnotation(AnnotationMirror annotation, Void aVoid) {
+    // The annotation type is not checked, as the generated code will refer to the @AutoAnnotation
+    // generated type which is always public
+    return visitValues(annotation.getElementValues().values());
+  }
+
+  @Override
+  public Boolean visitArray(List<? extends AnnotationValue> values, Void aVoid) {
+    return visitValues(values);
+  }
+
+  private boolean visitValues(Collection<? extends AnnotationValue> values) {
+    return values.stream().allMatch(value -> value.accept(this, null));
+  }
+
+  @Override
+  public Boolean visitEnumConstant(VariableElement enumConstant, Void aVoid) {
+    return accessibilityChecker.test(enumConstant.getEnclosingElement().asType());
+  }
+
+  @Override
+  public Boolean visitType(TypeMirror type, Void aVoid) {
+    return accessibilityChecker.test(type);
+  }
+
+  @Override
+  protected Boolean defaultAction(Object o, Void aVoid) {
+    return true;
+  }
+
+  static boolean isMapKeyAccessibleFrom(AnnotationMirror annotation, String accessingPackage) {
+    return new MapKeyAccessibility(type -> isTypeAccessibleFrom(type, accessingPackage))
+        .visitAnnotation(annotation, null);
+  }
+
+  static boolean isMapKeyPubliclyAccessible(AnnotationMirror annotation) {
+    return new MapKeyAccessibility(Accessibility::isTypePubliclyAccessible)
+        .visitAnnotation(annotation, null);
+  }
+}
diff --git a/java/dagger/internal/codegen/MapKeyProcessingStep.java b/java/dagger/internal/codegen/MapKeyProcessingStep.java
index 50693da..19975a7 100644
--- a/java/dagger/internal/codegen/MapKeyProcessingStep.java
+++ b/java/dagger/internal/codegen/MapKeyProcessingStep.java
@@ -16,7 +16,7 @@
 
 package dagger.internal.codegen;
 
-import static dagger.internal.codegen.binding.MapKeys.getUnwrappedMapKeyType;
+import static dagger.internal.codegen.MapKeys.getUnwrappedMapKeyType;
 import static javax.lang.model.element.ElementKind.ANNOTATION_TYPE;
 
 import com.google.auto.common.MoreElements;
@@ -24,11 +24,6 @@
 import com.google.common.collect.ImmutableSet;
 import dagger.MapKey;
 import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.validation.MapKeyValidator;
-import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
-import dagger.internal.codegen.validation.ValidationReport;
-import dagger.internal.codegen.writing.AnnotationCreatorGenerator;
-import dagger.internal.codegen.writing.UnwrappedMapKeyGenerator;
 import java.lang.annotation.Annotation;
 import java.util.Set;
 import javax.annotation.processing.Messager;
@@ -42,7 +37,7 @@
  * The annotation processor responsible for validating the mapKey annotation and auto-generate
  * implementation of annotations marked with {@link MapKey @MapKey} where necessary.
  */
-final class MapKeyProcessingStep extends TypeCheckingProcessingStep<TypeElement> {
+public class MapKeyProcessingStep extends TypeCheckingProcessingStep<TypeElement> {
   private final Messager messager;
   private final DaggerTypes types;
   private final MapKeyValidator mapKeyValidator;
diff --git a/java/dagger/internal/codegen/MapKeyValidator.java b/java/dagger/internal/codegen/MapKeyValidator.java
new file mode 100644
index 0000000..f2568ef
--- /dev/null
+++ b/java/dagger/internal/codegen/MapKeyValidator.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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 javax.lang.model.util.ElementFilter.methodsIn;
+
+import dagger.MapKey;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.List;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+
+/**
+ * A validator for {@link MapKey} annotations.
+ */
+// TODO(dpb,gak): Should unwrapped MapKeys be required to have their single member be named "value"?
+final class MapKeyValidator {
+  private final DaggerElements elements;
+
+  @Inject
+  MapKeyValidator(DaggerElements elements) {
+    this.elements = elements;
+  }
+
+  ValidationReport<Element> validate(Element element) {
+    ValidationReport.Builder<Element> builder = ValidationReport.about(element);
+    List<ExecutableElement> members = methodsIn(((TypeElement) element).getEnclosedElements());
+    if (members.isEmpty()) {
+      builder.addError("Map key annotations must have members", element);
+    } else if (element.getAnnotation(MapKey.class).unwrapValue()) {
+      if (members.size() > 1) {
+        builder.addError(
+            "Map key annotations with unwrapped values must have exactly one member", element);
+      } else if (members.get(0).getReturnType().getKind() == TypeKind.ARRAY) {
+        builder.addError("Map key annotations with unwrapped values cannot use arrays", element);
+      }
+    } else if (autoAnnotationIsMissing()) {
+      builder.addError(
+          "@AutoAnnotation is a necessary dependency if @MapKey(unwrapValue = false). Add a "
+              + "dependency on com.google.auto.value:auto-value:<current version>");
+    }
+    return builder.build();
+  }
+
+  private boolean autoAnnotationIsMissing() {
+    return elements.getTypeElement("com.google.auto.value.AutoAnnotation") == null;
+  }
+}
diff --git a/java/dagger/internal/codegen/MapKeys.java b/java/dagger/internal/codegen/MapKeys.java
new file mode 100644
index 0000000..d8da6af
--- /dev/null
+++ b/java/dagger/internal/codegen/MapKeys.java
@@ -0,0 +1,225 @@
+/*
+ * 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.AnnotationMirrors.getAnnotatedAnnotations;
+import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static dagger.internal.codegen.MapKeyAccessibility.isMapKeyPubliclyAccessible;
+import static dagger.internal.codegen.SourceFiles.elementBasedClassName;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.MapKey;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleTypeVisitor6;
+
+/**
+ * Methods for extracting {@link MapKey} annotations and key code blocks from binding elements.
+ */
+final class MapKeys {
+
+  /**
+   * If {@code bindingElement} is annotated with a {@link MapKey} annotation, returns it.
+   *
+   * @throws IllegalArgumentException if the element is annotated with more than one {@code MapKey}
+   *     annotation
+   */
+  static Optional<AnnotationMirror> getMapKey(Element bindingElement) {
+    ImmutableSet<? extends AnnotationMirror> mapKeys = getMapKeys(bindingElement);
+    return mapKeys.isEmpty()
+        ? Optional.empty()
+        : Optional.<AnnotationMirror>of(getOnlyElement(mapKeys));
+  }
+
+  /**
+   * Returns all of the {@link MapKey} annotations that annotate {@code bindingElement}.
+   */
+  static ImmutableSet<? extends AnnotationMirror> getMapKeys(Element bindingElement) {
+    return getAnnotatedAnnotations(bindingElement, MapKey.class);
+  }
+
+  /**
+   * Returns the annotation value if {@code mapKey}'s type is annotated with
+   * {@link MapKey @MapKey(unwrapValue = true)}.
+   *
+   * @throws IllegalArgumentException if {@code mapKey}'s type is not annotated with
+   *     {@link MapKey @MapKey} at all.
+   */
+  static Optional<? extends AnnotationValue> unwrapValue(AnnotationMirror mapKey) {
+    MapKey mapKeyAnnotation = mapKey.getAnnotationType().asElement().getAnnotation(MapKey.class);
+    checkArgument(
+        mapKeyAnnotation != null, "%s is not annotated with @MapKey", mapKey.getAnnotationType());
+    return mapKeyAnnotation.unwrapValue()
+        ? Optional.of(getOnlyElement(getAnnotationValuesWithDefaults(mapKey).values()))
+        : Optional.empty();
+  }
+
+  static TypeMirror mapKeyType(AnnotationMirror mapKeyAnnotation, DaggerTypes types) {
+    return unwrapValue(mapKeyAnnotation).isPresent()
+        ? getUnwrappedMapKeyType(mapKeyAnnotation.getAnnotationType(), types)
+        : mapKeyAnnotation.getAnnotationType();
+  }
+
+  /**
+   * Returns the map key type for an unwrapped {@link MapKey} annotation type. If the single member
+   * type is primitive, returns the boxed type.
+   *
+   * @throws IllegalArgumentException if {@code mapKeyAnnotationType} is not an annotation type or
+   *     has more than one member, or if its single member is an array
+   * @throws NoSuchElementException if the annotation has no members
+   */
+  static DeclaredType getUnwrappedMapKeyType(
+      final DeclaredType mapKeyAnnotationType, final DaggerTypes types) {
+    checkArgument(
+        MoreTypes.asTypeElement(mapKeyAnnotationType).getKind() == ElementKind.ANNOTATION_TYPE,
+        "%s is not an annotation type",
+        mapKeyAnnotationType);
+
+    final ExecutableElement onlyElement =
+        getOnlyElement(methodsIn(mapKeyAnnotationType.asElement().getEnclosedElements()));
+
+    SimpleTypeVisitor6<DeclaredType, Void> keyTypeElementVisitor =
+        new SimpleTypeVisitor6<DeclaredType, Void>() {
+
+          @Override
+          public DeclaredType visitArray(ArrayType t, Void p) {
+            throw new IllegalArgumentException(
+                mapKeyAnnotationType + "." + onlyElement.getSimpleName() + " cannot be an array");
+          }
+
+          @Override
+          public DeclaredType visitPrimitive(PrimitiveType t, Void p) {
+            return MoreTypes.asDeclared(types.boxedClass(t).asType());
+          }
+
+          @Override
+          public DeclaredType visitDeclared(DeclaredType t, Void p) {
+            return t;
+          }
+        };
+    return keyTypeElementVisitor.visit(onlyElement.getReturnType());
+  }
+
+  /**
+   * Returns a code block for {@code binding}'s {@link ContributionBinding#mapKeyAnnotation() map
+   * key}. If for whatever reason the map key is not accessible from within {@code requestingClass}
+   * (i.e. it has a package-private {@code enum} from a different package), this will return an
+   * invocation of a proxy-method giving it access.
+   *
+   * @throws IllegalStateException if {@code binding} is not a {@link dagger.multibindings.IntoMap
+   *     map} contribution.
+   */
+  static CodeBlock getMapKeyExpression(
+      ContributionBinding binding, ClassName requestingClass, DaggerElements elements) {
+    AnnotationMirror mapKeyAnnotation = binding.mapKeyAnnotation().get();
+    return MapKeyAccessibility.isMapKeyAccessibleFrom(
+            mapKeyAnnotation, requestingClass.packageName())
+        ? directMapKeyExpression(mapKeyAnnotation, elements)
+        : CodeBlock.of("$T.create()", mapKeyProxyClassName(binding));
+  }
+
+  /**
+   * Returns a code block for the map key annotation {@code mapKey}.
+   *
+   * <p>This method assumes the map key will be accessible in the context that the returned {@link
+   * CodeBlock} is used. Use {@link #getMapKeyExpression(ContributionBinding, ClassName,
+   * DaggerElements)} when that assumption is not guaranteed.
+   *
+   * @throws IllegalArgumentException if the element is annotated with more than one {@code MapKey}
+   *     annotation
+   * @throws IllegalStateException if {@code bindingElement} is not annotated with a {@code MapKey}
+   *     annotation
+   */
+  private static CodeBlock directMapKeyExpression(
+      AnnotationMirror mapKey, DaggerElements elements) {
+    Optional<? extends AnnotationValue> unwrappedValue = unwrapValue(mapKey);
+    AnnotationExpression annotationExpression = new AnnotationExpression(mapKey);
+
+    if (MoreTypes.asTypeElement(mapKey.getAnnotationType())
+        .getQualifiedName()
+        .contentEquals("dagger.android.AndroidInjectionKey")) {
+      TypeElement unwrappedType =
+          elements.checkTypePresent((String) unwrappedValue.get().getValue());
+      return CodeBlock.of(
+          "$T.of($S)",
+          ClassName.get("dagger.android.internal", "AndroidInjectionKeys"),
+          ClassName.get(unwrappedType).reflectionName());
+    }
+
+    if (unwrappedValue.isPresent()) {
+      TypeMirror unwrappedValueType =
+          getOnlyElement(getAnnotationValuesWithDefaults(mapKey).keySet()).getReturnType();
+      return annotationExpression.getValueExpression(unwrappedValueType, unwrappedValue.get());
+    } else {
+      return annotationExpression.getAnnotationInstanceExpression();
+    }
+  }
+
+  /**
+   * Returns the {@link ClassName} in which {@link #mapKeyFactoryMethod(ContributionBinding,
+   * DaggerTypes, DaggerElements)} is generated.
+   */
+  static ClassName mapKeyProxyClassName(ContributionBinding binding) {
+    return elementBasedClassName(
+        MoreElements.asExecutable(binding.bindingElement().get()), "MapKey");
+  }
+
+  /**
+   * A {@code static create()} method to be added to {@link
+   * #mapKeyProxyClassName(ContributionBinding)} when the {@code @MapKey} annotation is not publicly
+   * accessible.
+   */
+  static Optional<MethodSpec> mapKeyFactoryMethod(
+      ContributionBinding binding, DaggerTypes types, DaggerElements elements) {
+    return binding
+        .mapKeyAnnotation()
+        .filter(mapKey -> !isMapKeyPubliclyAccessible(mapKey))
+        .map(
+            mapKey ->
+                methodBuilder("create")
+                    .addModifiers(PUBLIC, STATIC)
+                    .returns(TypeName.get(mapKeyType(mapKey, types)))
+                    .addStatement("return $L", directMapKeyExpression(mapKey, elements))
+                    .build());
+  }
+
+  private MapKeys() {}
+}
diff --git a/java/dagger/internal/codegen/MapMultibindingValidator.java b/java/dagger/internal/codegen/MapMultibindingValidator.java
new file mode 100644
index 0000000..346d271
--- /dev/null
+++ b/java/dagger/internal/codegen/MapMultibindingValidator.java
@@ -0,0 +1,199 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Multimaps.filterKeys;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSetMultimap;
+import static dagger.internal.codegen.Formatter.INDENT;
+import static dagger.model.BindingKind.MULTIBOUND_MAP;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.base.Equivalence;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+import dagger.model.BindingGraph;
+import dagger.model.Key;
+import dagger.producers.Producer;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.lang.model.type.DeclaredType;
+
+/**
+ * Reports an error for any map binding with either more than one contribution with the same map key
+ * or contributions with inconsistent map key annotation types.
+ */
+final class MapMultibindingValidator implements BindingGraphPlugin {
+
+  private final BindingDeclarationFormatter bindingDeclarationFormatter;
+  private final KeyFactory keyFactory;
+
+  @Inject
+  MapMultibindingValidator(
+      BindingDeclarationFormatter bindingDeclarationFormatter, KeyFactory keyFactory) {
+    this.bindingDeclarationFormatter = bindingDeclarationFormatter;
+    this.keyFactory = keyFactory;
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/MapKeys";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    mapMultibindings(bindingGraph)
+        .forEach(
+            binding -> {
+              ImmutableSet<ContributionBinding> contributions =
+                  mapBindingContributions(binding, bindingGraph);
+              checkForDuplicateMapKeys(binding, contributions, diagnosticReporter);
+              checkForInconsistentMapKeyAnnotationTypes(binding, contributions, diagnosticReporter);
+            });
+  }
+
+  /**
+   * Returns the map multibindings in the binding graph. If a graph contains bindings for more than
+   * one of the following for the same {@code K} and {@code V}, then only the first one found will
+   * be returned so we don't report the same map contribution problem more than once.
+   *
+   * <ol>
+   *   <li>{@code Map<K, V>}
+   *   <li>{@code Map<K, Provider<V>>}
+   *   <li>{@code Map<K, Producer<V>>}
+   * </ol>
+   */
+  private ImmutableSet<dagger.model.Binding> mapMultibindings(BindingGraph bindingGraph) {
+    ImmutableSetMultimap<Key, dagger.model.Binding> mapMultibindings =
+        bindingGraph.bindings().stream()
+            .filter(node -> node.kind().equals(MULTIBOUND_MAP))
+            .collect(toImmutableSetMultimap(dagger.model.Binding::key, node -> node));
+
+    // Mutlbindings for Map<K, V>
+    SetMultimap<Key, dagger.model.Binding> plainValueMapMultibindings =
+        filterKeys(mapMultibindings, key -> !MapType.from(key).valuesAreFrameworkType());
+
+    // Multibindings for Map<K, Provider<V>> where Map<K, V> isn't in plainValueMapMultibindings
+    SetMultimap<Key, dagger.model.Binding> providerValueMapMultibindings =
+        filterKeys(
+            mapMultibindings,
+            key ->
+                MapType.from(key).valuesAreTypeOf(Provider.class)
+                    && !plainValueMapMultibindings.containsKey(keyFactory.unwrapMapValueType(key)));
+
+    // Multibindings for Map<K, Producer<V>> where Map<K, V> isn't in plainValueMapMultibindings and
+    // Map<K, Provider<V>> isn't in providerValueMapMultibindings
+    SetMultimap<Key, dagger.model.Binding> producerValueMapMultibindings =
+        filterKeys(
+            mapMultibindings,
+            key ->
+                MapType.from(key).valuesAreTypeOf(Producer.class)
+                    && !plainValueMapMultibindings.containsKey(keyFactory.unwrapMapValueType(key))
+                    && !providerValueMapMultibindings.containsKey(
+                        keyFactory.rewrapMapKey(key, Producer.class, Provider.class).get()));
+
+    return new ImmutableSet.Builder<dagger.model.Binding>()
+        .addAll(plainValueMapMultibindings.values())
+        .addAll(providerValueMapMultibindings.values())
+        .addAll(producerValueMapMultibindings.values())
+        .build();
+  }
+
+  private ImmutableSet<ContributionBinding> mapBindingContributions(
+      dagger.model.Binding binding, BindingGraph bindingGraph) {
+    checkArgument(binding.kind().equals(MULTIBOUND_MAP));
+    return bindingGraph.requestedBindings(binding).stream()
+        .map(b -> (BindingNode) b)
+        .map(b -> (ContributionBinding) b.delegate())
+        .collect(toImmutableSet());
+  }
+
+  private void checkForDuplicateMapKeys(
+      dagger.model.Binding multiboundMapBinding,
+      ImmutableSet<ContributionBinding> contributions,
+      DiagnosticReporter diagnosticReporter) {
+    ImmutableSetMultimap<Object, ContributionBinding> contributionsByMapKey =
+        ImmutableSetMultimap.copyOf(Multimaps.index(contributions, ContributionBinding::mapKey));
+
+    for (Set<ContributionBinding> contributionsForOneMapKey :
+        Multimaps.asMap(contributionsByMapKey).values()) {
+      if (contributionsForOneMapKey.size() > 1) {
+        diagnosticReporter.reportBinding(
+            ERROR,
+            multiboundMapBinding,
+            duplicateMapKeyErrorMessage(contributionsForOneMapKey, multiboundMapBinding.key()));
+      }
+    }
+  }
+
+  private void checkForInconsistentMapKeyAnnotationTypes(
+      dagger.model.Binding multiboundMapBinding,
+      ImmutableSet<ContributionBinding> contributions,
+      DiagnosticReporter diagnosticReporter) {
+    ImmutableSetMultimap<Equivalence.Wrapper<DeclaredType>, ContributionBinding>
+        contributionsByMapKeyAnnotationType = indexByMapKeyAnnotationType(contributions);
+
+    if (contributionsByMapKeyAnnotationType.keySet().size() > 1) {
+      diagnosticReporter.reportBinding(
+          ERROR,
+          multiboundMapBinding,
+          inconsistentMapKeyAnnotationTypesErrorMessage(
+              contributionsByMapKeyAnnotationType, multiboundMapBinding.key()));
+    }
+  }
+
+  private static ImmutableSetMultimap<Equivalence.Wrapper<DeclaredType>, ContributionBinding>
+      indexByMapKeyAnnotationType(ImmutableSet<ContributionBinding> contributions) {
+    return ImmutableSetMultimap.copyOf(
+        Multimaps.index(
+            contributions,
+            mapBinding ->
+                MoreTypes.equivalence()
+                    .wrap(mapBinding.mapKeyAnnotation().get().getAnnotationType())));
+  }
+
+  private String inconsistentMapKeyAnnotationTypesErrorMessage(
+      ImmutableSetMultimap<Equivalence.Wrapper<DeclaredType>, ContributionBinding>
+          contributionsByMapKeyAnnotationType,
+      Key mapBindingKey) {
+    StringBuilder message =
+        new StringBuilder(mapBindingKey.toString())
+            .append(" uses more than one @MapKey annotation type");
+    Multimaps.asMap(contributionsByMapKeyAnnotationType)
+        .forEach(
+            (annotationType, contributions) -> {
+              message.append('\n').append(INDENT).append(annotationType.get()).append(':');
+              bindingDeclarationFormatter.formatIndentedList(message, contributions, 2);
+            });
+    return message.toString();
+  }
+
+  private String duplicateMapKeyErrorMessage(
+      Set<ContributionBinding> contributionsForOneMapKey, Key mapBindingKey) {
+    StringBuilder message =
+        new StringBuilder("The same map key is bound more than once for ").append(mapBindingKey);
+    bindingDeclarationFormatter.formatIndentedList(message, contributionsForOneMapKey, 1);
+    return message.toString();
+  }
+}
diff --git a/java/dagger/internal/codegen/MapType.java b/java/dagger/internal/codegen/MapType.java
new file mode 100644
index 0000000..73ecdbf
--- /dev/null
+++ b/java/dagger/internal/codegen/MapType.java
@@ -0,0 +1,158 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Equivalence;
+import dagger.model.Key;
+import java.util.Map;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Information about a {@link Map} {@link TypeMirror}.
+ */
+@AutoValue
+abstract class MapType {
+  /**
+   * The map type itself, wrapped using {@link MoreTypes#equivalence()}. Use
+   * {@link #declaredMapType()} instead.
+   */
+  protected abstract Equivalence.Wrapper<DeclaredType> wrappedDeclaredMapType();
+
+  /**
+   * The map type itself.
+   */
+  DeclaredType declaredMapType() {
+    return wrappedDeclaredMapType().get();
+  }
+
+  /**
+   * {@code true} if the map type is the raw {@link Map} type.
+   */
+  boolean isRawType() {
+    return declaredMapType().getTypeArguments().isEmpty();
+  }
+
+  /**
+   * The map key type.
+   * 
+   * @throws IllegalStateException if {@link #isRawType()} is true.
+   */
+  TypeMirror keyType() {
+    checkState(!isRawType());
+    return declaredMapType().getTypeArguments().get(0);
+  }
+
+  /**
+   * The map value type.
+   * 
+   * @throws IllegalStateException if {@link #isRawType()} is true.
+   */
+  TypeMirror valueType() {
+    checkState(!isRawType());
+    return declaredMapType().getTypeArguments().get(1);
+  }
+
+  /**
+   * {@code true} if {@link #valueType()} is a {@code clazz}.
+   * 
+   * @throws IllegalStateException if {@link #isRawType()} is true.
+   */
+  boolean valuesAreTypeOf(Class<?> clazz) {
+    return MoreTypes.isType(valueType()) && MoreTypes.isTypeOf(clazz, valueType());
+  }
+
+  /**
+   * Returns {@code true} if the {@linkplain #valueType() value type} of the {@link Map} is a
+   * {@linkplain FrameworkTypes#isFrameworkType(TypeMirror) framework type}.
+   */
+  boolean valuesAreFrameworkType() {
+    return FrameworkTypes.isFrameworkType(valueType());
+  }
+
+  /**
+   * {@code V} if {@link #valueType()} is a framework type like {@code Provider<V>} or {@code
+   * Producer<V>}.
+   *
+   * @throws IllegalStateException if {@link #isRawType()} is true or {@link #valueType()} is not a
+   *     framework type
+   */
+  TypeMirror unwrappedFrameworkValueType() {
+    checkState(
+        valuesAreFrameworkType(), "called unwrappedFrameworkValueType() on %s", declaredMapType());
+    return uncheckedUnwrappedValueType();
+  }
+
+  /**
+   * {@code V} if {@link #valueType()} is a {@code WrappingClass<V>}.
+   *
+   * @throws IllegalStateException if {@link #isRawType()} is true or {@link #valueType()} is not a
+   *     {@code WrappingClass<V>}
+   * @throws IllegalArgumentException if {@code wrappingClass} does not have exactly one type
+   *     parameter
+   */
+  TypeMirror unwrappedValueType(Class<?> wrappingClass) {
+    checkArgument(
+        wrappingClass.getTypeParameters().length == 1,
+        "%s must have exactly one type parameter",
+        wrappingClass);
+    checkState(valuesAreTypeOf(wrappingClass), "expected values to be %s: %s", wrappingClass, this);
+    return uncheckedUnwrappedValueType();
+  }
+
+  private TypeMirror uncheckedUnwrappedValueType() {
+    return MoreTypes.asDeclared(valueType()).getTypeArguments().get(0);
+  }
+
+  /**
+   * {@code true} if {@code type} is a {@link Map} type.
+   */
+  static boolean isMap(TypeMirror type) {
+    return MoreTypes.isType(type) && MoreTypes.isTypeOf(Map.class, type);
+  }
+
+  /**
+   * {@code true} if {@code key.type()} is a {@link Map} type.
+   */
+  static boolean isMap(Key key) {
+    return isMap(key.type());
+  }
+
+  /**
+   * Returns a {@link MapType} for {@code type}.
+   *
+   * @throws IllegalArgumentException if {@code type} is not a {@link Map} type
+   */
+  static MapType from(TypeMirror type) {
+    checkArgument(isMap(type), "%s is not a Map", type);
+    return new AutoValue_MapType(MoreTypes.equivalence().wrap(MoreTypes.asDeclared(type)));
+  }
+
+  /**
+   * Returns a {@link MapType} for {@code key}'s {@link Key#type() type}.
+   *
+   * @throws IllegalArgumentException if {@code key.type()} is not a {@link Map} type
+   */
+  static MapType from(Key key) {
+    return from(key.type());
+  }
+}
diff --git a/java/dagger/internal/codegen/MemberSelect.java b/java/dagger/internal/codegen/MemberSelect.java
new file mode 100644
index 0000000..c42c7c9
--- /dev/null
+++ b/java/dagger/internal/codegen/MemberSelect.java
@@ -0,0 +1,274 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
+import static dagger.internal.codegen.SourceFiles.bindingTypeElementTypeVariableNames;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+import static dagger.internal.codegen.SourceFiles.setFactoryClassName;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCERS;
+import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static javax.lang.model.type.TypeKind.DECLARED;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import java.util.List;
+import java.util.Optional;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Represents a {@link com.sun.source.tree.MemberSelectTree} as a {@link CodeBlock}.
+ */
+abstract class MemberSelect {
+
+  /**
+   * Returns a {@link MemberSelect} that accesses the field given by {@code fieldName} owned by
+   * {@code owningClass}.  In this context "local" refers to the fact that the field is owned by the
+   * type (or an enclosing type) from which the code block will be used.  The returned
+   * {@link MemberSelect} will not be valid for accessing the field from a different class
+   * (regardless of accessibility).
+   */
+  static MemberSelect localField(ClassName owningClass, String fieldName) {
+    return new LocalField(owningClass, fieldName);
+  }
+
+  private static final class LocalField extends MemberSelect {
+    final String fieldName;
+
+    LocalField(ClassName owningClass, String fieldName) {
+      super(owningClass, false);
+      this.fieldName = checkNotNull(fieldName);
+    }
+
+    @Override
+    CodeBlock getExpressionFor(ClassName usingClass) {
+      return owningClass().equals(usingClass)
+          ? CodeBlock.of("$N", fieldName)
+          : CodeBlock.of("$T.this.$N", owningClass(), fieldName);
+    }
+  }
+
+  /**
+   * Returns a {@link MemberSelect} that accesses the method given by {@code methodName} owned by
+   * {@code owningClass}. In this context "local" refers to the fact that the method is owned by the
+   * type (or an enclosing type) from which the code block will be used. The returned {@link
+   * MemberSelect} will not be valid for accessing the method from a different class (regardless of
+   * accessibility).
+   */
+  static MemberSelect localMethod(ClassName owningClass, String methodName) {
+    return new LocalMethod(owningClass, methodName);
+  }
+
+  private static final class LocalMethod extends MemberSelect {
+    final String methodName;
+
+    LocalMethod(ClassName owningClass, String methodName) {
+      super(owningClass, false);
+      this.methodName = checkNotNull(methodName);
+    }
+
+    @Override
+    CodeBlock getExpressionFor(ClassName usingClass) {
+      return owningClass().equals(usingClass)
+          ? CodeBlock.of("$N()", methodName)
+          : CodeBlock.of("$T.this.$N()", owningClass(), methodName);
+    }
+  }
+
+  /**
+   * If {@code resolvedBindings} is an unscoped provision binding with no factory arguments or a
+   * no-op members injection binding, then we don't need a field to hold its factory. In that case,
+   * this method returns the static member select that returns the factory or no-op members
+   * injector.
+   */
+  static Optional<MemberSelect> staticFactoryCreation(ResolvedBindings resolvedBindings) {
+    if (resolvedBindings.contributionBindings().isEmpty()) {
+      throw new AssertionError(
+          "Expected a contribution binding, but none found. *THIS IS A DAGGER BUG* - please "
+              + "report it on Github with as much context as you can provide. Thanks!"
+              + "\n\nKey: "
+              + resolvedBindings.key()
+              + "\nMultibinding declarations: "
+              + resolvedBindings.multibindingDeclarations()
+              + "\nSubcomponent declarations: "
+              + resolvedBindings.subcomponentDeclarations()
+              + "\nOptional binding declarations: "
+              + resolvedBindings.optionalBindingDeclarations());
+    }
+    ContributionBinding contributionBinding = resolvedBindings.contributionBinding();
+    if (contributionBinding.factoryCreationStrategy().equals(SINGLETON_INSTANCE)
+        && !contributionBinding.scope().isPresent()) {
+      switch (contributionBinding.kind()) {
+        case MULTIBOUND_MAP:
+          return Optional.of(emptyMapFactory(contributionBinding));
+
+        case MULTIBOUND_SET:
+          return Optional.of(emptySetFactory(contributionBinding));
+
+        case INJECTION:
+        case PROVISION:
+          TypeMirror keyType = resolvedBindings.key().type();
+          if (keyType.getKind().equals(DECLARED)) {
+            ImmutableList<TypeVariableName> typeVariables =
+                bindingTypeElementTypeVariableNames(contributionBinding);
+            if (!typeVariables.isEmpty()) {
+              List<? extends TypeMirror> typeArguments =
+                  ((DeclaredType) keyType).getTypeArguments();
+              return Optional.of(
+                  MemberSelect.parameterizedFactoryCreateMethod(
+                      generatedClassNameForBinding(contributionBinding), typeArguments));
+            }
+          }
+          // fall through
+
+        default:
+          return Optional.of(
+              new StaticMethod(
+                  generatedClassNameForBinding(contributionBinding), CodeBlock.of("create()")));
+      }
+    }
+
+    return Optional.empty();
+  }
+
+  /**
+   * Returns a {@link MemberSelect} for the instance of a {@code create()} method on a factory. This
+   * only applies for factories that do not have any dependencies.
+   */
+  private static MemberSelect parameterizedFactoryCreateMethod(
+      ClassName owningClass, List<? extends TypeMirror> parameters) {
+    return new ParameterizedStaticMethod(
+        owningClass, ImmutableList.copyOf(parameters), CodeBlock.of("create()"), FACTORY);
+  }
+
+  private static final class StaticMethod extends MemberSelect {
+    final CodeBlock methodCodeBlock;
+
+    StaticMethod(ClassName owningClass, CodeBlock methodCodeBlock) {
+      super(owningClass, true);
+      this.methodCodeBlock = checkNotNull(methodCodeBlock);
+    }
+
+    @Override
+    CodeBlock getExpressionFor(ClassName usingClass) {
+      return owningClass().equals(usingClass)
+          ? methodCodeBlock
+          : CodeBlock.of("$T.$L", owningClass(), methodCodeBlock);
+    }
+  }
+
+  /** A {@link MemberSelect} for a factory of an empty map. */
+  private static MemberSelect emptyMapFactory(ContributionBinding contributionBinding) {
+    BindingType bindingType = contributionBinding.bindingType();
+    ImmutableList<TypeMirror> typeParameters =
+        ImmutableList.copyOf(
+            MoreTypes.asDeclared(contributionBinding.key().type()).getTypeArguments());
+    if (bindingType.equals(BindingType.PRODUCTION)) {
+      return new ParameterizedStaticMethod(
+          PRODUCERS, typeParameters, CodeBlock.of("emptyMapProducer()"), PRODUCER);
+    } else {
+      return new ParameterizedStaticMethod(
+          MAP_FACTORY, typeParameters, CodeBlock.of("emptyMapProvider()"), PROVIDER);
+    }
+  }
+
+  /**
+   * A static member select for an empty set factory. Calls {@link
+   * dagger.internal.SetFactory#empty()}, {@link dagger.producers.internal.SetProducer#empty()}, or
+   * {@link dagger.producers.internal.SetOfProducedProducer#empty()}, depending on the set bindings.
+   */
+  private static MemberSelect emptySetFactory(ContributionBinding binding) {
+    return new ParameterizedStaticMethod(
+        setFactoryClassName(binding),
+        ImmutableList.of(SetType.from(binding.key()).elementType()),
+        CodeBlock.of("empty()"),
+        FACTORY);
+  }
+
+  private static final class ParameterizedStaticMethod extends MemberSelect {
+    final ImmutableList<TypeMirror> typeParameters;
+    final CodeBlock methodCodeBlock;
+    final ClassName rawReturnType;
+
+    ParameterizedStaticMethod(
+        ClassName owningClass,
+        ImmutableList<TypeMirror> typeParameters,
+        CodeBlock methodCodeBlock,
+        ClassName rawReturnType) {
+      super(owningClass, true);
+      this.typeParameters = typeParameters;
+      this.methodCodeBlock = methodCodeBlock;
+      this.rawReturnType = rawReturnType;
+    }
+
+    @Override
+    CodeBlock getExpressionFor(ClassName usingClass) {
+      boolean accessible = true;
+      for (TypeMirror typeParameter : typeParameters) {
+        accessible &= isTypeAccessibleFrom(typeParameter, usingClass.packageName());
+      }
+
+      if (accessible) {
+        return CodeBlock.of(
+            "$T.<$L>$L",
+            owningClass(),
+            typeParameters.stream().map(CodeBlocks::type).collect(toParametersCodeBlock()),
+            methodCodeBlock);
+      } else {
+        return CodeBlock.of("(($T) $T.$L)", rawReturnType, owningClass(), methodCodeBlock);
+      }
+    }
+  }
+
+  private final ClassName owningClass;
+  private final boolean staticMember;
+
+  MemberSelect(ClassName owningClass, boolean staticMemeber) {
+    this.owningClass = owningClass;
+    this.staticMember = staticMemeber;
+  }
+
+  /** Returns the class that owns the member being selected. */
+  ClassName owningClass() {
+    return owningClass;
+  }
+
+  /**
+   * Returns true if the member being selected is static and does not require an instance of
+   * {@link #owningClass()}.
+   */
+  boolean staticMember() {
+    return staticMember;
+  }
+
+  /**
+   * Returns a {@link CodeBlock} suitable for accessing the member from the given {@code
+   * usingClass}.
+   */
+  abstract CodeBlock getExpressionFor(ClassName usingClass);
+}
diff --git a/java/dagger/internal/codegen/MembersInjectionBinding.java b/java/dagger/internal/codegen/MembersInjectionBinding.java
new file mode 100644
index 0000000..4918fa1
--- /dev/null
+++ b/java/dagger/internal/codegen/MembersInjectionBinding.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2014 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.MoreElements.isAnnotationPresent;
+import static java.util.stream.Collectors.toList;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import dagger.model.BindingKind;
+import dagger.model.DependencyRequest;
+import java.util.Optional;
+import javax.inject.Inject;
+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.element.VariableElement;
+
+/**
+ * Represents the full members injection of a particular type.
+ */
+@AutoValue
+abstract class MembersInjectionBinding extends Binding {
+  @Override
+  public final Optional<Element> bindingElement() {
+    return Optional.of(membersInjectedType());
+  }
+
+  abstract TypeElement membersInjectedType();
+
+  @Override
+  abstract Optional<MembersInjectionBinding> unresolved();
+
+  @Override
+  public Optional<TypeElement> contributingModule() {
+    return Optional.empty();
+  }
+
+  /** The set of individual sites where {@link Inject} is applied. */
+  abstract ImmutableSortedSet<InjectionSite> injectionSites();
+
+  @Override
+  BindingType bindingType() {
+    return BindingType.MEMBERS_INJECTION;
+  }
+
+  @Override
+  public BindingKind kind() {
+    return BindingKind.MEMBERS_INJECTION;
+  }
+
+  @Override
+  public boolean isNullable() {
+    return false;
+  }
+
+  /**
+   * Returns {@code true} if any of this binding's injection sites are directly on the bound type.
+   */
+  boolean hasLocalInjectionSites() {
+    return injectionSites()
+        .stream()
+        .anyMatch(
+            injectionSite ->
+                injectionSite.element().getEnclosingElement().equals(membersInjectedType()));
+  }
+
+  @Override
+  boolean requiresModuleInstance() {
+    return false;
+  }
+
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  // TODO(ronshapiro,dpb): simplify the equality semantics
+  @Override
+  public abstract boolean equals(Object obj);
+
+  @AutoValue
+  abstract static class InjectionSite {
+    enum Kind {
+      FIELD,
+      METHOD,
+    }
+
+    abstract Kind kind();
+
+    abstract Element element();
+
+    abstract ImmutableSet<DependencyRequest> dependencies();
+
+    /**
+     * Returns the index of {@link #element()} in its parents {@code @Inject} members that have the
+     * same simple name. This method filters out private elements so that the results will be
+     * consistent independent of whether the build system uses header jars or not.
+     */
+    @Memoized
+    int indexAmongAtInjectMembersWithSameSimpleName() {
+      return element()
+          .getEnclosingElement()
+          .getEnclosedElements()
+          .stream()
+          .filter(element -> isAnnotationPresent(element, Inject.class))
+          .filter(element -> !element.getModifiers().contains(Modifier.PRIVATE))
+          .filter(element -> element.getSimpleName().equals(this.element().getSimpleName()))
+          .collect(toList())
+          .indexOf(element());
+    }
+
+    static InjectionSite field(VariableElement element, DependencyRequest dependency) {
+      return new AutoValue_MembersInjectionBinding_InjectionSite(
+          Kind.FIELD, element, ImmutableSet.of(dependency));
+    }
+
+    static InjectionSite method(
+        ExecutableElement element, Iterable<DependencyRequest> dependencies) {
+      return new AutoValue_MembersInjectionBinding_InjectionSite(
+          Kind.METHOD, element, ImmutableSet.copyOf(dependencies));
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/MembersInjectionBindingExpression.java b/java/dagger/internal/codegen/MembersInjectionBindingExpression.java
new file mode 100644
index 0000000..e9a8ffc
--- /dev/null
+++ b/java/dagger/internal/codegen/MembersInjectionBindingExpression.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 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.common.collect.Iterables.getOnlyElement;
+import static javax.lang.model.type.TypeKind.VOID;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.ParameterSpec;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import javax.lang.model.element.ExecutableElement;
+
+/**
+ * A binding expression for members injection component methods. See {@link
+ * MembersInjectionMethods}.
+ */
+final class MembersInjectionBindingExpression extends BindingExpression {
+  private final MembersInjectionBinding binding;
+  private final MembersInjectionMethods membersInjectionMethods;
+
+  MembersInjectionBindingExpression(
+      ResolvedBindings resolvedBindings, MembersInjectionMethods membersInjectionMethods) {
+    this.binding = resolvedBindings.membersInjectionBinding().get();
+    this.membersInjectionMethods = membersInjectionMethods;
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    throw new UnsupportedOperationException(binding.toString());
+  }
+
+  // TODO(ronshapiro): This class doesn't need to be a BindingExpression, as
+  // getDependencyExpression() should never be called for members injection methods. It's probably
+  // better suited as a method on MembersInjectionMethods
+  @Override
+  protected CodeBlock getComponentMethodImplementation(
+      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
+    ExecutableElement methodElement = componentMethod.methodElement();
+    ParameterSpec parameter = ParameterSpec.get(getOnlyElement(methodElement.getParameters()));
+
+    if (binding.injectionSites().isEmpty()) {
+      return methodElement.getReturnType().getKind().equals(VOID)
+          ? CodeBlock.of("")
+          : CodeBlock.of("return $N;", parameter);
+    } else {
+      return methodElement.getReturnType().getKind().equals(VOID)
+          ? CodeBlock.of("$L;", membersInjectionInvocation(parameter))
+          : CodeBlock.of("return $L;", membersInjectionInvocation(parameter));
+    }
+  }
+
+  CodeBlock membersInjectionInvocation(ParameterSpec target) {
+    return CodeBlock.of("$N($N)", membersInjectionMethods.getOrCreate(binding.key()), target);
+  }
+}
diff --git a/java/dagger/internal/codegen/MembersInjectionMethods.java b/java/dagger/internal/codegen/MembersInjectionMethods.java
new file mode 100644
index 0000000..1e04669
--- /dev/null
+++ b/java/dagger/internal/codegen/MembersInjectionMethods.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkNotNull;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.MEMBERS_INJECTION_METHOD;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.InjectionMethods.InjectionSiteMethod;
+import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/** Manages the member injection methods for a component. */
+final class MembersInjectionMethods {
+  private final Map<Key, MethodSpec> membersInjectionMethods = new LinkedHashMap<>();
+  private final ComponentImplementation componentImplementation;
+  private final ComponentBindingExpressions bindingExpressions;
+  private final BindingGraph graph;
+  private final DaggerElements elements;
+  private final DaggerTypes types;
+
+  MembersInjectionMethods(
+      ComponentImplementation componentImplementation,
+      ComponentBindingExpressions bindingExpressions,
+      BindingGraph graph,
+      DaggerElements elements,
+      DaggerTypes types) {
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.bindingExpressions = checkNotNull(bindingExpressions);
+    this.graph = checkNotNull(graph);
+    this.elements = checkNotNull(elements);
+    this.types = checkNotNull(types);
+  }
+
+  /**
+   * Returns the members injection {@link MethodSpec} for the given {@link Key}, creating it if
+   * necessary.
+   */
+  MethodSpec getOrCreate(Key key) {
+    return reentrantComputeIfAbsent(membersInjectionMethods, key, this::membersInjectionMethod);
+  }
+
+  private MethodSpec membersInjectionMethod(Key key) {
+    ResolvedBindings resolvedBindings =
+        graph.membersInjectionBindings().getOrDefault(key, graph.contributionBindings().get(key));
+    Binding binding = resolvedBindings.binding();
+    TypeMirror keyType = binding.key().type();
+    TypeMirror membersInjectedType =
+        isTypeAccessibleFrom(keyType, componentImplementation.name().packageName())
+            ? keyType
+            : elements.getTypeElement(Object.class).asType();
+    TypeName membersInjectedTypeName = TypeName.get(membersInjectedType);
+    Name bindingTypeName = binding.bindingTypeElement().get().getSimpleName();
+    // TODO(ronshapiro): include type parameters in this name e.g. injectFooOfT, and outer class
+    // simple names Foo.Builder -> injectFooBuilder
+    String methodName = componentImplementation.getUniqueMethodName("inject" + bindingTypeName);
+    ParameterSpec parameter = ParameterSpec.builder(membersInjectedTypeName, "instance").build();
+    MethodSpec.Builder methodBuilder =
+        methodBuilder(methodName)
+            .addModifiers(PRIVATE)
+            .returns(membersInjectedTypeName)
+            .addParameter(parameter);
+    TypeElement canIgnoreReturnValue =
+        elements.getTypeElement("com.google.errorprone.annotations.CanIgnoreReturnValue");
+    if (canIgnoreReturnValue != null) {
+      methodBuilder.addAnnotation(ClassName.get(canIgnoreReturnValue));
+    }
+    CodeBlock instance = CodeBlock.of("$N", parameter);
+    methodBuilder.addCode(
+        InjectionSiteMethod.invokeAll(
+            injectionSites(binding),
+            componentImplementation.name(),
+            instance,
+            membersInjectedType,
+            types,
+            request ->
+                bindingExpressions
+                    .getDependencyArgumentExpression(request, componentImplementation.name())
+                    .codeBlock(),
+            elements));
+    methodBuilder.addStatement("return $L", instance);
+
+    MethodSpec method = methodBuilder.build();
+    componentImplementation.addMethod(MEMBERS_INJECTION_METHOD, method);
+    return method;
+  }
+
+  private static ImmutableSet<InjectionSite> injectionSites(Binding binding) {
+    if (binding instanceof ProvisionBinding) {
+      return ((ProvisionBinding) binding).injectionSites();
+    } else if (binding instanceof MembersInjectionBinding) {
+      return ((MembersInjectionBinding) binding).injectionSites();
+    }
+    throw new IllegalArgumentException(binding.key().toString());
+  }
+}
diff --git a/java/dagger/internal/codegen/MembersInjectionValidator.java b/java/dagger/internal/codegen/MembersInjectionValidator.java
new file mode 100644
index 0000000..036315e
--- /dev/null
+++ b/java/dagger/internal/codegen/MembersInjectionValidator.java
@@ -0,0 +1,149 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifiers;
+
+import com.google.auto.common.MoreElements;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVisitor;
+import javax.lang.model.util.SimpleTypeVisitor8;
+
+/**
+ * Validates members injection requests (members injection methods on components and requests for
+ * {@code MembersInjector<Foo>}).
+ */
+final class MembersInjectionValidator {
+
+  @Inject
+  MembersInjectionValidator() {}
+
+  /** Reports errors if a request for a {@code MembersInjector<Foo>}) is invalid. */
+  ValidationReport<Element> validateMembersInjectionRequest(
+      Element requestElement, TypeMirror membersInjectedType) {
+    ValidationReport.Builder<Element> report = ValidationReport.about(requestElement);
+    checkQualifiers(report, requestElement);
+    membersInjectedType.accept(VALIDATE_MEMBERS_INJECTED_TYPE, report);
+    return report.build();
+  }
+
+  /**
+   * Reports errors if a members injection method on a component is invalid.
+   *
+   * @throws IllegalArgumentException if the method doesn't have exactly one parameter
+   */
+  ValidationReport<ExecutableElement> validateMembersInjectionMethod(
+      ExecutableElement method, TypeMirror membersInjectedType) {
+    checkArgument(
+        method.getParameters().size() == 1, "expected a method with one parameter: %s", method);
+
+    ValidationReport.Builder<ExecutableElement> report = ValidationReport.about(method);
+    checkQualifiers(report, method);
+    checkQualifiers(report, method.getParameters().get(0));
+    membersInjectedType.accept(VALIDATE_MEMBERS_INJECTED_TYPE, report);
+    return report.build();
+  }
+
+  private void checkQualifiers(ValidationReport.Builder<?> report, Element element) {
+    for (AnnotationMirror qualifier : getQualifiers(element)) {
+      report.addError("Cannot inject members into qualified types", element, qualifier);
+      break; // just report on the first qualifier, in case there is more than one
+    }
+  }
+
+  private static final TypeVisitor<Void, ValidationReport.Builder<?>>
+      VALIDATE_MEMBERS_INJECTED_TYPE =
+          new SimpleTypeVisitor8<Void, ValidationReport.Builder<?>>() {
+            // Only declared types can be members-injected.
+            @Override
+            protected Void defaultAction(TypeMirror type, ValidationReport.Builder<?> report) {
+              report.addError("Cannot inject members into " + type);
+              return null;
+            }
+
+            @Override
+            public Void visitDeclared(DeclaredType type, ValidationReport.Builder<?> report) {
+              if (type.getTypeArguments().isEmpty()) {
+                // If the type is the erasure of a generic type, that means the user referred to
+                // Foo<T> as just 'Foo', which we don't allow.  (This is a judgement call; we
+                // *could* allow it and instantiate the type bounds, but we don't.)
+                if (!MoreElements.asType(type.asElement()).getTypeParameters().isEmpty()) {
+                  report.addError("Cannot inject members into raw type " + type);
+                }
+              } else {
+                // If the type has arguments, validate that each type argument is declared.
+                // Otherwise the type argument may be a wildcard (or other type), and we can't
+                // resolve that to actual types.  For array type arguments, validate the type of the
+                // array.
+                for (TypeMirror arg : type.getTypeArguments()) {
+                  if (!arg.accept(DECLARED_OR_ARRAY, null)) {
+                    report.addError(
+                        "Cannot inject members into types with unbounded type arguments: " + type);
+                  }
+                }
+              }
+              return null;
+            }
+          };
+
+  // TODO(dpb): Can this be inverted so it explicitly rejects wildcards or type variables?
+  // This logic is hard to describe.
+  private static final TypeVisitor<Boolean, Void> DECLARED_OR_ARRAY =
+      new SimpleTypeVisitor8<Boolean, Void>(false) {
+        @Override
+        public Boolean visitArray(ArrayType arrayType, Void p) {
+          return arrayType
+              .getComponentType()
+              .accept(
+                  new SimpleTypeVisitor8<Boolean, Void>(false) {
+                    @Override
+                    public Boolean visitDeclared(DeclaredType declaredType, Void p) {
+                      for (TypeMirror arg : declaredType.getTypeArguments()) {
+                        if (!arg.accept(this, null)) {
+                          return false;
+                        }
+                      }
+                      return true;
+                    }
+
+                    @Override
+                    public Boolean visitArray(ArrayType arrayType, Void p) {
+                      return arrayType.getComponentType().accept(this, null);
+                    }
+
+                    @Override
+                    public Boolean visitPrimitive(PrimitiveType primitiveType, Void p) {
+                      return true;
+                    }
+                  },
+                  null);
+        }
+
+        @Override
+        public Boolean visitDeclared(DeclaredType t, Void p) {
+          return true;
+        }
+      };
+}
diff --git a/java/dagger/internal/codegen/MembersInjectorGenerator.java b/java/dagger/internal/codegen/MembersInjectorGenerator.java
new file mode 100644
index 0000000..4360af7
--- /dev/null
+++ b/java/dagger/internal/codegen/MembersInjectorGenerator.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkState;
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.GwtCompatibility.gwtIncompatibleAnnotation;
+import static dagger.internal.codegen.SourceFiles.bindingTypeElementTypeVariableNames;
+import static dagger.internal.codegen.SourceFiles.frameworkFieldUsages;
+import static dagger.internal.codegen.SourceFiles.generateBindingFieldsForDependencies;
+import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
+import static dagger.internal.codegen.SourceFiles.parameterizedGeneratedTypeNameForBinding;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.membersInjectorOf;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import com.squareup.javapoet.TypeVariableName;
+import dagger.MembersInjector;
+import dagger.internal.codegen.InjectionMethods.InjectionSiteMethod;
+import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import java.util.Map.Entry;
+import java.util.Optional;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+
+/**
+ * Generates {@link MembersInjector} implementations from {@link MembersInjectionBinding} instances.
+ */
+final class MembersInjectorGenerator extends SourceFileGenerator<MembersInjectionBinding> {
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+
+  @Inject
+  MembersInjectorGenerator(
+      Filer filer, DaggerElements elements, DaggerTypes types, SourceVersion sourceVersion) {
+    super(filer, elements, sourceVersion);
+    this.types = types;
+    this.elements = elements;
+  }
+
+  @Override
+  ClassName nameGeneratedType(MembersInjectionBinding binding) {
+    return membersInjectorNameForType(binding.membersInjectedType());
+  }
+
+  @Override
+  Element originatingElement(MembersInjectionBinding binding) {
+    return binding.membersInjectedType();
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, MembersInjectionBinding binding) {
+    // Empty members injection bindings are special and don't need source files.
+    if (binding.injectionSites().isEmpty()) {
+      return Optional.empty();
+    }
+    // We don't want to write out resolved bindings -- we want to write out the generic version.
+    checkState(
+        !binding.unresolved().isPresent(),
+        "tried to generate a MembersInjector for a binding of a resolved generic type: %s",
+        binding);
+
+    ImmutableList<TypeVariableName> typeParameters = bindingTypeElementTypeVariableNames(binding);
+    TypeSpec.Builder injectorTypeBuilder =
+        classBuilder(generatedTypeName)
+            .addModifiers(PUBLIC, FINAL)
+            .addTypeVariables(typeParameters);
+
+    TypeName injectedTypeName = TypeName.get(binding.key().type());
+    TypeName implementedType = membersInjectorOf(injectedTypeName);
+    injectorTypeBuilder.addSuperinterface(implementedType);
+
+    MethodSpec.Builder injectMembersBuilder =
+        methodBuilder("injectMembers")
+            .addModifiers(PUBLIC)
+            .addAnnotation(Override.class)
+            .addParameter(injectedTypeName, "instance");
+
+    ImmutableMap<Key, FrameworkField> fields = generateBindingFieldsForDependencies(binding);
+
+    ImmutableMap.Builder<Key, FieldSpec> dependencyFieldsBuilder = ImmutableMap.builder();
+
+    MethodSpec.Builder constructorBuilder = constructorBuilder().addModifiers(PUBLIC);
+
+    // We use a static create method so that generated components can avoid having
+    // to refer to the generic types of the factory.
+    // (Otherwise they may have visibility problems referring to the types.)
+    MethodSpec.Builder createMethodBuilder =
+        methodBuilder("create")
+            .returns(implementedType)
+            .addModifiers(PUBLIC, STATIC)
+            .addTypeVariables(typeParameters);
+
+    createMethodBuilder.addCode(
+        "return new $T(", parameterizedGeneratedTypeNameForBinding(binding));
+    ImmutableList.Builder<CodeBlock> constructorInvocationParameters = ImmutableList.builder();
+
+    boolean usesRawFrameworkTypes = false;
+    UniqueNameSet fieldNames = new UniqueNameSet();
+    for (Entry<Key, FrameworkField> fieldEntry : fields.entrySet()) {
+      Key dependencyKey = fieldEntry.getKey();
+      FrameworkField bindingField = fieldEntry.getValue();
+
+      // If the dependency type is not visible to this members injector, then use the raw framework
+      // type for the field.
+      boolean useRawFrameworkType =
+          !isTypeAccessibleFrom(dependencyKey.type(), generatedTypeName.packageName());
+
+      String fieldName = fieldNames.getUniqueName(bindingField.name());
+      TypeName fieldType = useRawFrameworkType ? bindingField.type().rawType : bindingField.type();
+      FieldSpec.Builder fieldBuilder = FieldSpec.builder(fieldType, fieldName, PRIVATE, FINAL);
+      ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(fieldType, fieldName);
+
+      // If we're using the raw type for the field, then suppress the injectMembers method's
+      // unchecked-type warning and the field's and the constructor and create-method's
+      // parameters' raw-type warnings.
+      if (useRawFrameworkType) {
+        usesRawFrameworkTypes = true;
+        fieldBuilder.addAnnotation(suppressWarnings(RAWTYPES));
+        parameterBuilder.addAnnotation(suppressWarnings(RAWTYPES));
+      }
+      constructorBuilder.addParameter(parameterBuilder.build());
+      createMethodBuilder.addParameter(parameterBuilder.build());
+
+      FieldSpec field = fieldBuilder.build();
+      injectorTypeBuilder.addField(field);
+      constructorBuilder.addStatement("this.$1N = $1N", field);
+      dependencyFieldsBuilder.put(dependencyKey, field);
+      constructorInvocationParameters.add(CodeBlock.of("$N", field));
+    }
+
+    createMethodBuilder.addCode(
+        constructorInvocationParameters.build().stream().collect(toParametersCodeBlock()));
+    createMethodBuilder.addCode(");");
+
+    injectorTypeBuilder.addMethod(constructorBuilder.build());
+    injectorTypeBuilder.addMethod(createMethodBuilder.build());
+
+    ImmutableMap<Key, FieldSpec> dependencyFields = dependencyFieldsBuilder.build();
+
+    injectMembersBuilder.addCode(
+        InjectionSiteMethod.invokeAll(
+            binding.injectionSites(),
+            generatedTypeName,
+            CodeBlock.of("instance"),
+            binding.key().type(),
+            types,
+            frameworkFieldUsages(binding.dependencies(), dependencyFields)::get,
+            elements));
+
+    if (usesRawFrameworkTypes) {
+      injectMembersBuilder.addAnnotation(suppressWarnings(UNCHECKED));
+    }
+    injectorTypeBuilder.addMethod(injectMembersBuilder.build());
+
+    for (InjectionSite injectionSite : binding.injectionSites()) {
+      if (injectionSite.element().getEnclosingElement().equals(binding.membersInjectedType())) {
+        injectorTypeBuilder.addMethod(
+            InjectionSiteMethod.create(injectionSite, elements).toMethodSpec());
+      }
+    }
+
+    gwtIncompatibleAnnotation(binding).ifPresent(injectorTypeBuilder::addAnnotation);
+
+    return Optional.of(injectorTypeBuilder);
+  }
+}
diff --git a/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java b/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java
new file mode 100644
index 0000000..8e863e5
--- /dev/null
+++ b/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java
@@ -0,0 +1,65 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
+import static dagger.internal.codegen.javapoet.TypeNames.INSTANCE_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.MEMBERS_INJECTORS;
+
+import com.google.auto.common.MoreTypes;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import javax.lang.model.type.TypeMirror;
+
+/** A {@code Provider<MembersInjector<Foo>>} creation expression. */
+final class MembersInjectorProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final ProvisionBinding binding;
+
+  MembersInjectorProviderCreationExpression(
+      ProvisionBinding binding, ComponentBindingExpressions componentBindingExpressions) {
+    this.binding = checkNotNull(binding);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    TypeMirror membersInjectedType =
+        getOnlyElement(MoreTypes.asDeclared(binding.key().type()).getTypeArguments());
+
+    CodeBlock membersInjector =
+        binding.injectionSites().isEmpty()
+            ? CodeBlock.of("$T.<$T>noOp()", MEMBERS_INJECTORS, membersInjectedType)
+            : CodeBlock.of(
+                "$T.create($L)",
+                membersInjectorNameForType(MoreTypes.asTypeElement(membersInjectedType)),
+                componentBindingExpressions.getCreateMethodArgumentsCodeBlock(binding));
+
+    // TODO(ronshapiro): consider adding a MembersInjectorBindingExpression to return this directly
+    // (as it's rarely requested as a Provider).
+    return CodeBlock.of("$T.create($L)", INSTANCE_FACTORY, membersInjector);
+  }
+
+  @Override
+  public boolean useInnerSwitchingProvider() {
+    return !binding.injectionSites().isEmpty();
+  }
+}
diff --git a/java/dagger/internal/codegen/MethodBindingExpression.java b/java/dagger/internal/codegen/MethodBindingExpression.java
new file mode 100644
index 0000000..2120e80
--- /dev/null
+++ b/java/dagger/internal/codegen/MethodBindingExpression.java
@@ -0,0 +1,323 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.ComponentImplementation.FieldSpecKind.PRIVATE_METHOD_SCOPED_FIELD;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.VOLATILE;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.DoubleCheck;
+import dagger.internal.MemoizedSentinel;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.RequestKind;
+import java.util.Optional;
+import javax.lang.model.type.TypeMirror;
+
+/** A binding expression that wraps another in a nullary method on the component. */
+abstract class MethodBindingExpression extends BindingExpression {
+  private final BindingRequest request;
+  private final ResolvedBindings resolvedBindings;
+  private final ContributionBinding binding;
+  private final BindingMethodImplementation bindingMethodImplementation;
+  private final ComponentImplementation componentImplementation;
+  private final ProducerEntryPointView producerEntryPointView;
+  private final BindingExpression wrappedBindingExpression;
+  private final DaggerTypes types;
+
+  protected MethodBindingExpression(
+      BindingRequest request,
+      ResolvedBindings resolvedBindings,
+      MethodImplementationStrategy methodImplementationStrategy,
+      BindingExpression wrappedBindingExpression,
+      ComponentImplementation componentImplementation,
+      DaggerTypes types) {
+    this.request = checkNotNull(request);
+    this.resolvedBindings = resolvedBindings;
+    this.binding = resolvedBindings.contributionBinding();
+    this.bindingMethodImplementation = bindingMethodImplementation(methodImplementationStrategy);
+    this.wrappedBindingExpression = checkNotNull(wrappedBindingExpression);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.producerEntryPointView = new ProducerEntryPointView(types);
+    this.types = checkNotNull(types);
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    if (request.frameworkType().isPresent()) {
+      // Initializing a framework instance that participates in a cycle requires that the underlying
+      // FrameworkInstanceBindingExpression is invoked in order for a cycle to be detected properly.
+      // When a MethodBindingExpression wraps a FrameworkInstanceBindingExpression, the wrapped
+      // expression will only be invoked once to implement the method body. This is a hack to work
+      // around that weirdness - methodImplementation.body() will invoke the framework instance
+      // initialization again in case the field is not fully initialized.
+      // TODO(b/121196706): use a less hacky approach to fix this bug
+      Object unused = methodBody();
+    }
+    
+    addMethod();
+    return Expression.create(
+        returnType(),
+        requestingClass.equals(componentImplementation.name())
+            ? CodeBlock.of("$N()", methodName())
+            : CodeBlock.of("$T.this.$N()", componentImplementation.name(), methodName()));
+  }
+
+  @Override
+  final CodeBlock getModifiableBindingMethodImplementation(
+      ModifiableBindingMethod modifiableBindingMethod,
+      ComponentImplementation component,
+      DaggerTypes types) {
+    // A matching modifiable binding method means that we have previously created the binding method
+    // and we are now implementing it. If there is no matching method we need to first create the
+    // method. We create the method by deferring to getDependencyExpression (defined above) via a
+    // call to super.getModifiableBindingMethodImplementation().
+    if (supertypeModifiableBindingMethod().isPresent()) {
+      checkState(
+          supertypeModifiableBindingMethod().get().fulfillsSameRequestAs(modifiableBindingMethod));
+      return methodBody();
+    }
+    return super.getModifiableBindingMethodImplementation(
+        modifiableBindingMethod, component, types);
+  }
+
+  protected final Optional<ModifiableBindingMethod> supertypeModifiableBindingMethod() {
+    return componentImplementation.supertypeModifiableBindingMethod(request);
+  }
+
+  @Override
+  Expression getDependencyExpressionForComponentMethod(ComponentMethodDescriptor componentMethod,
+      ComponentImplementation component) {
+    return producerEntryPointView
+        .getProducerEntryPointField(this, componentMethod, component)
+        .orElseGet(
+            () -> super.getDependencyExpressionForComponentMethod(componentMethod, component));
+  }
+
+  /** Adds the method to the component (if necessary) the first time it's called. */
+  protected abstract void addMethod();
+
+  /** Returns the name of the method to call. */
+  protected abstract String methodName();
+
+  /**
+   * Returns {@code true} if the method of this binding expression is modifiable and is not a
+   * component method.
+   */
+  protected boolean isModifiableImplementationMethod() {
+    return false;
+  }
+
+  /** The method's body. */
+  protected final CodeBlock methodBody() {
+    return implementation(
+        wrappedBindingExpression.getDependencyExpression(componentImplementation.name())
+            ::codeBlock);
+  }
+
+  /** The method's body if this method is a component method. */
+  protected final CodeBlock methodBodyForComponentMethod(
+      ComponentMethodDescriptor componentMethod) {
+    return implementation(
+        wrappedBindingExpression.getDependencyExpressionForComponentMethod(
+                componentMethod, componentImplementation)
+            ::codeBlock);
+  }
+
+  private CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression) {
+    return bindingMethodImplementation.implementation(simpleBindingExpression);
+  }
+
+  private BindingMethodImplementation bindingMethodImplementation(
+      MethodImplementationStrategy methodImplementationStrategy) {
+    switch (methodImplementationStrategy) {
+      case SIMPLE:
+        return new SimpleMethodImplementation();
+      case SINGLE_CHECK:
+        return new SingleCheckedMethodImplementation();
+      case DOUBLE_CHECK:
+        return new DoubleCheckedMethodImplementation();
+    }
+    throw new AssertionError(methodImplementationStrategy);
+  }
+
+  /** Returns the return type for the dependency request. */
+  protected TypeMirror returnType() {
+    if (request.isRequestKind(RequestKind.INSTANCE)
+        && binding.contributedPrimitiveType().isPresent()) {
+      return binding.contributedPrimitiveType().get();
+    }
+
+    if (matchingComponentMethod().isPresent()) {
+      // Component methods are part of the user-defined API, and thus we must use the user-defined
+      // type.
+      return matchingComponentMethod().get().resolvedReturnType(types);
+    }
+
+    // If the component is abstract, this method may be overridden by another implementation in a
+    // different package for which requestedType is inaccessible. In order to make that method
+    // overridable, we use the publicly accessible type. If the method is private, we don't need to
+    // worry about this, and instead just need to check accessibility of the file we're about to
+    // write
+    TypeMirror requestedType = request.requestedType(binding.contributedType(), types);
+    return isModifiableImplementationMethod()
+        ? types.publiclyAccessibleType(requestedType)
+        : types.accessibleType(requestedType, componentImplementation.name());
+  }
+
+  private Optional<ComponentMethodDescriptor> matchingComponentMethod() {
+    return componentImplementation.componentDescriptor().firstMatchingComponentMethod(request);
+  }
+
+  /** Strateg for implementing the body of this method. */
+  enum MethodImplementationStrategy {
+    SIMPLE,
+    SINGLE_CHECK,
+    DOUBLE_CHECK,
+    ;
+  }
+
+  private abstract static class BindingMethodImplementation {
+    /**
+     * Returns the method body, which contains zero or more statements (including semicolons).
+     *
+     * <p>If the implementation has a non-void return type, the body will also include the {@code
+     * return} statement.
+     *
+     * @param simpleBindingExpression the expression to retrieve an instance of this binding without
+     *     the wrapping method.
+     */
+    abstract CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression);
+  }
+
+  /** Returns the {@code wrappedBindingExpression} directly. */
+  private static final class SimpleMethodImplementation extends BindingMethodImplementation {
+    @Override
+    CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression) {
+      return CodeBlock.of("return $L;", simpleBindingExpression.get());
+    }
+  }
+
+  /**
+   * Defines a method body for single checked caching of the given {@code wrappedBindingExpression}.
+   */
+  private final class SingleCheckedMethodImplementation extends BindingMethodImplementation {
+    private final Supplier<FieldSpec> field = Suppliers.memoize(this::createField);
+
+    @Override
+    CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression) {
+      String fieldExpression = field.get().name.equals("local") ? "this.local" : field.get().name;
+
+      CodeBlock.Builder builder = CodeBlock.builder()
+          .addStatement("Object local = $N", fieldExpression);
+
+      if (isNullable()) {
+        builder.beginControlFlow("if (local instanceof $T)", MemoizedSentinel.class);
+      } else {
+        builder.beginControlFlow("if (local == null)");
+      }
+
+      return builder
+          .addStatement("local = $L", simpleBindingExpression.get())
+          .addStatement("$N = ($T) local", fieldExpression, returnType())
+          .endControlFlow()
+          .addStatement("return ($T) local", returnType())
+          .build();
+    }
+
+    FieldSpec createField() {
+      String name =
+          componentImplementation.getUniqueFieldName(
+              request.isRequestKind(RequestKind.INSTANCE)
+                  ? KeyVariableNamer.name(binding.key())
+                  // TODO(ronshapiro): Use KeyVariableNamer directly so we don't need to use a
+                  // ResolvedBindings instance and construct a whole framework field just to get the
+                  // name
+                  : FrameworkField.forResolvedBindings(resolvedBindings, Optional.empty()).name());
+
+      FieldSpec.Builder builder = FieldSpec.builder(fieldType(), name, PRIVATE, VOLATILE);
+      if (isNullable()) {
+        builder.initializer("new $T()", MemoizedSentinel.class);
+      }
+
+      FieldSpec field = builder.build();
+      componentImplementation.addField(PRIVATE_METHOD_SCOPED_FIELD, field);
+      return field;
+    }
+
+    TypeName fieldType() {
+      if (isNullable()) {
+        // Nullable instances use `MemoizedSentinel` instead of `null` as the initialization value,
+        // so the field type must accept that and the return type
+        return TypeName.OBJECT;
+      }
+      TypeName returnType = TypeName.get(returnType());
+      return returnType.isPrimitive() ? returnType.box() : returnType;
+    }
+
+    private boolean isNullable() {
+      return request.isRequestKind(RequestKind.INSTANCE) && binding.isNullable();
+    }
+  }
+
+  /**
+   * Defines a method body for double checked caching of the given {@code wrappedBindingExpression}.
+   */
+  private final class DoubleCheckedMethodImplementation extends BindingMethodImplementation {
+    private final Supplier<String> fieldName = Suppliers.memoize(this::createField);
+
+    @Override
+    CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression) {
+      String fieldExpression = fieldName.get().equals("local") ? "this.local" : fieldName.get();
+      return CodeBlock.builder()
+          .addStatement("$T local = $L", TypeName.OBJECT, fieldExpression)
+          .beginControlFlow("if (local instanceof $T)", MemoizedSentinel.class)
+          .beginControlFlow("synchronized (local)")
+          .addStatement("local = $L", fieldExpression)
+          .beginControlFlow("if (local instanceof $T)", MemoizedSentinel.class)
+          .addStatement("local = $L", simpleBindingExpression.get())
+          .addStatement("$1L = $2T.reentrantCheck($1L, local)", fieldExpression, DoubleCheck.class)
+          .endControlFlow()
+          .endControlFlow()
+          .endControlFlow()
+          .addStatement("return ($T) local", returnType())
+          .build();
+    }
+
+    private String createField() {
+      String name =
+          componentImplementation.getUniqueFieldName(KeyVariableNamer.name(binding.key()));
+      componentImplementation.addField(
+          PRIVATE_METHOD_SCOPED_FIELD,
+          FieldSpec.builder(TypeName.OBJECT, name, PRIVATE, VOLATILE)
+              .initializer("new $T()", MemoizedSentinel.class)
+              .build());
+      return name;
+    }
+  }
+
+}
diff --git a/java/dagger/internal/codegen/MethodSignature.java b/java/dagger/internal/codegen/MethodSignature.java
new file mode 100644
index 0000000..ef5c9c5
--- /dev/null
+++ b/java/dagger/internal/codegen/MethodSignature.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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 dagger.internal.codegen.DaggerStreams.toImmutableList;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Equivalence;
+import com.google.common.collect.ImmutableList;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.List;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+@AutoValue
+abstract class MethodSignature {
+
+  abstract String name();
+
+  abstract ImmutableList<? extends Equivalence.Wrapper<? extends TypeMirror>> parameterTypes();
+
+  abstract ImmutableList<? extends Equivalence.Wrapper<? extends TypeMirror>> thrownTypes();
+
+  static MethodSignature forComponentMethod(
+      ComponentMethodDescriptor componentMethod, DeclaredType componentType, DaggerTypes types) {
+    ExecutableType methodType =
+        MoreTypes.asExecutable(types.asMemberOf(componentType, componentMethod.methodElement()));
+    return new AutoValue_MethodSignature(
+        componentMethod.methodElement().getSimpleName().toString(),
+        wrapInEquivalence(methodType.getParameterTypes()),
+        wrapInEquivalence(methodType.getThrownTypes()));
+  }
+
+  private static ImmutableList<? extends Equivalence.Wrapper<? extends TypeMirror>>
+      wrapInEquivalence(List<? extends TypeMirror> types) {
+    return types.stream().map(MoreTypes.equivalence()::wrap).collect(toImmutableList());
+  }
+}
diff --git a/java/dagger/internal/codegen/MethodSignatureFormatter.java b/java/dagger/internal/codegen/MethodSignatureFormatter.java
new file mode 100644
index 0000000..012d5b0
--- /dev/null
+++ b/java/dagger/internal/codegen/MethodSignatureFormatter.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.DiagnosticFormatting.stripCommonTypePrefixes;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifier;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Formats the signature of an {@link ExecutableElement} suitable for use in error messages.
+ */
+final class MethodSignatureFormatter extends Formatter<ExecutableElement> {
+  private final DaggerTypes types;
+
+  @Inject
+  MethodSignatureFormatter(DaggerTypes types) {
+    this.types = types;
+  }
+
+  /**
+   * A formatter that uses the type where the method is declared for the annotations and name of the
+   * method, but the method's resolved type as a member of {@code declaredType} for the key.
+   */
+  Formatter<ExecutableElement> typedFormatter(DeclaredType declaredType) {
+    return new Formatter<ExecutableElement>() {
+      @Override
+      public String format(ExecutableElement method) {
+        return MethodSignatureFormatter.this.format(
+            method,
+            MoreTypes.asExecutable(types.asMemberOf(declaredType, method)),
+            MoreElements.asType(method.getEnclosingElement()));
+      }
+    };
+  }
+
+  @Override public String format(ExecutableElement method) {
+    return format(method, Optional.empty());
+  }
+
+  /**
+   * Formats an ExecutableElement as if it were contained within the container, if the container is
+   * present.
+   */
+  public String format(ExecutableElement method, Optional<DeclaredType> container) {
+    TypeElement type = MoreElements.asType(method.getEnclosingElement());
+    ExecutableType executableType = MoreTypes.asExecutable(method.asType());
+    if (container.isPresent()) {
+      executableType = MoreTypes.asExecutable(types.asMemberOf(container.get(), method));
+      type = MoreElements.asType(container.get().asElement());
+    }
+    return format(method, executableType, type);
+  }
+
+  private String format(
+      ExecutableElement method, ExecutableType methodType, TypeElement declaringType) {
+    StringBuilder builder = new StringBuilder();
+    // TODO(cgruber): AnnotationMirror formatter.
+    List<? extends AnnotationMirror> annotations = method.getAnnotationMirrors();
+    if (!annotations.isEmpty()) {
+      Iterator<? extends AnnotationMirror> annotationIterator = annotations.iterator();
+      for (int i = 0; annotationIterator.hasNext(); i++) {
+        if (i > 0) {
+          builder.append(' ');
+        }
+        builder.append(formatAnnotation(annotationIterator.next()));
+      }
+      builder.append(' ');
+    }
+    if (method.getSimpleName().contentEquals("<init>")) {
+      builder.append(declaringType.getQualifiedName());
+    } else {
+      builder
+          .append(nameOfType(methodType.getReturnType()))
+          .append(' ')
+          .append(declaringType.getQualifiedName())
+          .append('.')
+          .append(method.getSimpleName());
+    }
+    builder.append('(');
+    checkState(method.getParameters().size() == methodType.getParameterTypes().size());
+    Iterator<? extends VariableElement> parameters = method.getParameters().iterator();
+    Iterator<? extends TypeMirror> parameterTypes = methodType.getParameterTypes().iterator();
+    for (int i = 0; parameters.hasNext(); i++) {
+      if (i > 0) {
+        builder.append(", ");
+      }
+      appendParameter(builder, parameters.next(), parameterTypes.next());
+    }
+    builder.append(')');
+    return builder.toString();
+  }
+
+  private static void appendParameter(StringBuilder builder, VariableElement parameter,
+      TypeMirror type) {
+    getQualifier(parameter)
+        .ifPresent(
+            qualifier -> {
+              builder.append(formatAnnotation(qualifier)).append(' ');
+            });
+    builder.append(nameOfType(type));
+  }
+
+  private static String nameOfType(TypeMirror type) {
+    return stripCommonTypePrefixes(type.toString());
+  }
+
+  private static String formatAnnotation(AnnotationMirror annotation) {
+    return stripCommonTypePrefixes(annotation.toString());
+  }
+}
diff --git a/java/dagger/internal/codegen/MissingBindingExpression.java b/java/dagger/internal/codegen/MissingBindingExpression.java
new file mode 100644
index 0000000..610d052
--- /dev/null
+++ b/java/dagger/internal/codegen/MissingBindingExpression.java
@@ -0,0 +1,61 @@
+/*
+ * 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 dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.Optional;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A {@link ModifiableAbstractMethodBindingExpression} for a binding that is missing when generating
+ * the abstract base class implementation of a subcomponent. The (unimplemented) method is added to
+ * the {@link ComponentImplementation} when the dependency expression is requested. The method is
+ * overridden when generating the implementation of an ancestor component.
+ */
+final class MissingBindingExpression extends ModifiableAbstractMethodBindingExpression {
+  private final ComponentImplementation componentImplementation;
+  private final BindingRequest request;
+
+  MissingBindingExpression(
+      ComponentImplementation componentImplementation,
+      BindingRequest request,
+      Optional<ModifiableBindingMethod> matchingModifiableBindingMethod,
+      Optional<ComponentMethodDescriptor> matchingComponentMethod,
+      DaggerTypes types) {
+    super(
+        componentImplementation,
+        ModifiableBindingType.MISSING,
+        request,
+        matchingModifiableBindingMethod,
+        matchingComponentMethod,
+        types);
+    this.componentImplementation = componentImplementation;
+    this.request = request;
+  }
+
+  @Override
+  String chooseMethodName() {
+    return componentImplementation.getUniqueMethodName(request);
+  }
+
+  @Override
+  protected TypeMirror contributedType() {
+    return request.key().type();
+  }
+}
diff --git a/java/dagger/internal/codegen/MissingBindingValidator.java b/java/dagger/internal/codegen/MissingBindingValidator.java
new file mode 100644
index 0000000..f39361d
--- /dev/null
+++ b/java/dagger/internal/codegen/MissingBindingValidator.java
@@ -0,0 +1,131 @@
+/*
+ * 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.common.base.Verify.verify;
+import static dagger.internal.codegen.DaggerStreams.instancesOf;
+import static dagger.internal.codegen.Keys.isValidImplicitProvisionKey;
+import static dagger.internal.codegen.Keys.isValidMembersInjectionKey;
+import static dagger.internal.codegen.RequestKinds.canBeSatisfiedByProductionBinding;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.BindingGraph;
+import dagger.model.BindingGraph.ComponentNode;
+import dagger.model.BindingGraph.DependencyEdge;
+import dagger.model.BindingGraph.MissingBinding;
+import dagger.model.BindingGraph.Node;
+import dagger.model.Key;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import javax.inject.Inject;
+import javax.lang.model.type.TypeKind;
+
+/** Reports errors for missing bindings. */
+final class MissingBindingValidator implements BindingGraphPlugin {
+
+  private final DaggerTypes types;
+  private final InjectBindingRegistry injectBindingRegistry;
+
+  @Inject
+  MissingBindingValidator(
+      DaggerTypes types, InjectBindingRegistry injectBindingRegistry) {
+    this.types = types;
+    this.injectBindingRegistry = injectBindingRegistry;
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/MissingBinding";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph graph, DiagnosticReporter diagnosticReporter) {
+    // Don't report missing bindings when validating a full binding graph or a graph built from a
+    // subcomponent.
+    if (graph.isFullBindingGraph() || graph.rootComponentNode().isSubcomponent()) {
+      return;
+    }
+    graph
+        .missingBindings()
+        .forEach(missingBinding -> reportMissingBinding(missingBinding, graph, diagnosticReporter));
+  }
+
+  private void reportMissingBinding(
+      MissingBinding missingBinding, BindingGraph graph, DiagnosticReporter diagnosticReporter) {
+    diagnosticReporter.reportBinding(
+        ERROR, missingBinding, missingBindingErrorMessage(missingBinding, graph));
+  }
+
+  private String missingBindingErrorMessage(MissingBinding missingBinding, BindingGraph graph) {
+    Key key = missingBinding.key();
+    StringBuilder errorMessage = new StringBuilder();
+    // Wildcards should have already been checked by DependencyRequestValidator.
+    verify(!key.type().getKind().equals(TypeKind.WILDCARD), "unexpected wildcard request: %s", key);
+    // TODO(ronshapiro): replace "provided" with "satisfied"?
+    errorMessage.append(key).append(" cannot be provided without ");
+    if (isValidImplicitProvisionKey(key, types)) {
+      errorMessage.append("an @Inject constructor or ");
+    }
+    errorMessage.append("an @Provides-"); // TODO(dpb): s/an/a
+    if (allIncomingDependenciesCanUseProduction(missingBinding, graph)) {
+      errorMessage.append(" or @Produces-");
+    }
+    errorMessage.append("annotated method.");
+    if (isValidMembersInjectionKey(key) && typeHasInjectionSites(key)) {
+      errorMessage.append(
+          " This type supports members injection but cannot be implicitly provided.");
+    }
+    graph.bindings(key).stream()
+        .map(binding -> binding.componentPath().currentComponent())
+        .distinct()
+        .forEach(
+            component ->
+                errorMessage
+                    .append("\nA binding with matching key exists in component: ")
+                    .append(component.getQualifiedName()));
+    return errorMessage.toString();
+  }
+
+  private boolean allIncomingDependenciesCanUseProduction(
+      MissingBinding missingBinding, BindingGraph graph) {
+    return graph.network().inEdges(missingBinding).stream()
+        .flatMap(instancesOf(DependencyEdge.class))
+        .allMatch(edge -> dependencyCanBeProduction(edge, graph));
+  }
+
+  // TODO(ronshapiro): merge with
+  // ProvisionDependencyOnProduerBindingValidator.dependencyCanUseProduction
+  private boolean dependencyCanBeProduction(DependencyEdge edge, BindingGraph graph) {
+    Node source = graph.network().incidentNodes(edge).source();
+    if (source instanceof ComponentNode) {
+      return canBeSatisfiedByProductionBinding(edge.dependencyRequest().kind());
+    }
+    if (source instanceof dagger.model.Binding) {
+      return ((dagger.model.Binding) source).isProduction();
+    }
+    throw new IllegalArgumentException(
+        "expected a dagger.model.Binding or ComponentNode: " + source);
+  }
+
+  private boolean typeHasInjectionSites(Key key) {
+    return injectBindingRegistry
+        .getOrFindMembersInjectionBinding(key)
+        .map(binding -> !binding.injectionSites().isEmpty())
+        .orElse(false);
+  }
+}
diff --git a/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java b/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java
new file mode 100644
index 0000000..412acae
--- /dev/null
+++ b/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java
@@ -0,0 +1,138 @@
+/*
+ * 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 javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.PROTECTED;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.Accessibility;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.Optional;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A {@link BindingExpression} that invokes a method that encapsulates a binding that cannot be
+ * satisfied when generating the abstract base class implementation of a subcomponent. The
+ * (unimplemented) method is added to the {@link ComponentImplementation} when the dependency
+ * expression is requested. The method is overridden when generating the implementation of an
+ * ancestor component.
+ */
+abstract class ModifiableAbstractMethodBindingExpression extends BindingExpression {
+  private final ComponentImplementation componentImplementation;
+  private final ModifiableBindingType modifiableBindingType;
+  private final BindingRequest request;
+  private final Optional<ComponentMethodDescriptor> matchingComponentMethod;
+  private final DaggerTypes types;
+  private Optional<String> methodName;
+
+  ModifiableAbstractMethodBindingExpression(
+      ComponentImplementation componentImplementation,
+      ModifiableBindingType modifiableBindingType,
+      BindingRequest request,
+      Optional<ModifiableBindingMethod> matchingModifiableBindingMethod,
+      Optional<ComponentMethodDescriptor> matchingComponentMethod,
+      DaggerTypes types) {
+    this.componentImplementation = componentImplementation;
+    this.modifiableBindingType = modifiableBindingType;
+    this.request = request;
+    this.matchingComponentMethod = matchingComponentMethod;
+    this.types = types;
+    this.methodName =
+        initializeMethodName(matchingComponentMethod, matchingModifiableBindingMethod);
+  }
+
+  /**
+   * If this binding corresponds to an existing component method, or a known modifiable binding
+   * method, use them to initialize the method name, which is a signal to call the existing method
+   * rather than emit an abstract method.
+   */
+  private static Optional<String> initializeMethodName(
+      Optional<ComponentMethodDescriptor> matchingComponentMethod,
+      Optional<ModifiableBindingMethod> matchingModifiableBindingMethod) {
+    if (matchingComponentMethod.isPresent()) {
+      return Optional.of(matchingComponentMethod.get().methodElement().getSimpleName().toString());
+    }
+    if (matchingModifiableBindingMethod.isPresent()) {
+      return Optional.of(matchingModifiableBindingMethod.get().methodSpec().name);
+    }
+    return Optional.empty();
+  }
+
+  @Override
+  final Expression getDependencyExpression(ClassName requestingClass) {
+    addUnimplementedMethod();
+    return Expression.create(
+        returnType(),
+        componentImplementation.name().equals(requestingClass)
+            ? CodeBlock.of("$N()", methodName.get())
+            : CodeBlock.of("$T.this.$N()", componentImplementation.name(), methodName.get()));
+  }
+
+  private void addUnimplementedMethod() {
+    if (!methodName.isPresent()) {
+      // Only add the method once in case of repeated references to the missing binding.
+      methodName = Optional.of(chooseMethodName());
+      TypeMirror returnType = returnType();
+      componentImplementation.addModifiableBindingMethod(
+          modifiableBindingType,
+          request,
+          returnType,
+          MethodSpec.methodBuilder(methodName.get())
+              .addModifiers(PROTECTED, ABSTRACT)
+              .returns(TypeName.get(returnType))
+              .build(),
+          false /* finalized */);
+    }
+  }
+
+  /**
+   * The return type of this abstract method expression:
+   *
+   * <ul>
+   *   <li>If there's a {@code matchingComponentMethod}, use its return type.
+   *   <li>Otherwise, use the {@linkplain DaggerTypes#publiclyAccessibleType(TypeMirror) publicly
+   *       accessible type} of the request. We can't use the {@linkplain
+   *       Accessibility#isTypeAccessibleFrom(TypeMirror, String) type accessible from the current
+   *       implementation's package} because a subclass implementation may be in a different package
+   *       from which the request type is not accessible.
+   * </ul>
+   */
+  private TypeMirror returnType() {
+    if (matchingComponentMethod.isPresent()) {
+      return matchingComponentMethod.get().resolvedReturnType(types);
+    }
+
+    TypeMirror requestedType = request.requestedType(contributedType(), types);
+    return types.publiclyAccessibleType(requestedType);
+  }
+
+  /**
+   * The {@link ContributionBinding#contributedType() type contributed} by the binding of this
+   * expression. For missing bindings, this will be the key type.
+   */
+  protected abstract TypeMirror contributedType();
+
+  /** Returns a unique 'getter' method name for the current component. */
+  abstract String chooseMethodName();
+}
diff --git a/java/dagger/internal/codegen/ModifiableBindingExpressions.java b/java/dagger/internal/codegen/ModifiableBindingExpressions.java
new file mode 100644
index 0000000..76bcb8b
--- /dev/null
+++ b/java/dagger/internal/codegen/ModifiableBindingExpressions.java
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static java.util.stream.Collectors.toList;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PROTECTED;
+import static javax.lang.model.element.Modifier.PUBLIC;
+
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.MethodSpec;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.ComponentImplementation.MethodSpecKind;
+import dagger.internal.codegen.MethodBindingExpression.MethodImplementationStrategy;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.BindingKind;
+import dagger.model.DependencyRequest;
+import java.util.Optional;
+
+/**
+ * A central repository of code expressions used to access modifiable bindings available to a
+ * component. A binding is modifiable if it can be modified across implementations of a
+ * subcomponent. This is only relevant for ahead-of-time subcomponents.
+ */
+final class ModifiableBindingExpressions {
+  private final Optional<ModifiableBindingExpressions> parent;
+  private final ComponentBindingExpressions bindingExpressions;
+  private final BindingGraph graph;
+  private final ComponentImplementation componentImplementation;
+  private final CompilerOptions compilerOptions;
+  private final DaggerTypes types;
+
+  ModifiableBindingExpressions(
+      Optional<ModifiableBindingExpressions> parent,
+      ComponentBindingExpressions bindingExpressions,
+      BindingGraph graph,
+      ComponentImplementation componentImplementation,
+      CompilerOptions compilerOptions,
+      DaggerTypes types) {
+    this.parent = parent;
+    this.bindingExpressions = bindingExpressions;
+    this.graph = graph;
+    this.componentImplementation = componentImplementation;
+    this.compilerOptions = compilerOptions;
+    this.types = types;
+  }
+
+  /**
+   * Adds {@code method} to the component implementation. If the binding for the method is
+   * modifiable, also registers the relevant modifiable binding information.
+   */
+  void addPossiblyModifiableComponentMethod(
+      ComponentMethodDescriptor componentMethod, MethodSpec method) {
+    BindingRequest request = bindingRequest(componentMethod.dependencyRequest().get());
+    ModifiableBindingType modifiableBindingType = getModifiableBindingType(request);
+    if (modifiableBindingType.isModifiable()) {
+      componentImplementation.addModifiableComponentMethod(
+          modifiableBindingType,
+          request,
+          componentMethod.resolvedReturnType(types),
+          method,
+          newModifiableBindingWillBeFinalized(modifiableBindingType, request));
+    } else {
+      componentImplementation.addMethod(MethodSpecKind.COMPONENT_METHOD, method);
+    }
+  }
+
+  /**
+   * Returns the implementation of a modifiable binding method originally defined in a supertype
+   * implementation of this subcomponent. Returns {@link Optional#empty()} when the binding cannot
+   * or should not be modified by the current binding graph.
+   */
+  Optional<ModifiableBindingMethod> possiblyReimplementedMethod(
+      ModifiableBindingMethod modifiableBindingMethod) {
+    checkState(componentImplementation.superclassImplementation().isPresent());
+    BindingRequest request = modifiableBindingMethod.request();
+    ModifiableBindingType newModifiableBindingType = getModifiableBindingType(request);
+    ModifiableBindingType oldModifiableBindingType = modifiableBindingMethod.type();
+    boolean modifiableBindingTypeChanged =
+        !newModifiableBindingType.equals(oldModifiableBindingType);
+
+    ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
+    // Don't reimplement modifiable bindings that were perceived to be provision bindings in a
+    // superclass implementation but are now production bindings.
+    if ((modifiableBindingTypeChanged
+            // Optional bindings don't need the same treatment since the only transition they can
+            // make is empty -> present. In that case, the Producer<Optional<T>> will be overridden
+            // and the absentOptionalProvider() will be a dangling reference that is never attempted
+            // to be overridden.
+            || newModifiableBindingType.equals(ModifiableBindingType.MULTIBINDING))
+        && resolvedBindings != null
+        && resolvedBindings.bindingType().equals(BindingType.PRODUCTION)
+        && !request.canBeSatisfiedByProductionBinding()) {
+      return oldModifiableBindingType.hasBaseClassImplementation()
+          ? Optional.empty()
+          : Optional.of(
+              reimplementedMethod(
+                  modifiableBindingMethod,
+                  newModifiableBindingType,
+                  new PrunedConcreteMethodBindingExpression(),
+                  componentImplementation.isAbstract()));
+    }
+
+    if (modifiableBindingTypeChanged
+        && !newModifiableBindingType.hasBaseClassImplementation()
+        && (oldModifiableBindingType.hasBaseClassImplementation()
+            || componentImplementation.isAbstract())) {
+      // We don't want to override one abstract method with another one. However, If the component
+      // is not abstract (such as a transition from GENERATED_INSTANCE -> MISSING), we must provide
+      // an implementation like normal.
+      return Optional.empty();
+    }
+
+    if (modifiableBindingTypeChanged
+        || shouldModifyImplementation(newModifiableBindingType, request)) {
+      boolean markMethodFinal =
+          knownModifiableBindingWillBeFinalized(modifiableBindingMethod)
+              // no need to mark the method final if the component implementation will be final
+              && componentImplementation.isAbstract();
+      return Optional.of(
+          reimplementedMethod(
+              modifiableBindingMethod,
+              newModifiableBindingType,
+              bindingExpressions.getBindingExpression(request),
+              markMethodFinal));
+    }
+    return Optional.empty();
+  }
+
+  /**
+   * Returns a new {@link ModifiableBindingMethod} that overrides {@code supertypeMethod} and is
+   * implemented with {@code bindingExpression}.
+   */
+  private ModifiableBindingMethod reimplementedMethod(
+      ModifiableBindingMethod supertypeMethod,
+      ModifiableBindingType newModifiableBindingType,
+      BindingExpression bindingExpression,
+      boolean markMethodFinal) {
+    MethodSpec baseMethod = supertypeMethod.methodSpec();
+    return supertypeMethod.reimplement(
+        newModifiableBindingType,
+        MethodSpec.methodBuilder(baseMethod.name)
+            .addModifiers(baseMethod.modifiers.contains(PUBLIC) ? PUBLIC : PROTECTED)
+            .addModifiers(markMethodFinal ? ImmutableSet.of(FINAL) : ImmutableSet.of())
+            .returns(baseMethod.returnType)
+            .addAnnotation(Override.class)
+            .addCode(
+                bindingExpression.getModifiableBindingMethodImplementation(
+                    supertypeMethod, componentImplementation, types))
+            .build(),
+        markMethodFinal);
+  }
+
+  /**
+   * Returns true if a modifiable binding method that was registered in a superclass implementation
+   * of this subcomponent should be marked as "finalized" if it is being overridden by this
+   * subcomponent implementation. "Finalized" means we should not attempt to modify the binding in
+   * any subcomponent subclass.
+   */
+  private boolean knownModifiableBindingWillBeFinalized(
+      ModifiableBindingMethod modifiableBindingMethod) {
+    ModifiableBindingType newModifiableBindingType =
+        getModifiableBindingType(modifiableBindingMethod.request());
+    if (!newModifiableBindingType.isModifiable()) {
+      // If a modifiable binding has become non-modifiable it is final by definition.
+      return true;
+    }
+    return modifiableBindingWillBeFinalized(
+        newModifiableBindingType,
+        shouldModifyImplementation(newModifiableBindingType, modifiableBindingMethod.request()));
+  }
+
+  /**
+   * Returns true if a newly discovered modifiable binding method, once it is defined in this
+   * subcomponent implementation, should be marked as "finalized", meaning we should not attempt to
+   * modify the binding in any subcomponent subclass.
+   */
+  private boolean newModifiableBindingWillBeFinalized(
+      ModifiableBindingType modifiableBindingType, BindingRequest request) {
+    return modifiableBindingWillBeFinalized(
+        modifiableBindingType, shouldModifyImplementation(modifiableBindingType, request));
+  }
+
+  /**
+   * Returns true if we shouldn't attempt to further modify a modifiable binding once we complete
+   * the implementation for the current subcomponent.
+   */
+  private boolean modifiableBindingWillBeFinalized(
+      ModifiableBindingType modifiableBindingType, boolean modifyingBinding) {
+    switch (modifiableBindingType) {
+      case MISSING:
+      case BINDS_METHOD_WITH_MISSING_DEPENDENCY:
+      case GENERATED_INSTANCE:
+      case OPTIONAL:
+      case INJECTION:
+        // Once we modify any of the above a single time, then they are finalized.
+        return modifyingBinding;
+      case MULTIBINDING:
+        return false;
+      default:
+        throw new IllegalStateException(
+            String.format(
+                "Building binding expression for unsupported ModifiableBindingType [%s].",
+                modifiableBindingType));
+    }
+  }
+
+  /**
+   * Creates a binding expression for a binding if it may be modified across implementations of a
+   * subcomponent.
+   */
+  Optional<BindingExpression> maybeCreateModifiableBindingExpression(BindingRequest request) {
+    ModifiableBindingType type = getModifiableBindingType(request);
+    if (!type.isModifiable()) {
+      return Optional.empty();
+    }
+    return Optional.of(createModifiableBindingExpression(type, request));
+  }
+
+  /** Creates a binding expression for a modifiable binding. */
+  private BindingExpression createModifiableBindingExpression(
+      ModifiableBindingType type, BindingRequest request) {
+    ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
+    Optional<ModifiableBindingMethod> matchingModifiableBindingMethod =
+        componentImplementation.getModifiableBindingMethod(request);
+    Optional<ComponentMethodDescriptor> matchingComponentMethod =
+        graph.componentDescriptor().firstMatchingComponentMethod(request);
+    switch (type) {
+      case GENERATED_INSTANCE:
+        // If the subcomponent is abstract then we need to define an (un-implemented)
+        // DeferredModifiableBindingExpression.
+        if (componentImplementation.isAbstract()) {
+          return new DeferredModifiableBindingExpression(
+              componentImplementation,
+              type,
+              resolvedBindings.contributionBinding(),
+              request,
+              matchingModifiableBindingMethod,
+              matchingComponentMethod,
+              types);
+        }
+        // Otherwise return a concrete implementation.
+        return bindingExpressions.createBindingExpression(resolvedBindings, request);
+
+      case MISSING:
+        // If we need an expression for a missing binding and the current implementation is
+        // abstract, then we need an (un-implemented) MissingBindingExpression.
+        if (componentImplementation.isAbstract()) {
+          return new MissingBindingExpression(
+              componentImplementation,
+              request,
+              matchingModifiableBindingMethod,
+              matchingComponentMethod,
+              types);
+        }
+        // Otherwise we assume that it is valid to have a missing binding as it is part of a
+        // dependency chain that has been passively pruned.
+        // TODO(b/117833324): Identify pruned bindings when generating the subcomponent
+        // implementation in which the bindings are pruned. If we hold a reference to the binding
+        // graph used to generate a given implementation then we can compare a implementation's
+        // graph with its superclass implementation's graph to detect pruned dependency branches.
+        return new PrunedConcreteMethodBindingExpression();
+
+      case BINDS_METHOD_WITH_MISSING_DEPENDENCY:
+        checkState(componentImplementation.isAbstract());
+        return new DeferredModifiableBindingExpression(
+            componentImplementation,
+            type,
+            resolvedBindings.contributionBinding(),
+            request,
+            matchingModifiableBindingMethod,
+            matchingComponentMethod,
+            types);
+
+      case OPTIONAL:
+      case MULTIBINDING:
+      case INJECTION:
+        return bindingExpressions.wrapInMethod(
+            resolvedBindings,
+            request,
+            bindingExpressions.createBindingExpression(resolvedBindings, request));
+      default:
+        throw new IllegalStateException(
+            String.format(
+                "Building binding expression for unsupported ModifiableBindingType [%s].", type));
+    }
+  }
+
+  /**
+   * The reason why a binding may need to be modified across implementations of a subcomponent, if
+   * at all.
+   */
+  ModifiableBindingType getModifiableBindingType(BindingRequest request) {
+    if (!compilerOptions.aheadOfTimeSubcomponents()) {
+      return ModifiableBindingType.NONE;
+    }
+
+    // When generating a component the binding is not considered modifiable. Bindings are modifiable
+    // only across subcomponent implementations.
+    if (!componentImplementation.componentDescriptor().isSubcomponent()) {
+      return ModifiableBindingType.NONE;
+    }
+
+    if (request.requestKind().filter(RequestKinds::isDerivedFromProvider).isPresent()) {
+      return ModifiableBindingType.NONE;
+    }
+
+    if (resolvedInThisComponent(request)) {
+      ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
+      if (resolvedBindings.contributionBindings().isEmpty()) {
+        // TODO(ronshapiro): Confirm whether a resolved binding must have a single contribution
+        // binding.
+        return ModifiableBindingType.NONE;
+      }
+
+      ContributionBinding binding = resolvedBindings.contributionBinding();
+      if (binding.requiresGeneratedInstance()) {
+        return ModifiableBindingType.GENERATED_INSTANCE;
+      }
+
+      if (binding.kind().equals(BindingKind.DELEGATE)
+          && graph
+              .contributionBindings()
+              .get(getOnlyElement(binding.dependencies()).key())
+              .isEmpty()) {
+        return ModifiableBindingType.BINDS_METHOD_WITH_MISSING_DEPENDENCY;
+      }
+
+      if (binding.kind().equals(BindingKind.OPTIONAL) && binding.dependencies().isEmpty()) {
+        // only empty optional bindings can be modified
+        return ModifiableBindingType.OPTIONAL;
+      }
+
+      if (binding.isSyntheticMultibinding()) {
+        return ModifiableBindingType.MULTIBINDING;
+      }
+
+      if (binding.kind().equals(BindingKind.INJECTION)) {
+        return ModifiableBindingType.INJECTION;
+      }
+    } else if (!resolvableBinding(request)) {
+      return ModifiableBindingType.MISSING;
+    }
+
+    return ModifiableBindingType.NONE;
+  }
+
+  /**
+   * Returns true if the current binding graph can, and should, modify a binding by overriding a
+   * modifiable binding method.
+   */
+  private boolean shouldModifyImplementation(
+      ModifiableBindingType modifiableBindingType, BindingRequest request) {
+    ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
+    if (request.requestKind().isPresent()) {
+      switch (request.requestKind().get()) {
+        case FUTURE:
+          // Futures backed by production bindings are always requested by a Producer.get() call, so
+          // if the binding is modifiable, the producer will be wrapped in a modifiable method and
+          // the future can refer to that  method; even if the producer binding is modified,
+          // getModifiableProducer().get() will never need to be modified. Furthermore, because
+          // cancellation is treated by wrapped producers, and those producers point to the
+          // modifiable producer wrapper methods, we never need or want to change the access of
+          // these wrapped producers for entry methods
+          //
+          // Futures backed by provision bindings are inlined and contain no wrapping producer, so
+          // if the binding is modifiable and is resolved as a provision binding in a superclass
+          // but later resolved as a production binding, we can't take the same shortcut as before.
+          Optional<ComponentImplementation> superclassImplementation =
+              componentImplementation.superclassImplementation();
+          if (superclassImplementation.isPresent()) {
+            if (superclassImplementation.get().isDeserializedImplementation()) {
+              // TODO(b/117833324): consider serializing the binding type so that we don't need to
+              // branch here. Or, instead, consider removing this optimization entirely if there
+              // aren't that many FUTURE entry point methods to justify the extra code.
+              break;
+            } else {
+              return bindingTypeChanged(request, resolvedBindings);
+            }
+          }
+          return false;
+
+        case LAZY:
+        case PROVIDER_OF_LAZY:
+          // Lazy and ProviderOfLazy are always created from a Provider, and therefore this request
+          // never needs to be modifiable. It will refer (via DoubleCheck.lazy() or
+          // ProviderOfLazy.create()) to the modifiable method and not the framework instance.
+          return false;
+
+        case MEMBERS_INJECTION:
+        case PRODUCED:
+          // MEMBERS_INJECTION has a completely different code path for binding expressions, and
+          // PRODUCED requests are only requestable in @Produces methods, which are hidden from
+          // generated components inside Producer factories
+          throw new AssertionError(request);
+
+        case INSTANCE:
+        case PROVIDER:
+        case PRODUCER:
+          // These may be modifiable, so run through the regular logic. They're spelled out
+          // explicitly so that ErrorProne will detect if a new enum value is created and missing
+          // from this list.
+          break;
+      }
+    }
+
+    switch (modifiableBindingType) {
+      case GENERATED_INSTANCE:
+        return !componentImplementation.isAbstract();
+
+      case MISSING:
+        // TODO(b/117833324): investigate beder@'s comment about having intermediate component
+        // ancestors satisfy missing bindings of their children with their own missing binding
+        // methods so that we can minimize the cases where we need to reach into doubly-nested
+        // descendant component implementations.
+
+        // Implement a missing binding if it is resolvable, or if we're generating a concrete
+        // subcomponent implementation. If a binding is still missing when the subcomponent
+        // implementation is concrete then it is assumed to be part of a dependency that would have
+        // been passively pruned when implementing the full component hierarchy.
+        return resolvableBinding(request) || !componentImplementation.isAbstract();
+
+      case BINDS_METHOD_WITH_MISSING_DEPENDENCY:
+        DependencyRequest dependency =
+            getOnlyElement(resolvedBindings.contributionBinding().dependencies());
+        return !graph.contributionBindings().get(dependency.key()).isEmpty();
+
+      case OPTIONAL:
+        // Only override optional binding methods if we have a non-empty binding.
+        return !resolvedBindings.contributionBinding().dependencies().isEmpty();
+
+      case MULTIBINDING:
+        // Only modify a multibinding if there are new contributions.
+        return !componentImplementation
+            .superclassContributionsMade(request)
+            .containsAll(
+                resolvedBindings.contributionBinding().dependencies().stream()
+                    .map(DependencyRequest::key)
+                    .collect(toList()));
+
+      case INJECTION:
+        return !resolvedBindings.contributionBinding().kind().equals(BindingKind.INJECTION);
+
+      default:
+        throw new IllegalStateException(
+            String.format(
+                "Overriding modifiable binding method with unsupported ModifiableBindingType [%s].",
+                modifiableBindingType));
+    }
+  }
+
+  /**
+   * Returns {@code true} if the {@link BindingType} for {@code request} is not the same in this
+   * implementation and it's superclass implementation.
+   */
+  private boolean bindingTypeChanged(BindingRequest request, ResolvedBindings resolvedBindings) {
+    BindingGraph superclassGraph =
+        componentImplementation.superclassImplementation().get().graph();
+    ResolvedBindings superclassBindings = superclassGraph.resolvedBindings(request);
+    return superclassBindings != null
+        && resolvedBindings != null
+        && !superclassBindings.bindingType().equals(resolvedBindings.bindingType());
+  }
+
+  /**
+   * Returns true if the binding can be resolved by the graph for this component or any parent
+   * component.
+   */
+  private boolean resolvableBinding(BindingRequest request) {
+    for (ModifiableBindingExpressions expressions = this;
+        expressions != null;
+        expressions = expressions.parent.orElse(null)) {
+      if (expressions.resolvedInThisComponent(request)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /** Returns true if the binding can be resolved by the graph for this component. */
+  private boolean resolvedInThisComponent(BindingRequest request) {
+    ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
+    return resolvedBindings != null
+        && !resolvedBindings.bindingsOwnedBy(graph.componentDescriptor()).isEmpty();
+  }
+
+  /**
+   * Wraps a modifiable binding expression in a method that can be overridden in a subclass
+   * implementation.
+   */
+  BindingExpression wrapInModifiableMethodBindingExpression(
+      BindingRequest request,
+      ResolvedBindings resolvedBindings,
+      MethodImplementationStrategy methodImplementationStrategy,
+      BindingExpression wrappedBindingExpression) {
+    ModifiableBindingType modifiableBindingType = getModifiableBindingType(request);
+    checkState(modifiableBindingType.isModifiable());
+    return new ModifiableConcreteMethodBindingExpression(
+        request,
+        resolvedBindings,
+        methodImplementationStrategy,
+        wrappedBindingExpression,
+        modifiableBindingType,
+        componentImplementation,
+        newModifiableBindingWillBeFinalized(modifiableBindingType, request),
+        types);
+  }
+}
diff --git a/java/dagger/internal/codegen/ModifiableBindingMethods.java b/java/dagger/internal/codegen/ModifiableBindingMethods.java
new file mode 100644
index 0000000..ead708d
--- /dev/null
+++ b/java/dagger/internal/codegen/ModifiableBindingMethods.java
@@ -0,0 +1,133 @@
+/*
+ * 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.common.base.Verify.verify;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Equivalence;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.squareup.javapoet.MethodSpec;
+import java.util.Map;
+import java.util.Optional;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A registry for those methods which each wrap a binding whose definition may be modified across
+ * each class in the class hierarchy implementing a subcomponent. Subcomponent implementations are
+ * spread across a class hierarchy when generating ahead-of-time subcomponents. There is one
+ * subcomponent implementation class for each of the subcomponent's ancestor components. An instance
+ * of {@link ModifiableBindingMethod} is associated with a single class in this hierarchy. For a
+ * given subcomponent implementation class we can use the {@link ModifiableBindingMethod}s of its
+ * superclasses to know what binding methods to attempt to modify.
+ */
+final class ModifiableBindingMethods {
+  private final Map<BindingRequest, ModifiableBindingMethod> methods = Maps.newLinkedHashMap();
+
+  /** Registers a new method encapsulating a modifiable binding. */
+  void addModifiableMethod(
+      ModifiableBindingType type,
+      BindingRequest request,
+      TypeMirror returnType,
+      MethodSpec method,
+      boolean finalized) {
+    // It's ok for the type to not be modifiable, since it could be overriding a previously
+    // modifiable method (such as with addReimplementedMethod).
+    addMethod(ModifiableBindingMethod.create(type, request, returnType, method, finalized));
+  }
+
+  /** Registers a reimplemented modifiable method. */
+  void addReimplementedMethod(ModifiableBindingMethod method) {
+    addMethod(method);
+  }
+
+  private void addMethod(ModifiableBindingMethod method) {
+    ModifiableBindingMethod previousMethod = methods.put(method.request(), method);
+    verify(
+        previousMethod == null,
+        "registering %s but %s is already registered for the same binding request",
+        method,
+        previousMethod);
+  }
+
+  /** Returns all {@link ModifiableBindingMethod}s that have not been marked as finalized. */
+  ImmutableMap<BindingRequest, ModifiableBindingMethod> getNonFinalizedMethods() {
+    return ImmutableMap.copyOf(Maps.filterValues(methods, m -> !m.finalized()));
+  }
+
+  /** Returns the {@link ModifiableBindingMethod} for the given binding if present. */
+  Optional<ModifiableBindingMethod> getMethod(BindingRequest request) {
+    return Optional.ofNullable(methods.get(request));
+  }
+
+  /** Returns all of the {@link ModifiableBindingMethod}s. */
+  ImmutableList<ModifiableBindingMethod> allMethods() {
+    return ImmutableList.copyOf(methods.values());
+  }
+
+  /** Whether a given binding has been marked as finalized. */
+  // TODO(ronshapiro): possibly rename this to something that indicates that the BindingRequest for
+  // `method` has been finalized in *this* component implementation?
+  boolean finalized(ModifiableBindingMethod method) {
+    ModifiableBindingMethod storedMethod = methods.get(method.request());
+    return storedMethod != null && storedMethod.finalized();
+  }
+
+  @AutoValue
+  abstract static class ModifiableBindingMethod {
+    private static ModifiableBindingMethod create(
+        ModifiableBindingType type,
+        BindingRequest request,
+        TypeMirror returnType,
+        MethodSpec methodSpec,
+        boolean finalized) {
+      return new AutoValue_ModifiableBindingMethods_ModifiableBindingMethod(
+          type, request, MoreTypes.equivalence().wrap(returnType), methodSpec, finalized);
+    }
+
+    /** Creates a {@ModifiableBindingMethod} that reimplements the current method. */
+    ModifiableBindingMethod reimplement(
+        ModifiableBindingType newModifiableBindingType,
+        MethodSpec newImplementation,
+        boolean finalized) {
+      return new AutoValue_ModifiableBindingMethods_ModifiableBindingMethod(
+          newModifiableBindingType, request(), returnTypeWrapper(), newImplementation, finalized);
+    }
+
+    abstract ModifiableBindingType type();
+
+    abstract BindingRequest request();
+
+    final TypeMirror returnType() {
+      return returnTypeWrapper().get();
+    }
+
+    abstract Equivalence.Wrapper<TypeMirror> returnTypeWrapper();
+
+    abstract MethodSpec methodSpec();
+
+    abstract boolean finalized();
+
+    /** Whether a {@link ModifiableBindingMethod} is for the same binding request. */
+    boolean fulfillsSameRequestAs(ModifiableBindingMethod other) {
+      return request().equals(other.request());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ModifiableBindingType.java b/java/dagger/internal/codegen/ModifiableBindingType.java
new file mode 100644
index 0000000..7e43ec1
--- /dev/null
+++ b/java/dagger/internal/codegen/ModifiableBindingType.java
@@ -0,0 +1,99 @@
+/*
+ * 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.common.collect.ImmutableSet;
+
+/**
+ * A label for a binding indicating whether, and how, it may be redefined across implementations of
+ * a subcomponent.
+ *
+ * <p>A subcomponent has multiple implementations only when generating ahead-of-time subcomponents.
+ * Specifically, each subcomponent type in a component hierarchy is implemented as an abstract
+ * class, and descendent components are implemented as abstract inner classes. A consequence of this
+ * is that a given subcomponent has an implementation for each ancestor component. Each
+ * implementation represents a different sub-binding-graph of the full subcomponent. A binding is
+ * modifiable if it's definition may change depending on the characteristics of its ancestor
+ * components.
+ */
+enum ModifiableBindingType {
+  /** A binding that is not modifiable */
+  NONE,
+
+  /**
+   * A binding that is missing when generating the abstract base class implementation of a
+   * subcomponent.
+   */
+  MISSING,
+
+  /**
+   * A binding that requires an instance of a generated type. These binding are modifiable in the
+   * sense that they are encapsulated in a method when they are first required, possibly in an
+   * abstract implementation of a subcomponent, where, in general, no concrete instances of
+   * generated types are available, and the method is satisfied in a final concrete implementation.
+   */
+  GENERATED_INSTANCE,
+
+  /**
+   * Multibindings may have contributions come from any ancestor component. Therefore, each
+   * implementation of a subcomponent may have newly available contributions, and so the binding
+   * method is reimplemented with each subcomponent implementation.
+   */
+  MULTIBINDING,
+
+  /**
+   * A Optional binding that may be empty when looking at a partial binding graph, but bound to a
+   * value when considering the complete binding graph, thus modifiable across subcomponent
+   * implementations.
+   */
+  OPTIONAL,
+
+  /**
+   * If a binding is defined according to an {@code @Inject} annotated constructor on the object it
+   * is valid for that binding to be redefined a single time by an {@code @Provides} annotated
+   * module method. It is possible that the {@code @Provides} binding isn't available in a partial
+   * binding graph, but becomes available when considering a more complete binding graph, therefore
+   * such bindings are modifiable across subcomponent implementations.
+   */
+  INJECTION,
+
+  /**
+   * A {@link dagger.Binds} method whose dependency is {@link #MISSING}.
+   *
+   * <p>There's not much to do for @Binds bindings if the dependency is missing - at best, if the
+   * dependency is a weaker scope/unscoped, we save only a few lines that implement the scoping. But
+   * it's also possible, if the dependency is the same or stronger scope, that no extra code is
+   * necessary, in which case we'd be overriding a method that just returns another.
+   */
+  BINDS_METHOD_WITH_MISSING_DEPENDENCY,
+  ;
+
+  private static final ImmutableSet<ModifiableBindingType> TYPES_WITH_BASE_CLASS_IMPLEMENTATIONS =
+      ImmutableSet.of(NONE, INJECTION, MULTIBINDING, OPTIONAL);
+
+  boolean isModifiable() {
+    return !equals(NONE);
+  }
+
+  /**
+   * Returns true if the method encapsulating the modifiable binding should have a concrete
+   * implementation in the abstract base class for a subcomponent.
+   */
+  boolean hasBaseClassImplementation() {
+    return TYPES_WITH_BASE_CLASS_IMPLEMENTATIONS.contains(this);
+  }
+}
diff --git a/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java b/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java
new file mode 100644
index 0000000..907466b
--- /dev/null
+++ b/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PROTECTED;
+
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.Optional;
+
+/**
+ * A binding expression that wraps a modifiable binding expression in a public, no-arg method.
+ *
+ * <p>Dependents of this binding expression will just call the modifiable binding method.
+ */
+final class ModifiableConcreteMethodBindingExpression extends MethodBindingExpression {
+
+  private final BindingRequest request;
+  private final ModifiableBindingType modifiableBindingType;
+  private final ComponentImplementation componentImplementation;
+  private final boolean bindingCannotBeModified;
+  private Optional<String> methodName = Optional.empty();
+
+  ModifiableConcreteMethodBindingExpression(
+      BindingRequest request,
+      ResolvedBindings resolvedBindings,
+      MethodImplementationStrategy methodImplementationStrategy,
+      BindingExpression wrappedBindingExpression,
+      ModifiableBindingType modifiableBindingType,
+      ComponentImplementation componentImplementation,
+      boolean bindingCannotBeModified,
+      DaggerTypes types) {
+    super(
+        request,
+        resolvedBindings,
+        methodImplementationStrategy,
+        wrappedBindingExpression,
+        componentImplementation,
+        types);
+    this.request = checkNotNull(request);
+    this.modifiableBindingType = checkNotNull(modifiableBindingType);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.bindingCannotBeModified = bindingCannotBeModified;
+  }
+
+  @Override
+  protected void addMethod() {
+    if (methodName.isPresent()) {
+      return;
+    }
+
+    if (supertypeModifiableBindingMethod().isPresent()) {
+      methodName = supertypeModifiableBindingMethod().map(method -> method.methodSpec().name);
+      return;
+    }
+
+    // Add the modifiable binding method to the component if we haven't already.
+    methodName = Optional.of(componentImplementation.getUniqueMethodName(request));
+    componentImplementation.addModifiableBindingMethod(
+        modifiableBindingType,
+        request,
+        returnType(),
+        methodBuilder(methodName.get())
+            .addModifiers(bindingCannotBeModified ? PRIVATE : PROTECTED)
+            .returns(TypeName.get(returnType()))
+            .addCode(methodBody())
+            .build(),
+        bindingCannotBeModified);
+  }
+
+  @Override
+  protected String methodName() {
+    checkState(methodName.isPresent(), "addMethod() must be called before methodName().");
+    return methodName.get();
+  }
+
+  @Override
+  protected boolean isModifiableImplementationMethod() {
+    return true;
+  }
+}
diff --git a/java/dagger/internal/codegen/ModuleAnnotation.java b/java/dagger/internal/codegen/ModuleAnnotation.java
new file mode 100644
index 0000000..27dd071
--- /dev/null
+++ b/java/dagger/internal/codegen/ModuleAnnotation.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2019 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.AnnotationMirrors.getAnnotationValue;
+import static com.google.auto.common.MoreTypes.asTypeElement;
+import static com.google.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.MoreAnnotationValues.asAnnotationValues;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import dagger.Module;
+import dagger.producers.ProducerModule;
+import java.lang.annotation.Annotation;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.TypeElement;
+
+/** A {@code @Module} or {@code @ProducerModule} annotation. */
+@AutoValue
+abstract class ModuleAnnotation {
+  private static final ImmutableSet<Class<? extends Annotation>> MODULE_ANNOTATIONS =
+      ImmutableSet.of(Module.class, ProducerModule.class);
+
+  /** The annotation itself. */
+  // This does not use AnnotationMirrors.equivalence() because we want the actual annotation
+  // instance.
+  abstract AnnotationMirror annotation();
+
+  /** The type of the annotation. */
+  @Memoized
+  Class<?> annotationClass() {
+    try {
+      return Class.forName(
+          asTypeElement(annotation().getAnnotationType()).getQualifiedName().toString());
+    } catch (ClassNotFoundException e) {
+      AssertionError assertionError = new AssertionError();
+      assertionError.initCause(e);
+      throw assertionError;
+    }
+  }
+
+  /**
+   * The types specified in the {@code includes} attribute.
+   *
+   * @throws IllegalArgumentException if any of the values are error types
+   */
+  @Memoized
+  ImmutableList<TypeElement> includes() {
+    return includesAsAnnotationValues().stream()
+        .map(MoreAnnotationValues::asType)
+        .map(MoreTypes::asTypeElement)
+        .collect(toImmutableList());
+  }
+
+  /** The values specified in the {@code includes} attribute. */
+  @Memoized
+  ImmutableList<AnnotationValue> includesAsAnnotationValues() {
+    return asAnnotationValues(getAnnotationValue(annotation(), "includes"));
+  }
+
+  /**
+   * The types specified in the {@code subcomponents} attribute.
+   *
+   * @throws IllegalArgumentException if any of the values are error types
+   */
+  @Memoized
+  ImmutableList<TypeElement> subcomponents() {
+    return subcomponentsAsAnnotationValues().stream()
+        .map(MoreAnnotationValues::asType)
+        .map(MoreTypes::asTypeElement)
+        .collect(toImmutableList());
+  }
+
+  /** The values specified in the {@code subcomponents} attribute. */
+  @Memoized
+  ImmutableList<AnnotationValue> subcomponentsAsAnnotationValues() {
+    return asAnnotationValues(getAnnotationValue(annotation(), "subcomponents"));
+  }
+
+  /** Returns {@code true} if the argument is a {@code @Module} or {@code @ProducerModule}. */
+  static boolean isModuleAnnotation(AnnotationMirror annotation) {
+    return MODULE_ANNOTATIONS.stream()
+        .map(Class::getCanonicalName)
+        .anyMatch(asTypeElement(annotation.getAnnotationType()).getQualifiedName()::contentEquals);
+  }
+
+  /** The module annotation types. */
+  static ImmutableSet<Class<? extends Annotation>> moduleAnnotations() {
+    return MODULE_ANNOTATIONS;
+  }
+
+  /**
+   * Creates an object that represents a {@code @Module} or {@code @ProducerModule}.
+   *
+   * @throws IllegalArgumentException if {@link #isModuleAnnotation(AnnotationMirror)} returns
+   *     {@code false}
+   */
+  static ModuleAnnotation moduleAnnotation(AnnotationMirror annotation) {
+    checkArgument(
+        isModuleAnnotation(annotation),
+        "%s is not a Module or ProducerModule annotation",
+        annotation);
+    return new AutoValue_ModuleAnnotation(annotation);
+  }
+
+  /**
+   * Returns an object representing the {@code @Module} or {@code @ProducerModule} annotation if one
+   * annotates {@code typeElement}.
+   */
+  static Optional<ModuleAnnotation> moduleAnnotation(TypeElement typeElement) {
+    return getAnyAnnotation(typeElement, Module.class, ProducerModule.class)
+        .map(ModuleAnnotation::moduleAnnotation);
+  }
+}
diff --git a/java/dagger/internal/codegen/ModuleConstructorProxyGenerator.java b/java/dagger/internal/codegen/ModuleConstructorProxyGenerator.java
new file mode 100644
index 0000000..5f0d687
--- /dev/null
+++ b/java/dagger/internal/codegen/ModuleConstructorProxyGenerator.java
@@ -0,0 +1,85 @@
+/*
+ * 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.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.ModuleKind.checkIsModule;
+import static dagger.internal.codegen.ModuleProxies.nonPublicNullaryConstructor;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.Optional;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Generates a {@code public static} method that calls {@code new SomeModule()} for modules that
+ * don't have {@linkplain ModuleProxies#nonPublicNullaryConstructor(TypeElement,
+ * DaggerElements) publicly accessible constructors}.
+ */
+// TODO(dpb): See if this can become a SourceFileGenerator<ModuleDescriptor> instead. Doing so may
+// cause ModuleProcessingStep to defer elements multiple times.
+final class ModuleConstructorProxyGenerator extends SourceFileGenerator<TypeElement> {
+  private final DaggerElements elements;
+
+  @Inject
+  ModuleConstructorProxyGenerator(
+      Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
+    super(filer, elements, sourceVersion);
+    this.elements = elements;
+  }
+
+  @Override
+  ClassName nameGeneratedType(TypeElement moduleElement) {
+    return ModuleProxies.constructorProxyTypeName(moduleElement);
+  }
+
+  @Override
+  Element originatingElement(TypeElement moduleElement) {
+    return moduleElement;
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, TypeElement moduleElement) {
+    checkIsModule(moduleElement);
+    return nonPublicNullaryConstructor(moduleElement, elements).isPresent()
+        ? Optional.of(buildProxy(generatedTypeName, moduleElement))
+        : Optional.empty();
+  }
+
+  private TypeSpec.Builder buildProxy(ClassName generatedTypeName, TypeElement moduleElement) {
+    return classBuilder(generatedTypeName)
+        .addModifiers(PUBLIC, FINAL)
+        .addMethod(constructorBuilder().addModifiers(PRIVATE).build())
+        .addMethod(
+            methodBuilder("newInstance")
+                .addModifiers(PUBLIC, STATIC)
+                .returns(ClassName.get(moduleElement))
+                .addStatement("return new $T()", moduleElement)
+                .build());
+  }
+}
diff --git a/java/dagger/internal/codegen/ModuleDescriptor.java b/java/dagger/internal/codegen/ModuleDescriptor.java
new file mode 100644
index 0000000..ac7a4b7
--- /dev/null
+++ b/java/dagger/internal/codegen/ModuleDescriptor.java
@@ -0,0 +1,225 @@
+/*
+ * 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.MoreElements.getPackage;
+import static com.google.auto.common.MoreElements.isAnnotationPresent;
+import static com.google.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.Verify.verify;
+import static com.google.common.collect.Iterables.transform;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
+import static dagger.internal.codegen.SourceFiles.classFileName;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnnotationPresent;
+import static javax.lang.model.type.TypeKind.DECLARED;
+import static javax.lang.model.type.TypeKind.NONE;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.graph.Traverser;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.squareup.javapoet.ClassName;
+import dagger.Binds;
+import dagger.BindsOptionalOf;
+import dagger.Module;
+import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.model.Key;
+import dagger.multibindings.Multibinds;
+import dagger.producers.Produces;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+@AutoValue
+abstract class ModuleDescriptor {
+
+  abstract TypeElement moduleElement();
+
+  abstract ImmutableSet<TypeElement> includedModules();
+
+  abstract ImmutableSet<ContributionBinding> bindings();
+
+  /** The multibinding declarations contained in this module. */
+  abstract ImmutableSet<MultibindingDeclaration> multibindingDeclarations();
+
+  /** The {@link Module#subcomponents() subcomponent declarations} contained in this module. */
+  abstract ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations();
+
+  /** The {@link Binds} method declarations that define delegate bindings. */
+  abstract ImmutableSet<DelegateDeclaration> delegateDeclarations();
+
+  /** The {@link BindsOptionalOf} method declarations that define optional bindings. */
+  abstract ImmutableSet<OptionalBindingDeclaration> optionalDeclarations();
+
+  /** The kind of the module. */
+  abstract ModuleKind kind();
+
+  /** Returns all of the bindings declared in this module. */
+  @Memoized
+  ImmutableSet<BindingDeclaration> allBindingDeclarations() {
+    return ImmutableSet.<BindingDeclaration>builder()
+        .addAll(bindings())
+        .addAll(delegateDeclarations())
+        .addAll(multibindingDeclarations())
+        .addAll(optionalDeclarations())
+        .addAll(subcomponentDeclarations())
+        .build();
+  }
+
+  /** Returns the keys of all bindings declared by this module. */
+  ImmutableSet<Key> allBindingKeys() {
+    return allBindingDeclarations().stream().map(BindingDeclaration::key).collect(toImmutableSet());
+  }
+
+  @Singleton
+  static final class Factory implements ClearableCache {
+    private final DaggerElements elements;
+    private final BindingFactory bindingFactory;
+    private final MultibindingDeclaration.Factory multibindingDeclarationFactory;
+    private final DelegateDeclaration.Factory bindingDelegateDeclarationFactory;
+    private final SubcomponentDeclaration.Factory subcomponentDeclarationFactory;
+    private final OptionalBindingDeclaration.Factory optionalBindingDeclarationFactory;
+    private final Map<TypeElement, ModuleDescriptor> cache = new HashMap<>();
+
+    @Inject
+    Factory(
+        DaggerElements elements,
+        BindingFactory bindingFactory,
+        MultibindingDeclaration.Factory multibindingDeclarationFactory,
+        DelegateDeclaration.Factory bindingDelegateDeclarationFactory,
+        SubcomponentDeclaration.Factory subcomponentDeclarationFactory,
+        OptionalBindingDeclaration.Factory optionalBindingDeclarationFactory) {
+      this.elements = elements;
+      this.bindingFactory = bindingFactory;
+      this.multibindingDeclarationFactory = multibindingDeclarationFactory;
+      this.bindingDelegateDeclarationFactory = bindingDelegateDeclarationFactory;
+      this.subcomponentDeclarationFactory = subcomponentDeclarationFactory;
+      this.optionalBindingDeclarationFactory = optionalBindingDeclarationFactory;
+    }
+
+    ModuleDescriptor create(TypeElement moduleElement) {
+      return reentrantComputeIfAbsent(cache, moduleElement, this::createUncached);
+    }
+
+    ModuleDescriptor createUncached(TypeElement moduleElement) {
+      ImmutableSet.Builder<ContributionBinding> bindings = ImmutableSet.builder();
+      ImmutableSet.Builder<DelegateDeclaration> delegates = ImmutableSet.builder();
+      ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations =
+          ImmutableSet.builder();
+      ImmutableSet.Builder<OptionalBindingDeclaration> optionalDeclarations =
+          ImmutableSet.builder();
+
+      for (ExecutableElement moduleMethod : methodsIn(elements.getAllMembers(moduleElement))) {
+        if (isAnnotationPresent(moduleMethod, Provides.class)) {
+          bindings.add(bindingFactory.providesMethodBinding(moduleMethod, moduleElement));
+        }
+        if (isAnnotationPresent(moduleMethod, Produces.class)) {
+          bindings.add(bindingFactory.producesMethodBinding(moduleMethod, moduleElement));
+        }
+        if (isAnnotationPresent(moduleMethod, Binds.class)) {
+          delegates.add(bindingDelegateDeclarationFactory.create(moduleMethod, moduleElement));
+        }
+        if (isAnnotationPresent(moduleMethod, Multibinds.class)) {
+          multibindingDeclarations.add(
+              multibindingDeclarationFactory.forMultibindsMethod(moduleMethod, moduleElement));
+        }
+        if (isAnnotationPresent(moduleMethod, BindsOptionalOf.class)) {
+          optionalDeclarations.add(
+              optionalBindingDeclarationFactory.forMethod(moduleMethod, moduleElement));
+        }
+      }
+
+      return new AutoValue_ModuleDescriptor(
+          moduleElement,
+          ImmutableSet.copyOf(collectIncludedModules(new LinkedHashSet<>(), moduleElement)),
+          bindings.build(),
+          multibindingDeclarations.build(),
+          subcomponentDeclarationFactory.forModule(moduleElement),
+          delegates.build(),
+          optionalDeclarations.build(),
+          ModuleKind.forAnnotatedElement(moduleElement).get());
+    }
+
+    /** Returns all the modules transitively included by given modules, including the arguments. */
+    ImmutableSet<ModuleDescriptor> transitiveModules(Iterable<TypeElement> modules) {
+      return ImmutableSet.copyOf(
+          Traverser.forGraph(
+                  (ModuleDescriptor module) -> transform(module.includedModules(), this::create))
+              .depthFirstPreOrder(transform(modules, this::create)));
+    }
+
+    @CanIgnoreReturnValue
+    private Set<TypeElement> collectIncludedModules(
+        Set<TypeElement> includedModules, TypeElement moduleElement) {
+      TypeMirror superclass = moduleElement.getSuperclass();
+      if (!superclass.getKind().equals(NONE)) {
+        verify(superclass.getKind().equals(DECLARED));
+        TypeElement superclassElement = MoreTypes.asTypeElement(superclass);
+        if (!superclassElement.getQualifiedName().contentEquals(Object.class.getCanonicalName())) {
+          collectIncludedModules(includedModules, superclassElement);
+        }
+      }
+      moduleAnnotation(moduleElement)
+          .ifPresent(
+              moduleAnnotation -> {
+                includedModules.addAll(moduleAnnotation.includes());
+                includedModules.addAll(implicitlyIncludedModules(moduleElement));
+              });
+      return includedModules;
+    }
+
+    // @ContributesAndroidInjector generates a module that is implicitly included in the enclosing
+    // module
+    private ImmutableSet<TypeElement> implicitlyIncludedModules(TypeElement moduleElement) {
+      TypeElement contributesAndroidInjector =
+          elements.getTypeElement("dagger.android.ContributesAndroidInjector");
+      if (contributesAndroidInjector == null) {
+        return ImmutableSet.of();
+      }
+      return methodsIn(moduleElement.getEnclosedElements()).stream()
+          .filter(method -> isAnnotationPresent(method, contributesAndroidInjector.asType()))
+          .map(method -> elements.checkTypePresent(implicitlyIncludedModuleName(method)))
+          .collect(toImmutableSet());
+    }
+
+    private String implicitlyIncludedModuleName(ExecutableElement method) {
+      return getPackage(method).getQualifiedName()
+          + "."
+          + classFileName(ClassName.get(MoreElements.asType(method.getEnclosingElement())))
+          + "_"
+          + LOWER_CAMEL.to(UPPER_CAMEL, method.getSimpleName().toString());
+    }
+
+    @Override
+    public void clearCache() {
+      cache.clear();
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ModuleGenerator.java b/java/dagger/internal/codegen/ModuleGenerator.java
new file mode 100644
index 0000000..161b47b
--- /dev/null
+++ b/java/dagger/internal/codegen/ModuleGenerator.java
@@ -0,0 +1,27 @@
+/*
+ * 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 java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import javax.inject.Qualifier;
+
+/** Qualifier for a {@link SourceFileGenerator} for modules. */
+@Qualifier
+@Retention(RUNTIME)
+@interface ModuleGenerator {}
diff --git a/java/dagger/internal/codegen/ModuleKind.java b/java/dagger/internal/codegen/ModuleKind.java
new file mode 100644
index 0000000..c93d8ce
--- /dev/null
+++ b/java/dagger/internal/codegen/ModuleKind.java
@@ -0,0 +1,107 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import dagger.Module;
+import dagger.producers.ProducerModule;
+import java.lang.annotation.Annotation;
+import java.util.EnumSet;
+import java.util.Optional;
+import java.util.Set;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.TypeElement;
+
+/** Enumeration of the kinds of modules. */
+enum ModuleKind {
+  /** {@code @Module} */
+  MODULE(Module.class),
+
+  /** {@code @ProducerModule} */
+  PRODUCER_MODULE(ProducerModule.class);
+
+  /** Returns the annotations for modules of the given kinds. */
+  static ImmutableSet<Class<? extends Annotation>> annotationsFor(Set<ModuleKind> kinds) {
+    return kinds.stream().map(ModuleKind::annotation).collect(toImmutableSet());
+  }
+
+  /**
+   * Returns the kind of an annotated element if it is annotated with one of the module {@linkplain
+   * #annotation() annotations}.
+   *
+   * @throws IllegalArgumentException if the element is annotated with more than one of the module
+   *     annotations
+   */
+  static Optional<ModuleKind> forAnnotatedElement(TypeElement element) {
+    Set<ModuleKind> kinds = EnumSet.noneOf(ModuleKind.class);
+    for (ModuleKind kind : values()) {
+      if (MoreElements.isAnnotationPresent(element, kind.annotation())) {
+        kinds.add(kind);
+      }
+    }
+
+    if (kinds.size() > 1) {
+      throw new IllegalArgumentException(
+          element + " cannot be annotated with more than one of " + annotationsFor(kinds));
+    }
+    return kinds.stream().findAny();
+  }
+
+  static void checkIsModule(TypeElement moduleElement) {
+    checkArgument(forAnnotatedElement(moduleElement).isPresent());
+  }
+
+  private final Class<? extends Annotation> moduleAnnotation;
+
+  ModuleKind(Class<? extends Annotation> moduleAnnotation) {
+    this.moduleAnnotation = moduleAnnotation;
+  }
+
+  /**
+   * Returns the annotation mirror for this module kind on the given type.
+   *
+   * @throws IllegalArgumentException if the annotation is not present on the type
+   */
+  AnnotationMirror getModuleAnnotation(TypeElement element) {
+    Optional<AnnotationMirror> result = getAnnotationMirror(element, moduleAnnotation);
+    checkArgument(
+        result.isPresent(), "annotation %s is not present on type %s", moduleAnnotation, element);
+    return result.get();
+  }
+
+  /** Returns the annotation that marks a module of this kind. */
+  Class<? extends Annotation> annotation() {
+    return moduleAnnotation;
+  }
+
+  /** Returns the kinds of modules that a module of this kind is allowed to include. */
+  ImmutableSet<ModuleKind> legalIncludedModuleKinds() {
+    switch (this) {
+      case MODULE:
+        return Sets.immutableEnumSet(MODULE);
+      case PRODUCER_MODULE:
+        return Sets.immutableEnumSet(MODULE, PRODUCER_MODULE);
+    }
+    throw new AssertionError(this);
+  }
+}
diff --git a/java/dagger/internal/codegen/ModuleProcessingStep.java b/java/dagger/internal/codegen/ModuleProcessingStep.java
index 2bf3354..27cd531 100644
--- a/java/dagger/internal/codegen/ModuleProcessingStep.java
+++ b/java/dagger/internal/codegen/ModuleProcessingStep.java
@@ -28,19 +28,7 @@
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.BindingFactory;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.DelegateDeclaration;
-import dagger.internal.codegen.binding.DelegateDeclaration.Factory;
-import dagger.internal.codegen.binding.ProductionBinding;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.validation.ModuleValidator;
-import dagger.internal.codegen.validation.TypeCheckingProcessingStep;
-import dagger.internal.codegen.validation.ValidationReport;
-import dagger.internal.codegen.writing.InaccessibleMapKeyProxyGenerator;
-import dagger.internal.codegen.writing.ModuleGenerator;
+import dagger.internal.codegen.DelegateDeclaration.Factory;
 import dagger.producers.ProducerModule;
 import dagger.producers.Produces;
 import java.lang.annotation.Annotation;
@@ -65,7 +53,6 @@
   private final SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator;
   private final InaccessibleMapKeyProxyGenerator inaccessibleMapKeyProxyGenerator;
   private final DelegateDeclaration.Factory delegateDeclarationFactory;
-  private final KotlinMetadataUtil metadataUtil;
   private final Set<TypeElement> processedModuleElements = Sets.newLinkedHashSet();
 
   @Inject
@@ -77,8 +64,7 @@
       SourceFileGenerator<ProductionBinding> producerFactoryGenerator,
       @ModuleGenerator SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator,
       InaccessibleMapKeyProxyGenerator inaccessibleMapKeyProxyGenerator,
-      Factory delegateDeclarationFactory,
-      KotlinMetadataUtil metadataUtil) {
+      Factory delegateDeclarationFactory) {
     super(MoreElements::asType);
     this.messager = messager;
     this.moduleValidator = moduleValidator;
@@ -88,7 +74,6 @@
     this.moduleConstructorProxyGenerator = moduleConstructorProxyGenerator;
     this.inaccessibleMapKeyProxyGenerator = inaccessibleMapKeyProxyGenerator;
     this.delegateDeclarationFactory = delegateDeclarationFactory;
-    this.metadataUtil = metadataUtil;
   }
 
   @Override
@@ -110,38 +95,23 @@
     if (processedModuleElements.contains(module)) {
       return;
     }
-    // For backwards compatibility, we allow a companion object to be annotated with @Module even
-    // though it's no longer required. However, we skip processing the companion object itself
-    // because it will now be processed when processing the companion object's enclosing class.
-    if (metadataUtil.isCompanionObjectClass(module)) {
-      // TODO(danysantiago): Be strict about annotating companion objects with @Module,
-      //  i.e. tell user to annotate parent instead.
-      return;
-    }
     ValidationReport<TypeElement> report = moduleValidator.validate(module);
     report.printMessagesTo(messager);
     if (report.isClean()) {
-      generateForMethodsIn(module);
-      if (metadataUtil.hasEnclosedCompanionObject(module)) {
-        generateForMethodsIn(metadataUtil.getEnclosedCompanionObject(module));
+      for (ExecutableElement method : methodsIn(module.getEnclosedElements())) {
+        if (isAnnotationPresent(method, Provides.class)) {
+          generate(factoryGenerator, bindingFactory.providesMethodBinding(method, module));
+        } else if (isAnnotationPresent(method, Produces.class)) {
+          generate(producerFactoryGenerator, bindingFactory.producesMethodBinding(method, module));
+        } else if (isAnnotationPresent(method, Binds.class)) {
+          inaccessibleMapKeyProxyGenerator.generate(bindsMethodBinding(module, method), messager);
+        }
       }
+      moduleConstructorProxyGenerator.generate(module, messager);
     }
     processedModuleElements.add(module);
   }
 
-  private void generateForMethodsIn(TypeElement module) {
-    for (ExecutableElement method : methodsIn(module.getEnclosedElements())) {
-      if (isAnnotationPresent(method, Provides.class)) {
-        generate(factoryGenerator, bindingFactory.providesMethodBinding(method, module));
-      } else if (isAnnotationPresent(method, Produces.class)) {
-        generate(producerFactoryGenerator, bindingFactory.producesMethodBinding(method, module));
-      } else if (isAnnotationPresent(method, Binds.class)) {
-        inaccessibleMapKeyProxyGenerator.generate(bindsMethodBinding(module, method), messager);
-      }
-    }
-    moduleConstructorProxyGenerator.generate(module, messager);
-  }
-
   private <B extends ContributionBinding> void generate(
       SourceFileGenerator<B> generator, B binding) {
     generator.generate(binding, messager);
diff --git a/java/dagger/internal/codegen/ModuleProxies.java b/java/dagger/internal/codegen/ModuleProxies.java
new file mode 100644
index 0000000..6426e69
--- /dev/null
+++ b/java/dagger/internal/codegen/ModuleProxies.java
@@ -0,0 +1,81 @@
+/*
+ * 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 dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.util.ElementFilter.constructorsIn;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.langmodel.Accessibility;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.Optional;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+/** Convenience methods for generating and using module constructor proxy methods. */
+final class ModuleProxies {
+  /** The name of the class that hosts the module constructor proxy method. */
+  static ClassName constructorProxyTypeName(TypeElement moduleElement) {
+    ModuleKind.checkIsModule(moduleElement);
+    ClassName moduleClassName = ClassName.get(moduleElement);
+    return moduleClassName
+        .topLevelClassName()
+        .peerClass(SourceFiles.classFileName(moduleClassName) + "_Proxy");
+  }
+
+  /**
+   * The module constructor being proxied. A proxy is generated if it is not publicly accessible and
+   * has no arguments. If an implicit reference to the enclosing class exists, or the module is
+   * abstract, no proxy method can be generated.
+   */
+  // TODO(ronshapiro): make this an @Injectable class that injects DaggerElements
+  static Optional<ExecutableElement> nonPublicNullaryConstructor(
+      TypeElement moduleElement, DaggerElements elements) {
+    ModuleKind.checkIsModule(moduleElement);
+    if (moduleElement.getModifiers().contains(ABSTRACT)
+        || (moduleElement.getNestingKind().isNested()
+            && !moduleElement.getModifiers().contains(STATIC))) {
+      return Optional.empty();
+    }
+    return constructorsIn(elements.getAllMembers(moduleElement)).stream()
+        .filter(constructor -> !Accessibility.isElementPubliclyAccessible(constructor))
+        .filter(constructor -> !constructor.getModifiers().contains(PRIVATE))
+        .filter(constructor -> constructor.getParameters().isEmpty())
+        .findAny();
+  }
+
+  /**
+   * Returns a code block that creates a new module instance, either by invoking the nullary
+   * constructor if it's accessible from {@code requestingClass} or else by invoking the
+   * constructor's generated proxy method.
+   */
+  static CodeBlock newModuleInstance(
+      TypeElement moduleElement, ClassName requestingClass, DaggerElements elements) {
+    ModuleKind.checkIsModule(moduleElement);
+    String packageName = requestingClass.packageName();
+    return nonPublicNullaryConstructor(moduleElement, elements)
+        .filter(constructor -> !isElementAccessibleFrom(constructor, packageName))
+        .map(
+            constructor ->
+                CodeBlock.of("$T.newInstance()", constructorProxyTypeName(moduleElement)))
+        .orElse(CodeBlock.of("new $T()", moduleElement));
+  }
+}
diff --git a/java/dagger/internal/codegen/ModuleValidator.java b/java/dagger/internal/codegen/ModuleValidator.java
new file mode 100644
index 0000000..094bf34
--- /dev/null
+++ b/java/dagger/internal/codegen/ModuleValidator.java
@@ -0,0 +1,644 @@
+/*
+ * Copyright (C) 2014 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.AnnotationMirrors.getAnnotatedAnnotations;
+import static com.google.auto.common.Visibility.PRIVATE;
+import static com.google.auto.common.Visibility.PUBLIC;
+import static com.google.auto.common.Visibility.effectiveVisibilityOfElement;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.ComponentAnnotation.componentAnnotation;
+import static dagger.internal.codegen.ComponentAnnotation.isComponentAnnotation;
+import static dagger.internal.codegen.ComponentAnnotation.subcomponentAnnotation;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.getCreatorAnnotations;
+import static dagger.internal.codegen.ConfigurationAnnotations.getSubcomponentCreator;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.ModuleAnnotation.isModuleAnnotation;
+import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
+import static dagger.internal.codegen.MoreAnnotationMirrors.simpleName;
+import static dagger.internal.codegen.MoreAnnotationValues.asType;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.ValidationType.NONE;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
+import static java.util.EnumSet.noneOf;
+import static java.util.stream.Collectors.joining;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.auto.common.Visibility;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Sets;
+import com.google.errorprone.annotations.FormatMethod;
+import dagger.Module;
+import dagger.Subcomponent;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.BindingGraph;
+import dagger.producers.ProducerModule;
+import dagger.producers.ProductionSubcomponent;
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Scope;
+import javax.inject.Singleton;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleAnnotationValueVisitor8;
+import javax.lang.model.util.SimpleTypeVisitor8;
+
+/**
+ * A {@linkplain ValidationReport validator} for {@link Module}s or {@link ProducerModule}s.
+ */
+@Singleton
+final class ModuleValidator {
+  private static final ImmutableSet<Class<? extends Annotation>> SUBCOMPONENT_TYPES =
+      ImmutableSet.of(Subcomponent.class, ProductionSubcomponent.class);
+  private static final ImmutableSet<Class<? extends Annotation>> SUBCOMPONENT_CREATOR_TYPES =
+      ImmutableSet.of(
+          Subcomponent.Builder.class,
+          Subcomponent.Factory.class,
+          ProductionSubcomponent.Builder.class,
+          ProductionSubcomponent.Factory.class);
+  private static final Optional<Class<?>> ANDROID_PROCESSOR;
+  private static final String CONTRIBUTES_ANDROID_INJECTOR_NAME =
+      "dagger.android.ContributesAndroidInjector";
+  private static final String ANDROID_PROCESSOR_NAME = "dagger.android.processor.AndroidProcessor";
+
+  static {
+    Class<?> clazz;
+    try {
+      clazz = Class.forName(ANDROID_PROCESSOR_NAME, false, ModuleValidator.class.getClassLoader());
+    } catch (ClassNotFoundException ignored) {
+      clazz = null;
+    }
+    ANDROID_PROCESSOR = Optional.ofNullable(clazz);
+  }
+
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+  private final AnyBindingMethodValidator anyBindingMethodValidator;
+  private final MethodSignatureFormatter methodSignatureFormatter;
+  private final ComponentDescriptorFactory componentDescriptorFactory;
+  private final BindingGraphFactory bindingGraphFactory;
+  private final BindingGraphConverter bindingGraphConverter;
+  private final BindingGraphValidator bindingGraphValidator;
+  private final CompilerOptions compilerOptions;
+  private final Map<TypeElement, ValidationReport<TypeElement>> cache = new HashMap<>();
+  private final Set<TypeElement> knownModules = new HashSet<>();
+
+  @Inject
+  ModuleValidator(
+      DaggerTypes types,
+      DaggerElements elements,
+      AnyBindingMethodValidator anyBindingMethodValidator,
+      MethodSignatureFormatter methodSignatureFormatter,
+      ComponentDescriptorFactory componentDescriptorFactory,
+      BindingGraphFactory bindingGraphFactory,
+      BindingGraphConverter bindingGraphConverter,
+      BindingGraphValidator bindingGraphValidator,
+      CompilerOptions compilerOptions) {
+    this.types = types;
+    this.elements = elements;
+    this.anyBindingMethodValidator = anyBindingMethodValidator;
+    this.methodSignatureFormatter = methodSignatureFormatter;
+    this.componentDescriptorFactory = componentDescriptorFactory;
+    this.bindingGraphFactory = bindingGraphFactory;
+    this.bindingGraphConverter = bindingGraphConverter;
+    this.bindingGraphValidator = bindingGraphValidator;
+    this.compilerOptions = compilerOptions;
+  }
+
+  /**
+   * Adds {@code modules} to the set of module types that will be validated during this compilation
+   * step. If a component or module includes a module that is not in this set, that included module
+   * is assumed to be valid because it was processed in a previous compilation step. If it were
+   * invalid, that previous compilation step would have failed and blocked this one.
+   *
+   * <p>This logic depends on this method being called before {@linkplain #validate(TypeElement)
+   * validating} any module or {@linkplain #validateReferencedModules(TypeElement, AnnotationMirror,
+   * ImmutableSet, Set) component}.
+   */
+  void addKnownModules(Collection<TypeElement> modules) {
+    knownModules.addAll(modules);
+  }
+
+  /** Returns a validation report for a module type. */
+  ValidationReport<TypeElement> validate(TypeElement module) {
+    return validate(module, new HashSet<>());
+  }
+
+  private ValidationReport<TypeElement> validate(
+      TypeElement module, Set<TypeElement> visitedModules) {
+    if (visitedModules.add(module)) {
+      return reentrantComputeIfAbsent(cache, module, m -> validateUncached(module, visitedModules));
+    }
+    return ValidationReport.about(module).build();
+  }
+
+  private ValidationReport<TypeElement> validateUncached(
+      TypeElement module, Set<TypeElement> visitedModules) {
+    ValidationReport.Builder<TypeElement> builder = ValidationReport.about(module);
+    ModuleKind moduleKind = ModuleKind.forAnnotatedElement(module).get();
+
+    ListMultimap<String, ExecutableElement> allMethodsByName = ArrayListMultimap.create();
+    ListMultimap<String, ExecutableElement> bindingMethodsByName = ArrayListMultimap.create();
+
+    Set<ModuleMethodKind> methodKinds = noneOf(ModuleMethodKind.class);
+    TypeElement contributesAndroidInjectorElement =
+        elements.getTypeElement(CONTRIBUTES_ANDROID_INJECTOR_NAME);
+    TypeMirror contributesAndroidInjector =
+        contributesAndroidInjectorElement != null
+            ? contributesAndroidInjectorElement.asType()
+            : null;
+    for (ExecutableElement moduleMethod : methodsIn(module.getEnclosedElements())) {
+      if (anyBindingMethodValidator.isBindingMethod(moduleMethod)) {
+        builder.addSubreport(anyBindingMethodValidator.validate(moduleMethod));
+        bindingMethodsByName.put(moduleMethod.getSimpleName().toString(), moduleMethod);
+        methodKinds.add(ModuleMethodKind.ofMethod(moduleMethod));
+      }
+      allMethodsByName.put(moduleMethod.getSimpleName().toString(), moduleMethod);
+
+      for (AnnotationMirror annotation : moduleMethod.getAnnotationMirrors()) {
+        if (!ANDROID_PROCESSOR.isPresent()
+            && MoreTypes.equivalence()
+                .equivalent(contributesAndroidInjector, annotation.getAnnotationType())) {
+          builder.addSubreport(
+              ValidationReport.about(moduleMethod)
+                  .addError(
+                      String.format(
+                          "@%s was used, but %s was not found on the processor path",
+                          CONTRIBUTES_ANDROID_INJECTOR_NAME, ANDROID_PROCESSOR_NAME))
+                  .build());
+          break;
+        }
+      }
+    }
+
+    if (methodKinds.containsAll(
+        EnumSet.of(ModuleMethodKind.ABSTRACT_DECLARATION, ModuleMethodKind.INSTANCE_BINDING))) {
+      builder.addError(
+          String.format(
+              "A @%s may not contain both non-static and abstract binding methods",
+              moduleKind.annotation().getSimpleName()));
+    }
+
+    validateModuleVisibility(module, moduleKind, builder);
+    validateMethodsWithSameName(builder, bindingMethodsByName);
+    if (module.getKind() != ElementKind.INTERFACE) {
+      validateBindingMethodOverrides(module, builder, allMethodsByName, bindingMethodsByName);
+    }
+    validateModifiers(module, builder);
+    validateReferencedModules(module, moduleKind, visitedModules, builder);
+    validateReferencedSubcomponents(module, moduleKind, builder);
+    validateNoScopeAnnotationsOnModuleElement(module, moduleKind, builder);
+    validateSelfCycles(module, builder);
+
+    if (builder.build().isClean()
+        && !compilerOptions.fullBindingGraphValidationType(module).equals(NONE)) {
+      validateModuleBindings(module, builder);
+    }
+
+    return builder.build();
+  }
+
+  private void validateReferencedSubcomponents(
+      final TypeElement subject,
+      ModuleKind moduleKind,
+      final ValidationReport.Builder<TypeElement> builder) {
+    // TODO(ronshapiro): use validateTypesAreDeclared when it is checked in
+    ModuleAnnotation moduleAnnotation = moduleAnnotation(moduleKind.getModuleAnnotation(subject));
+    for (AnnotationValue subcomponentAttribute :
+        moduleAnnotation.subcomponentsAsAnnotationValues()) {
+      asType(subcomponentAttribute)
+          .accept(
+              new SimpleTypeVisitor8<Void, Void>() {
+                @Override
+                protected Void defaultAction(TypeMirror e, Void aVoid) {
+                  builder.addError(
+                      e + " is not a valid subcomponent type",
+                      subject,
+                      moduleAnnotation.annotation(),
+                      subcomponentAttribute);
+                  return null;
+                }
+
+                @Override
+                public Void visitDeclared(DeclaredType declaredType, Void aVoid) {
+                  TypeElement attributeType = MoreTypes.asTypeElement(declaredType);
+                  if (isAnyAnnotationPresent(attributeType, SUBCOMPONENT_TYPES)) {
+                    validateSubcomponentHasBuilder(
+                        attributeType, moduleAnnotation.annotation(), builder);
+                  } else {
+                    builder.addError(
+                        isAnyAnnotationPresent(attributeType, SUBCOMPONENT_CREATOR_TYPES)
+                            ? moduleSubcomponentsIncludesCreator(attributeType)
+                            : moduleSubcomponentsIncludesNonSubcomponent(attributeType),
+                        subject,
+                        moduleAnnotation.annotation(),
+                        subcomponentAttribute);
+                  }
+
+                  return null;
+                }
+              },
+              null);
+    }
+  }
+
+  private static String moduleSubcomponentsIncludesNonSubcomponent(TypeElement notSubcomponent) {
+    return notSubcomponent.getQualifiedName()
+        + " is not a @Subcomponent or @ProductionSubcomponent";
+  }
+
+  private static String moduleSubcomponentsIncludesCreator(
+      TypeElement moduleSubcomponentsAttribute) {
+    TypeElement subcomponentType =
+        MoreElements.asType(moduleSubcomponentsAttribute.getEnclosingElement());
+    ComponentCreatorAnnotation creatorAnnotation =
+        getOnlyElement(getCreatorAnnotations(moduleSubcomponentsAttribute));
+    return String.format(
+        "%s is a @%s.%s. Did you mean to use %s?",
+        moduleSubcomponentsAttribute.getQualifiedName(),
+        subcomponentAnnotation(subcomponentType).get().simpleName(),
+        creatorAnnotation.creatorKind().typeName(),
+        subcomponentType.getQualifiedName());
+  }
+
+  private static void validateSubcomponentHasBuilder(
+      TypeElement subcomponentAttribute,
+      AnnotationMirror moduleAnnotation,
+      ValidationReport.Builder<TypeElement> builder) {
+    if (getSubcomponentCreator(subcomponentAttribute).isPresent()) {
+      return;
+    }
+    builder.addError(
+        moduleSubcomponentsDoesntHaveCreator(subcomponentAttribute, moduleAnnotation),
+        builder.getSubject(),
+        moduleAnnotation);
+  }
+
+  private static String moduleSubcomponentsDoesntHaveCreator(
+      TypeElement subcomponent, AnnotationMirror moduleAnnotation) {
+    return String.format(
+        "%1$s doesn't have a @%2$s.Builder or @%2$s.Factory, which is required when used with "
+            + "@%3$s.subcomponents",
+        subcomponent.getQualifiedName(),
+        subcomponentAnnotation(subcomponent).get().simpleName(),
+        simpleName(moduleAnnotation));
+  }
+
+  enum ModuleMethodKind {
+    ABSTRACT_DECLARATION,
+    INSTANCE_BINDING,
+    STATIC_BINDING,
+    ;
+
+    static ModuleMethodKind ofMethod(ExecutableElement moduleMethod) {
+      if (moduleMethod.getModifiers().contains(STATIC)) {
+        return STATIC_BINDING;
+      } else if (moduleMethod.getModifiers().contains(ABSTRACT)) {
+        return ABSTRACT_DECLARATION;
+      } else {
+        return INSTANCE_BINDING;
+      }
+    }
+  }
+
+  private void validateModifiers(
+      TypeElement subject, ValidationReport.Builder<TypeElement> builder) {
+    // This coupled with the check for abstract modules in ComponentValidator guarantees that
+    // only modules without type parameters are referenced from @Component(modules={...}).
+    if (!subject.getTypeParameters().isEmpty() && !subject.getModifiers().contains(ABSTRACT)) {
+      builder.addError("Modules with type parameters must be abstract", subject);
+    }
+  }
+
+  private void validateMethodsWithSameName(
+      ValidationReport.Builder<TypeElement> builder,
+      ListMultimap<String, ExecutableElement> bindingMethodsByName) {
+    for (Entry<String, Collection<ExecutableElement>> entry :
+        bindingMethodsByName.asMap().entrySet()) {
+      if (entry.getValue().size() > 1) {
+        for (ExecutableElement offendingMethod : entry.getValue()) {
+          builder.addError(
+              String.format(
+                  "Cannot have more than one binding method with the same name in a single module"),
+              offendingMethod);
+        }
+      }
+    }
+  }
+
+  private void validateReferencedModules(
+      TypeElement subject,
+      ModuleKind moduleKind,
+      Set<TypeElement> visitedModules,
+      ValidationReport.Builder<TypeElement> builder) {
+    // Validate that all the modules we include are valid for inclusion.
+    AnnotationMirror mirror = moduleKind.getModuleAnnotation(subject);
+    builder.addSubreport(
+        validateReferencedModules(
+            subject, mirror, moduleKind.legalIncludedModuleKinds(), visitedModules));
+  }
+
+  /**
+   * Validates modules included in a given module or installed in a given component.
+   *
+   * <p>Checks that the referenced modules are non-generic types annotated with {@code @Module} or
+   * {@code @ProducerModule}.
+   *
+   * <p>If the referenced module is in the {@linkplain #addKnownModules(Collection) known modules
+   * set} and has errors, reports an error at that module's inclusion.
+   *
+   * @param annotatedType the annotated module or component
+   * @param annotation the annotation specifying the referenced modules ({@code @Component},
+   *     {@code @ProductionComponent}, {@code @Subcomponent}, {@code @ProductionSubcomponent},
+   *     {@code @Module}, or {@code @ProducerModule})
+   * @param validModuleKinds the module kinds that the annotated type is permitted to include
+   */
+  ValidationReport<TypeElement> validateReferencedModules(
+      TypeElement annotatedType,
+      AnnotationMirror annotation,
+      ImmutableSet<ModuleKind> validModuleKinds,
+      Set<TypeElement> visitedModules) {
+    ValidationReport.Builder<TypeElement> subreport = ValidationReport.about(annotatedType);
+    ImmutableSet<? extends Class<? extends Annotation>> validModuleAnnotations =
+        validModuleKinds.stream().map(ModuleKind::annotation).collect(toImmutableSet());
+
+    for (AnnotationValue includedModule : getModules(annotation)) {
+      asType(includedModule)
+          .accept(
+              new SimpleTypeVisitor8<Void, Void>() {
+                @Override
+                protected Void defaultAction(TypeMirror mirror, Void p) {
+                  reportError("%s is not a valid module type.", mirror);
+                  return null;
+                }
+
+                @Override
+                public Void visitDeclared(DeclaredType t, Void p) {
+                  TypeElement module = MoreElements.asType(t.asElement());
+                  if (!t.getTypeArguments().isEmpty()) {
+                    reportError(
+                        "%s is listed as a module, but has type parameters",
+                        module.getQualifiedName());
+                  }
+                  if (!isAnyAnnotationPresent(module, validModuleAnnotations)) {
+                    reportError(
+                        "%s is listed as a module, but is not annotated with %s",
+                        module.getQualifiedName(),
+                        (validModuleAnnotations.size() > 1 ? "one of " : "")
+                            + validModuleAnnotations
+                                .stream()
+                                .map(otherClass -> "@" + otherClass.getSimpleName())
+                                .collect(joining(", ")));
+                  } else if (knownModules.contains(module)
+                      && !validate(module, visitedModules).isClean()) {
+                    reportError("%s has errors", module.getQualifiedName());
+                  }
+                  return null;
+                }
+
+                @FormatMethod
+                private void reportError(String format, Object... args) {
+                  subreport.addError(
+                      String.format(format, args), annotatedType, annotation, includedModule);
+                }
+              },
+              null);
+    }
+    return subreport.build();
+  }
+
+  private static ImmutableList<AnnotationValue> getModules(AnnotationMirror annotation) {
+    if (isModuleAnnotation(annotation)) {
+      return moduleAnnotation(annotation).includesAsAnnotationValues();
+    }
+    if (isComponentAnnotation(annotation)) {
+      return componentAnnotation(annotation).moduleValues();
+    }
+    throw new IllegalArgumentException(String.format("unsupported annotation: %s", annotation));
+  }
+
+  private void validateBindingMethodOverrides(
+      TypeElement subject,
+      ValidationReport.Builder<TypeElement> builder,
+      ListMultimap<String, ExecutableElement> allMethodsByName,
+      ListMultimap<String, ExecutableElement> bindingMethodsByName) {
+    // For every binding method, confirm it overrides nothing *and* nothing overrides it.
+    // Consider the following hierarchy:
+    // class Parent {
+    //    @Provides Foo a() {}
+    //    @Provides Foo b() {}
+    //    Foo c() {}
+    // }
+    // class Child extends Parent {
+    //    @Provides Foo a() {}
+    //    Foo b() {}
+    //    @Provides Foo c() {}
+    // }
+    // In each of those cases, we want to fail.  "a" is clear, "b" because Child is overriding
+    // a binding method in Parent, and "c" because Child is defining a binding method that overrides
+    // Parent.
+    TypeElement currentClass = subject;
+    TypeMirror objectType = elements.getTypeElement(Object.class).asType();
+    // We keep track of methods that failed so we don't spam with multiple failures.
+    Set<ExecutableElement> failedMethods = Sets.newHashSet();
+    while (!types.isSameType(currentClass.getSuperclass(), objectType)) {
+      currentClass = MoreElements.asType(types.asElement(currentClass.getSuperclass()));
+      List<ExecutableElement> superclassMethods = methodsIn(currentClass.getEnclosedElements());
+      for (ExecutableElement superclassMethod : superclassMethods) {
+        String name = superclassMethod.getSimpleName().toString();
+        // For each method in the superclass, confirm our binding methods don't override it
+        for (ExecutableElement bindingMethod : bindingMethodsByName.get(name)) {
+          if (failedMethods.add(bindingMethod)
+              && elements.overrides(bindingMethod, superclassMethod, subject)) {
+            builder.addError(
+                String.format(
+                    "Binding methods may not override another method. Overrides: %s",
+                    methodSignatureFormatter.format(superclassMethod)),
+                bindingMethod);
+          }
+        }
+        // For each binding method in superclass, confirm our methods don't override it.
+        if (anyBindingMethodValidator.isBindingMethod(superclassMethod)) {
+          for (ExecutableElement method : allMethodsByName.get(name)) {
+            if (failedMethods.add(method)
+                && elements.overrides(method, superclassMethod, subject)) {
+              builder.addError(
+                  String.format(
+                      "Binding methods may not be overridden in modules. Overrides: %s",
+                      methodSignatureFormatter.format(superclassMethod)),
+                  method);
+            }
+          }
+        }
+        allMethodsByName.put(superclassMethod.getSimpleName().toString(), superclassMethod);
+      }
+    }
+  }
+
+  private void validateModuleVisibility(
+      final TypeElement moduleElement,
+      ModuleKind moduleKind,
+      final ValidationReport.Builder<?> reportBuilder) {
+    ModuleAnnotation moduleAnnotation =
+        moduleAnnotation(getAnnotationMirror(moduleElement, moduleKind.annotation()).get());
+    Visibility moduleVisibility = Visibility.ofElement(moduleElement);
+    Visibility moduleEffectiveVisibility = effectiveVisibilityOfElement(moduleElement);
+    if (moduleVisibility.equals(PRIVATE)) {
+      reportBuilder.addError("Modules cannot be private.", moduleElement);
+    } else if (moduleEffectiveVisibility.equals(PRIVATE)) {
+      reportBuilder.addError("Modules cannot be enclosed in private types.", moduleElement);
+    }
+
+    switch (moduleElement.getNestingKind()) {
+      case ANONYMOUS:
+        throw new IllegalStateException("Can't apply @Module to an anonymous class");
+      case LOCAL:
+        throw new IllegalStateException("Local classes shouldn't show up in the processor");
+      case MEMBER:
+      case TOP_LEVEL:
+        if (moduleEffectiveVisibility.equals(PUBLIC)) {
+          ImmutableSet<TypeElement> invalidVisibilityIncludes =
+              getModuleIncludesWithInvalidVisibility(moduleAnnotation);
+          if (!invalidVisibilityIncludes.isEmpty()) {
+            reportBuilder.addError(
+                String.format(
+                    "This module is public, but it includes non-public (or effectively non-public) "
+                        + "modules (%s) that have non-static, non-abstract binding methods. Either "
+                        + "reduce the visibility of this module, make the included modules "
+                        + "public, or make all of the binding methods on the included modules "
+                        + "abstract or static.",
+                    formatListForErrorMessage(invalidVisibilityIncludes.asList())),
+                moduleElement);
+          }
+        }
+    }
+  }
+
+  private ImmutableSet<TypeElement> getModuleIncludesWithInvalidVisibility(
+      ModuleAnnotation moduleAnnotation) {
+    return moduleAnnotation.includes().stream()
+        .filter(include -> !effectiveVisibilityOfElement(include).equals(PUBLIC))
+        .filter(this::requiresModuleInstance)
+        .collect(toImmutableSet());
+  }
+
+  /**
+   * Returns {@code true} if a module instance is needed for any of the binding methods on the
+   * given {@code module}. This is the case when the module has any binding methods that are neither
+   * {@code abstract} nor {@code static}.
+   */
+  private boolean requiresModuleInstance(TypeElement module) {
+    // Note elements.getAllMembers(module) rather than module.getEnclosedElements() here: we need to
+    // include binding methods declared in supertypes because unlike most other validations being
+    // done in this class, which assume that supertype binding methods will be validated in a
+    // separate call to the validator since the supertype itself must be a @Module, we need to look
+    // at all the binding methods in the module's type hierarchy here.
+    return methodsIn(elements.getAllMembers(module)).stream()
+        .filter(method -> anyBindingMethodValidator.isBindingMethod(method))
+        .map(ExecutableElement::getModifiers)
+        .anyMatch(modifiers -> !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC));
+  }
+
+  private void validateNoScopeAnnotationsOnModuleElement(
+      TypeElement module, ModuleKind moduleKind, ValidationReport.Builder<TypeElement> report) {
+    for (AnnotationMirror scope : getAnnotatedAnnotations(module, Scope.class)) {
+      report.addError(
+          String.format(
+              "@%ss cannot be scoped. Did you mean to scope a method instead?",
+              moduleKind.annotation().getSimpleName()),
+          module,
+          scope);
+    }
+  }
+
+  private void validateSelfCycles(
+      TypeElement module, ValidationReport.Builder<TypeElement> builder) {
+    ModuleAnnotation moduleAnnotation = moduleAnnotation(module).get();
+    moduleAnnotation
+        .includesAsAnnotationValues()
+        .forEach(
+            value ->
+                value.accept(
+                    new SimpleAnnotationValueVisitor8<Void, Void>() {
+                      @Override
+                      public Void visitType(TypeMirror includedModule, Void aVoid) {
+                        if (MoreTypes.equivalence().equivalent(module.asType(), includedModule)) {
+                          String moduleKind = moduleAnnotation.annotationClass().getSimpleName();
+                          builder.addError(
+                              String.format("@%s cannot include themselves.", moduleKind),
+                              module,
+                              moduleAnnotation.annotation(),
+                              value);
+                        }
+                        return null;
+                      }
+                    },
+                    null));
+  }
+
+  private void validateModuleBindings(
+      TypeElement module, ValidationReport.Builder<TypeElement> report) {
+    BindingGraph bindingGraph =
+        bindingGraphConverter.convert(
+            bindingGraphFactory.create(
+                componentDescriptorFactory.moduleComponentDescriptor(module), true));
+    if (!bindingGraphValidator.isValid(bindingGraph)) {
+      // Since the validator uses a DiagnosticReporter to report errors, the ValdiationReport won't
+      // have any Items for them. We have to tell the ValidationReport that some errors were
+      // reported for the subject.
+      report.markDirty();
+    }
+  }
+
+  private static String formatListForErrorMessage(List<?> things) {
+    switch (things.size()) {
+      case 0:
+        return "";
+      case 1:
+        return things.get(0).toString();
+      default:
+        StringBuilder output = new StringBuilder();
+        Joiner.on(", ").appendTo(output, things.subList(0, things.size() - 1));
+        output.append(" and ").append(things.get(things.size() - 1));
+        return output.toString();
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/MonitoringModuleGenerator.java b/java/dagger/internal/codegen/MonitoringModuleGenerator.java
new file mode 100644
index 0000000..1738fe9
--- /dev/null
+++ b/java/dagger/internal/codegen/MonitoringModuleGenerator.java
@@ -0,0 +1,100 @@
+/*
+ * 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.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCTION_COMPONENT_MONITOR_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.setOf;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeSpec;
+import dagger.Module;
+import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.multibindings.Multibinds;
+import dagger.producers.ProductionScope;
+import dagger.producers.monitoring.ProductionComponentMonitor;
+import dagger.producers.monitoring.internal.Monitors;
+import java.util.Optional;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/** Generates a monitoring module for use with production components. */
+final class MonitoringModuleGenerator extends SourceFileGenerator<TypeElement> {
+
+  @Inject
+  MonitoringModuleGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
+    super(filer, elements, sourceVersion);
+  }
+
+  @Override
+  ClassName nameGeneratedType(TypeElement componentElement) {
+    return SourceFiles.generatedMonitoringModuleName(componentElement);
+  }
+
+  @Override
+  Element originatingElement(TypeElement componentElement) {
+    return componentElement;
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, TypeElement componentElement) {
+    return Optional.of(
+        classBuilder(generatedTypeName)
+            .addAnnotation(Module.class)
+            .addModifiers(ABSTRACT)
+            .addMethod(privateConstructor())
+            .addMethod(setOfFactories())
+            .addMethod(monitor(componentElement)));
+  }
+
+  private MethodSpec privateConstructor() {
+    return constructorBuilder().addModifiers(PRIVATE).build();
+  }
+
+  private MethodSpec setOfFactories() {
+    return methodBuilder("setOfFactories")
+        .addAnnotation(Multibinds.class)
+        .addModifiers(ABSTRACT)
+        .returns(setOf(PRODUCTION_COMPONENT_MONITOR_FACTORY))
+        .build();
+  }
+
+  private MethodSpec monitor(TypeElement componentElement) {
+    return methodBuilder("monitor")
+        .returns(ProductionComponentMonitor.class)
+        .addModifiers(STATIC)
+        .addAnnotation(Provides.class)
+        .addAnnotation(ProductionScope.class)
+        .addParameter(providerOf(ClassName.get(componentElement.asType())), "component")
+        .addParameter(
+            providerOf(setOf(PRODUCTION_COMPONENT_MONITOR_FACTORY)), "factories")
+        .addStatement(
+            "return $T.createMonitorForComponent(component, factories)", Monitors.class)
+        .build();
+  }
+}
diff --git a/java/dagger/internal/codegen/MonitoringModuleProcessingStep.java b/java/dagger/internal/codegen/MonitoringModuleProcessingStep.java
new file mode 100644
index 0000000..55ae579
--- /dev/null
+++ b/java/dagger/internal/codegen/MonitoringModuleProcessingStep.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.google.auto.common.MoreElements;
+import com.google.common.collect.ImmutableSet;
+import dagger.producers.ProductionComponent;
+import dagger.producers.ProductionSubcomponent;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+import javax.annotation.processing.Messager;
+import javax.inject.Inject;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * A processing step that is responsible for generating a special module for a {@link
+ * ProductionComponent} or {@link ProductionSubcomponent}.
+ */
+final class MonitoringModuleProcessingStep extends TypeCheckingProcessingStep<TypeElement> {
+  private final Messager messager;
+  private final MonitoringModuleGenerator monitoringModuleGenerator;
+
+  @Inject
+  MonitoringModuleProcessingStep(
+      Messager messager, MonitoringModuleGenerator monitoringModuleGenerator) {
+    super(MoreElements::asType);
+    this.messager = messager;
+    this.monitoringModuleGenerator = monitoringModuleGenerator;
+  }
+
+  @Override
+  public Set<? extends Class<? extends Annotation>> annotations() {
+    return ImmutableSet.of(ProductionComponent.class, ProductionSubcomponent.class);
+  }
+
+  @Override
+  protected void process(
+      TypeElement element, ImmutableSet<Class<? extends Annotation>> annotations) {
+      monitoringModuleGenerator.generate(MoreElements.asType(element), messager);
+  }
+}
diff --git a/java/dagger/internal/codegen/MoreAnnotationMirrors.java b/java/dagger/internal/codegen/MoreAnnotationMirrors.java
new file mode 100644
index 0000000..92825a0
--- /dev/null
+++ b/java/dagger/internal/codegen/MoreAnnotationMirrors.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 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.AnnotationMirrors.getAnnotationValue;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.MoreAnnotationValues.asAnnotationValues;
+
+import com.google.auto.common.AnnotationMirrors;
+import com.google.common.base.Equivalence;
+import com.google.common.collect.ImmutableList;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Name;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A utility class for working with {@link AnnotationMirror} instances, similar to {@link
+ * AnnotationMirrors}.
+ */
+final class MoreAnnotationMirrors {
+
+  private MoreAnnotationMirrors() {}
+
+  /**
+   * Wraps an {@link Optional} of a type in an {@code Optional} of a {@link Equivalence.Wrapper} for
+   * that type.
+   */
+  static Optional<Equivalence.Wrapper<AnnotationMirror>> wrapOptionalInEquivalence(
+      Optional<AnnotationMirror> optional) {
+    return optional.map(AnnotationMirrors.equivalence()::wrap);
+  }
+
+  /**
+   * Unwraps an {@link Optional} of a {@link Equivalence.Wrapper} into an {@code Optional} of the
+   * underlying type.
+   */
+  static Optional<AnnotationMirror> unwrapOptionalEquivalence(
+      Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedOptional) {
+    return wrappedOptional.map(Equivalence.Wrapper::get);
+  }
+
+  static Name simpleName(AnnotationMirror annotationMirror) {
+    return annotationMirror.getAnnotationType().asElement().getSimpleName();
+  }
+
+  /**
+   * Returns the list of types that is the value named {@code name} from {@code annotationMirror}.
+   *
+   * @throws IllegalArgumentException unless that member represents an array of types
+   */
+  static ImmutableList<TypeMirror> getTypeListValue(
+      AnnotationMirror annotationMirror, String name) {
+    return asAnnotationValues(getAnnotationValue(annotationMirror, name))
+        .stream()
+        .map(MoreAnnotationValues::asType)
+        .collect(toImmutableList());
+  }
+}
diff --git a/java/dagger/internal/codegen/MoreAnnotationValues.java b/java/dagger/internal/codegen/MoreAnnotationValues.java
new file mode 100644
index 0000000..84a4d94
--- /dev/null
+++ b/java/dagger/internal/codegen/MoreAnnotationValues.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 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.common.collect.ImmutableList;
+import java.util.List;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.AnnotationValueVisitor;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleAnnotationValueVisitor8;
+
+/** Utility methods for working with {@link AnnotationValue} instances. */
+final class MoreAnnotationValues {
+  /**
+   * Returns the list of values represented by an array annotation value.
+   *
+   * @throws IllegalArgumentException unless {@code annotationValue} represents an array
+   */
+  static ImmutableList<AnnotationValue> asAnnotationValues(AnnotationValue annotationValue) {
+    return annotationValue.accept(AS_ANNOTATION_VALUES, null);
+  }
+
+  private static final AnnotationValueVisitor<ImmutableList<AnnotationValue>, String>
+      AS_ANNOTATION_VALUES =
+          new SimpleAnnotationValueVisitor8<ImmutableList<AnnotationValue>, String>() {
+            @Override
+            public ImmutableList<AnnotationValue> visitArray(
+                List<? extends AnnotationValue> vals, String elementName) {
+              return ImmutableList.copyOf(vals);
+            }
+
+            @Override
+            protected ImmutableList<AnnotationValue> defaultAction(Object o, String elementName) {
+              throw new IllegalArgumentException(elementName + " is not an array: " + o);
+            }
+          };
+
+  /**
+   * Returns the type represented by an annotation value.
+   *
+   * @throws IllegalArgumentException unless {@code annotationValue} represents a single type
+   */
+  static TypeMirror asType(AnnotationValue annotationValue) {
+    return AS_TYPE.visit(annotationValue);
+  }
+
+  private static final AnnotationValueVisitor<TypeMirror, Void> AS_TYPE =
+      new SimpleAnnotationValueVisitor8<TypeMirror, Void>() {
+        @Override
+        public TypeMirror visitType(TypeMirror t, Void p) {
+          return t;
+        }
+
+        @Override
+        protected TypeMirror defaultAction(Object o, Void p) {
+          throw new TypeNotPresentException(o.toString(), null);
+        }
+      };
+
+  private MoreAnnotationValues() {}
+}
diff --git a/java/dagger/internal/codegen/MultibindingAnnotations.java b/java/dagger/internal/codegen/MultibindingAnnotations.java
new file mode 100644
index 0000000..b478704
--- /dev/null
+++ b/java/dagger/internal/codegen/MultibindingAnnotations.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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 dagger.internal.codegen.langmodel.DaggerElements.getAllAnnotations;
+
+import com.google.common.collect.ImmutableSet;
+import dagger.multibindings.ElementsIntoSet;
+import dagger.multibindings.IntoMap;
+import dagger.multibindings.IntoSet;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+
+/**
+ * Utility methods related to processing {@link IntoSet}, {@link ElementsIntoSet}, and {@link
+ * IntoMap}.
+ */
+final class MultibindingAnnotations {
+  static ImmutableSet<AnnotationMirror> forElement(Element method) {
+    return getAllAnnotations(method, IntoSet.class, ElementsIntoSet.class, IntoMap.class);
+  }
+}
diff --git a/java/dagger/internal/codegen/MultibindingAnnotationsProcessingStep.java b/java/dagger/internal/codegen/MultibindingAnnotationsProcessingStep.java
new file mode 100644
index 0000000..2bb0a7e
--- /dev/null
+++ b/java/dagger/internal/codegen/MultibindingAnnotationsProcessingStep.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 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 dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.collect.ImmutableSet;
+import dagger.multibindings.ElementsIntoSet;
+import dagger.multibindings.IntoMap;
+import dagger.multibindings.IntoSet;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+import javax.annotation.processing.Messager;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+
+/**
+ * Processing step that verifies that {@link IntoSet}, {@link ElementsIntoSet} and {@link IntoMap}
+ * are not present on non-binding methods.
+ */
+final class MultibindingAnnotationsProcessingStep
+    extends TypeCheckingProcessingStep<ExecutableElement> {
+  private final AnyBindingMethodValidator anyBindingMethodValidator;
+  private final Messager messager;
+
+  @Inject
+  MultibindingAnnotationsProcessingStep(
+      AnyBindingMethodValidator anyBindingMethodValidator, Messager messager) {
+    super(MoreElements::asExecutable);
+    this.anyBindingMethodValidator = anyBindingMethodValidator;
+    this.messager = messager;
+  }
+
+  @Override
+  public Set<? extends Class<? extends Annotation>> annotations() {
+    return ImmutableSet.of(IntoSet.class, ElementsIntoSet.class, IntoMap.class);
+  }
+
+  @Override
+  protected void process(
+      ExecutableElement method, ImmutableSet<Class<? extends Annotation>> annotations) {
+    if (!anyBindingMethodValidator.isBindingMethod(method)) {
+      annotations.forEach(
+          annotation ->
+              messager.printMessage(
+                  ERROR,
+                  "Multibinding annotations may only be on @Provides, @Produces, or @Binds methods",
+                  method,
+                  getAnnotationMirror(method, annotation).get()));
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/MultibindingDeclaration.java b/java/dagger/internal/codegen/MultibindingDeclaration.java
new file mode 100644
index 0000000..c3724dc
--- /dev/null
+++ b/java/dagger/internal/codegen/MultibindingDeclaration.java
@@ -0,0 +1,118 @@
+/*
+ * 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.MoreElements.isAnnotationPresent;
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import dagger.internal.codegen.ContributionType.HasContributionType;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import dagger.multibindings.Multibinds;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A declaration that a multibinding with a certain key is available to be injected in a component
+ * even if the component has no multibindings for that key. Identified by a map- or set-returning
+ * method annotated with {@link Multibinds @Multibinds}.
+ */
+@AutoValue
+abstract class MultibindingDeclaration extends BindingDeclaration implements HasContributionType {
+
+  /**
+   * The map or set key whose availability is declared. For maps, this will be {@code Map<K,
+   * Provider<V>>}. For sets, this will be {@code Set<T>}.
+   */
+  @Override
+  public abstract Key key();
+
+  /**
+   * {@link ContributionType#SET} if the declared type is a {@link Set}, or
+   * {@link ContributionType#MAP} if it is a {@link Map}.
+   */
+  @Override
+  public abstract ContributionType contributionType();
+
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  @Override
+  public abstract boolean equals(Object obj);
+
+  /**
+   * A factory for {@link MultibindingDeclaration}s.
+   */
+  static final class Factory {
+    private final DaggerTypes types;
+    private final KeyFactory keyFactory;
+
+    @Inject
+    Factory(DaggerTypes types, KeyFactory keyFactory) {
+      this.types = types;
+      this.keyFactory = keyFactory;
+    }
+
+    /** A multibinding declaration for a {@link Multibinds @Multibinds} method. */
+    MultibindingDeclaration forMultibindsMethod(
+        ExecutableElement moduleMethod, TypeElement moduleElement) {
+      checkArgument(isAnnotationPresent(moduleMethod, Multibinds.class));
+      return forDeclaredMethod(
+          moduleMethod,
+          MoreTypes.asExecutable(
+              types.asMemberOf(MoreTypes.asDeclared(moduleElement.asType()), moduleMethod)),
+          moduleElement);
+    }
+
+    private MultibindingDeclaration forDeclaredMethod(
+        ExecutableElement method,
+        ExecutableType methodType,
+        TypeElement contributingType) {
+      TypeMirror returnType = methodType.getReturnType();
+      checkArgument(
+          SetType.isSet(returnType) || MapType.isMap(returnType),
+          "%s must return a set or map",
+          method);
+      return new AutoValue_MultibindingDeclaration(
+          Optional.<Element>of(method),
+          Optional.of(contributingType),
+          keyFactory.forMultibindsMethod(methodType, method),
+          contributionType(returnType));
+    }
+
+    private ContributionType contributionType(TypeMirror returnType) {
+      if (MapType.isMap(returnType)) {
+        return ContributionType.MAP;
+      } else if (SetType.isSet(returnType)) {
+        return ContributionType.SET;
+      } else {
+        throw new IllegalArgumentException("Must be Map or Set: " + returnType);
+      }
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/MultibindingExpression.java b/java/dagger/internal/codegen/MultibindingExpression.java
new file mode 100644
index 0000000..f0523eb
--- /dev/null
+++ b/java/dagger/internal/codegen/MultibindingExpression.java
@@ -0,0 +1,95 @@
+/*
+ * 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.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import java.util.Optional;
+import java.util.Set;
+
+/** An abstract base class for multibinding {@link BindingExpression}s. */
+abstract class MultibindingExpression extends SimpleInvocationBindingExpression {
+  private final ProvisionBinding binding;
+  private final ComponentImplementation componentImplementation;
+
+  MultibindingExpression(
+      ResolvedBindings resolvedBindings, ComponentImplementation componentImplementation) {
+    super(resolvedBindings);
+    this.componentImplementation = componentImplementation;
+    this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    Expression expression = buildDependencyExpression(requestingClass);
+    componentImplementation.registerImplementedMultibinding(binding, bindingRequest());
+    return expression;
+  }
+
+  /**
+   * Returns an expression that evaluates to the value of a multibinding request for the given
+   * requesting class.
+   */
+  protected abstract Expression buildDependencyExpression(ClassName requestingClass);
+
+  /**
+   * Returns the subset of {@code dependencies} that represent multibinding contributions that were
+   * not included in a superclass implementation of this multibinding method. This is relevant only
+   * for ahead-of-time subcomponents. When not generating ahead-of-time subcomponents there is only
+   * one implementation of a multibinding expression and all {@link DependencyRequest}s from the
+   * argment are returned.
+   */
+  protected Set<DependencyRequest> getNewContributions(
+      ImmutableSet<DependencyRequest> dependencies) {
+    ImmutableSet<Key> superclassContributions = superclassContributions();
+    return Sets.filter(
+        dependencies, dependency -> !superclassContributions.contains(dependency.key()));
+  }
+
+  /**
+   * Returns the {@link CodeBlock} representing a call to a superclass implementation of the
+   * modifiable binding method that encapsulates this binding, if it exists. This is only possible
+   * when generating ahead-of-time subcomponents.
+   */
+  protected Optional<CodeBlock> superMethodCall() {
+    if (componentImplementation.superclassImplementation().isPresent()) {
+      Optional<ModifiableBindingMethod> method =
+          componentImplementation.getModifiableBindingMethod(bindingRequest());
+      if (method.isPresent()) {
+        if (!superclassContributions().isEmpty()) {
+          return Optional.of(CodeBlock.of("super.$L()", method.get().methodSpec().name));
+        }
+      }
+    }
+    return Optional.empty();
+  }
+
+  private BindingRequest bindingRequest() {
+    return BindingRequest.bindingRequest(binding.key(), RequestKind.INSTANCE);
+  }
+
+  private ImmutableSet<Key> superclassContributions() {
+    return componentImplementation.superclassContributionsMade(bindingRequest());
+  }
+}
diff --git a/java/dagger/internal/codegen/MultibindingFactoryCreationExpression.java b/java/dagger/internal/codegen/MultibindingFactoryCreationExpression.java
new file mode 100644
index 0000000..abe161a
--- /dev/null
+++ b/java/dagger/internal/codegen/MultibindingFactoryCreationExpression.java
@@ -0,0 +1,95 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import java.util.Optional;
+
+/** An abstract factory creation expression for multibindings. */
+abstract class MultibindingFactoryCreationExpression
+    implements FrameworkInstanceCreationExpression {
+  private final ComponentImplementation componentImplementation;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final ContributionBinding binding;
+
+  MultibindingFactoryCreationExpression(
+      ContributionBinding binding,
+      ComponentImplementation componentImplementation,
+      ComponentBindingExpressions componentBindingExpressions) {
+    this.binding = checkNotNull(binding);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+  }
+
+  /** Returns the expression for a dependency of this multibinding. */
+  protected final CodeBlock multibindingDependencyExpression(DependencyRequest dependency) {
+    CodeBlock expression =
+        componentBindingExpressions
+            .getDependencyExpression(
+                BindingRequest.bindingRequest(dependency.key(), binding.frameworkType()),
+                componentImplementation.name())
+            .codeBlock();
+
+    return useRawType()
+        ? CodeBlocks.cast(expression, binding.frameworkType().frameworkClass())
+        : expression;
+  }
+
+  protected final ImmutableSet<DependencyRequest> dependenciesToImplement() {
+    ImmutableSet<Key> alreadyImplementedKeys =
+        componentImplementation.superclassContributionsMade(bindingRequest());
+    return binding.dependencies().stream()
+        .filter(dependency -> !alreadyImplementedKeys.contains(dependency.key()))
+        .collect(toImmutableSet());
+  }
+
+  protected Optional<CodeBlock> superContributions() {
+    if (dependenciesToImplement().size() == binding.dependencies().size()) {
+      return Optional.empty();
+    }
+    ModifiableBindingMethod superMethod =
+        componentImplementation.getModifiableBindingMethod(bindingRequest()).get();
+    return Optional.of(CodeBlock.of("super.$N()", superMethod.methodSpec().name));
+  }
+
+  /** The binding request for this framework instance. */
+  protected final BindingRequest bindingRequest() {
+    return BindingRequest.bindingRequest(binding.key(), binding.frameworkType());
+  }
+
+  /**
+   * Returns true if the {@linkplain ContributionBinding#key() key type} is inaccessible from the
+   * component, and therefore a raw type must be used.
+   */
+  protected final boolean useRawType() {
+    return !componentImplementation.isTypeAccessible(binding.key().type());
+  }
+
+  @Override
+  public final boolean useInnerSwitchingProvider() {
+    return !binding.dependencies().isEmpty();
+  }
+}
diff --git a/java/dagger/internal/codegen/MultibindsMethodValidator.java b/java/dagger/internal/codegen/MultibindsMethodValidator.java
new file mode 100644
index 0000000..bc97d30
--- /dev/null
+++ b/java/dagger/internal/codegen/MultibindsMethodValidator.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 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 dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.NO_SCOPING;
+import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
+import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS;
+import static dagger.internal.codegen.FrameworkTypes.isFrameworkType;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSet;
+import dagger.Module;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.multibindings.Multibinds;
+import dagger.producers.ProducerModule;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.TypeMirror;
+
+/** A validator for {@link Multibinds} methods. */
+class MultibindsMethodValidator extends BindingMethodValidator {
+
+  /** Creates a validator for {@link Multibinds @Multibinds} methods. */
+  @Inject
+  MultibindsMethodValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      DependencyRequestValidator dependencyRequestValidator) {
+    super(
+        elements,
+        types,
+        Multibinds.class,
+        ImmutableSet.of(Module.class, ProducerModule.class),
+        dependencyRequestValidator,
+        MUST_BE_ABSTRACT,
+        NO_EXCEPTIONS,
+        NO_MULTIBINDINGS,
+        NO_SCOPING);
+  }
+
+  @Override
+  protected ElementValidator elementValidator(ExecutableElement element) {
+    return new Validator(element);
+  }
+
+  private class Validator extends MethodValidator {
+    Validator(ExecutableElement element) {
+      super(element);
+    }
+
+    @Override
+    protected void checkParameters() {
+      if (!element.getParameters().isEmpty()) {
+        report.addError(bindingMethods("cannot have parameters"));
+      }
+    }
+
+    /** Adds an error unless the method returns a {@code Map<K, V>} or {@code Set<T>}. */
+    @Override
+    protected void checkType() {
+      if (!isPlainMap(element.getReturnType())
+          && !isPlainSet(element.getReturnType())) {
+        report.addError(bindingMethods("must return Map<K, V> or Set<T>"));
+      }
+    }
+
+    private boolean isPlainMap(TypeMirror returnType) {
+      if (!MapType.isMap(returnType)) {
+        return false;
+      }
+      MapType mapType = MapType.from(returnType);
+      return !mapType.isRawType()
+          && MoreTypes.isType(mapType.valueType()) // No wildcards.
+          && !isFrameworkType(mapType.valueType());
+    }
+
+    private boolean isPlainSet(TypeMirror returnType) {
+      if (!SetType.isSet(returnType)) {
+        return false;
+      }
+      SetType setType = SetType.from(returnType);
+      return !setType.isRawType()
+          && MoreTypes.isType(setType.elementType()) // No wildcards.
+          && !isFrameworkType(setType.elementType());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/NullableBindingValidator.java b/java/dagger/internal/codegen/NullableBindingValidator.java
new file mode 100644
index 0000000..1452c3f
--- /dev/null
+++ b/java/dagger/internal/codegen/NullableBindingValidator.java
@@ -0,0 +1,82 @@
+/*
+ * 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 dagger.internal.codegen.DaggerStreams.instancesOf;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import dagger.model.BindingGraph;
+import dagger.model.BindingGraph.DependencyEdge;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import javax.inject.Inject;
+
+/**
+ * Reports errors or warnings (depending on the {@code -Adagger.nullableValidation} value) for each
+ * non-nullable dependency request that is satisfied by a nullable binding.
+ */
+final class NullableBindingValidator implements BindingGraphPlugin {
+
+  private final CompilerOptions compilerOptions;
+
+  @Inject
+  NullableBindingValidator(CompilerOptions compilerOptions) {
+    this.compilerOptions = compilerOptions;
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    for (dagger.model.Binding binding : nullableBindings(bindingGraph)) {
+      for (DependencyEdge dependencyEdge : nonNullableDependencies(bindingGraph, binding)) {
+        diagnosticReporter.reportDependency(
+            compilerOptions.nullableValidationKind(),
+            dependencyEdge,
+            nullableToNonNullable(
+                binding.key().toString(),
+                binding.toString())); // binding.toString() will include the @Nullable
+      }
+    }
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/Nullable";
+  }
+
+  private ImmutableList<dagger.model.Binding> nullableBindings(BindingGraph bindingGraph) {
+    return bindingGraph.bindings().stream()
+        .filter(binding -> binding.isNullable())
+        .collect(toImmutableList());
+  }
+
+  private ImmutableSet<DependencyEdge> nonNullableDependencies(
+      BindingGraph bindingGraph, dagger.model.Binding binding) {
+    return bindingGraph.network().inEdges(binding).stream()
+        .flatMap(instancesOf(DependencyEdge.class))
+        .filter(edge -> !edge.dependencyRequest().isNullable())
+        .collect(toImmutableSet());
+  }
+
+  @VisibleForTesting
+  static String nullableToNonNullable(String key, String binding) {
+    return String.format("%s is not nullable, but is being provided by %s", key, binding);
+  }
+}
diff --git a/java/dagger/internal/codegen/OptionalBindingDeclaration.java b/java/dagger/internal/codegen/OptionalBindingDeclaration.java
new file mode 100644
index 0000000..b26ab91
--- /dev/null
+++ b/java/dagger/internal/codegen/OptionalBindingDeclaration.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 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.MoreElements.isAnnotationPresent;
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import dagger.BindsOptionalOf;
+import dagger.model.Key;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+/** A {@link BindsOptionalOf} declaration. */
+@AutoValue
+abstract class OptionalBindingDeclaration extends BindingDeclaration {
+
+  /**
+   * {@inheritDoc}
+   *
+   * <p>The key's type is the method's return type, even though the synthetic bindings will be for
+   * {@code Optional} of derived types.
+   */
+  @Override
+  public abstract Key key();
+
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  @Override
+  public abstract boolean equals(Object obj);
+
+  static class Factory {
+    private final KeyFactory keyFactory;
+
+    @Inject
+    Factory(KeyFactory keyFactory) {
+      this.keyFactory = keyFactory;
+    }
+
+    OptionalBindingDeclaration forMethod(ExecutableElement method, TypeElement contributingModule) {
+      checkArgument(isAnnotationPresent(method, BindsOptionalOf.class));
+      return new AutoValue_OptionalBindingDeclaration(
+          Optional.<Element>of(method),
+          Optional.of(contributingModule),
+          keyFactory.forBindsOptionalOfMethod(method, contributingModule));
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/OptionalBindingExpression.java b/java/dagger/internal/codegen/OptionalBindingExpression.java
new file mode 100644
index 0000000..dbb0e37
--- /dev/null
+++ b/java/dagger/internal/codegen/OptionalBindingExpression.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.OptionalType.OptionalKind;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+
+/** A binding expression for optional bindings. */
+final class OptionalBindingExpression extends SimpleInvocationBindingExpression {
+  private final ProvisionBinding binding;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final DaggerTypes types;
+  private final SourceVersion sourceVersion;
+
+  @Inject
+  OptionalBindingExpression(
+      ResolvedBindings resolvedBindings,
+      ComponentBindingExpressions componentBindingExpressions,
+      DaggerTypes types,
+      SourceVersion sourceVersion) {
+    super(resolvedBindings);
+    this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
+    this.componentBindingExpressions = componentBindingExpressions;
+    this.types = types;
+    this.sourceVersion = sourceVersion;
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    OptionalType optionalType = OptionalType.from(binding.key());
+    OptionalKind optionalKind = optionalType.kind();
+    if (binding.dependencies().isEmpty()) {
+      if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
+        // When compiling with -source 7, javac's type inference isn't strong enough to detect
+        // Futures.immediateFuture(Optional.absent()) for keys that aren't Object. It also has
+        // issues
+        // when used as an argument to some members injection proxy methods (see
+        // https://github.com/google/dagger/issues/916)
+        if (isTypeAccessibleFrom(binding.key().type(), requestingClass.packageName())) {
+          return Expression.create(
+              binding.key().type(), optionalKind.parameterizedAbsentValueExpression(optionalType));
+        }
+      }
+      return Expression.create(binding.key().type(), optionalKind.absentValueExpression());
+    }
+    DependencyRequest dependency = getOnlyElement(binding.dependencies());
+
+    CodeBlock dependencyExpression =
+        componentBindingExpressions
+            .getDependencyExpression(bindingRequest(dependency), requestingClass)
+            .codeBlock();
+
+    // If the dependency type is inaccessible, then we have to use Optional.<Object>of(...), or else
+    // we will get "incompatible types: inference variable has incompatible bounds.
+    return isTypeAccessibleFrom(dependency.key().type(), requestingClass.packageName())
+        ? Expression.create(
+            binding.key().type(), optionalKind.presentExpression(dependencyExpression))
+        : Expression.create(
+            types.erasure(binding.key().type()),
+            optionalKind.presentObjectExpression(dependencyExpression));
+  }
+
+  @Override
+  boolean requiresMethodEncapsulation() {
+    // TODO(dpb): Maybe require it for present bindings.
+    return false;
+  }
+}
diff --git a/java/dagger/internal/codegen/OptionalFactories.java b/java/dagger/internal/codegen/OptionalFactories.java
new file mode 100644
index 0000000..51c9939
--- /dev/null
+++ b/java/dagger/internal/codegen/OptionalFactories.java
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2016 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.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static com.google.common.base.Verify.verify;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.ComponentImplementation.FieldSpecKind.ABSENT_OPTIONAL_FIELD;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.ABSENT_OPTIONAL_METHOD;
+import static dagger.internal.codegen.ComponentImplementation.TypeSpecKind.PRESENT_FACTORY;
+import static dagger.internal.codegen.RequestKinds.requestTypeName;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER;
+import static dagger.internal.codegen.javapoet.TypeNames.abstractProducerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.InstanceFactory;
+import dagger.internal.Preconditions;
+import dagger.internal.codegen.OptionalType.OptionalKind;
+import dagger.internal.codegen.javapoet.AnnotationSpecs;
+import dagger.model.RequestKind;
+import dagger.producers.Producer;
+import dagger.producers.internal.Producers;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Optional;
+import java.util.TreeMap;
+import java.util.concurrent.Executor;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+/** The nested class and static methods required by the component to implement optional bindings. */
+// TODO(dpb): Name members simply if a component uses only one of Guava or JDK Optional.
+@PerGeneratedFile
+final class OptionalFactories {
+  private final ComponentImplementation componentImplementation;
+
+  @Inject OptionalFactories(@TopLevel ComponentImplementation componentImplementation) {
+    this.componentImplementation = componentImplementation;
+  }
+
+  /**
+   * The factory classes that implement {@code Provider<Optional<T>>} or {@code
+   * Producer<Optional<T>>} for present optional bindings for a given kind of dependency request
+   * within the component.
+   *
+   * <p>The key is the {@code Provider<Optional<T>>} type.
+   */
+  private final Map<PresentFactorySpec, TypeSpec> presentFactoryClasses =
+      new TreeMap<>(
+          Comparator.comparing(PresentFactorySpec::valueKind)
+              .thenComparing(PresentFactorySpec::frameworkType)
+              .thenComparing(PresentFactorySpec::optionalKind));
+
+  /**
+   * The static methods that return a {@code Provider<Optional<T>>} that always returns an absent
+   * value.
+   */
+  private final Map<OptionalKind, MethodSpec> absentOptionalProviderMethods = new TreeMap<>();
+
+  /**
+   * The static fields for {@code Provider<Optional<T>>} objects that always return an absent value.
+   */
+  private final Map<OptionalKind, FieldSpec> absentOptionalProviderFields = new TreeMap<>();
+
+  /**
+   * Returns an expression that calls a static method that returns a {@code Provider<Optional<T>>}
+   * for absent optional bindings.
+   */
+  CodeBlock absentOptionalProvider(ContributionBinding binding) {
+    verify(
+        binding.bindingType().equals(BindingType.PROVISION),
+        "Absent optional bindings should be provisions: %s",
+        binding);
+    OptionalKind optionalKind = OptionalType.from(binding.key()).kind();
+    return CodeBlock.of(
+        "$N()",
+        absentOptionalProviderMethods.computeIfAbsent(
+            optionalKind,
+            kind -> {
+              MethodSpec method = absentOptionalProviderMethod(kind);
+              componentImplementation.addMethod(ABSENT_OPTIONAL_METHOD, method);
+              return method;
+            }));
+  }
+
+  /**
+   * Creates a method specification for a {@code Provider<Optional<T>>} that always returns an
+   * absent value.
+   */
+  private MethodSpec absentOptionalProviderMethod(OptionalKind optionalKind) {
+    TypeVariableName typeVariable = TypeVariableName.get("T");
+    return methodBuilder(
+            String.format(
+                "absent%sProvider", UPPER_UNDERSCORE.to(UPPER_CAMEL, optionalKind.name())))
+        .addModifiers(PRIVATE, STATIC)
+        .addTypeVariable(typeVariable)
+        .returns(providerOf(optionalKind.of(typeVariable)))
+        .addJavadoc(
+            "Returns a {@link $T} that returns {@code $L}.",
+            Provider.class,
+            optionalKind.absentValueExpression())
+        .addCode("$L // safe covariant cast\n", AnnotationSpecs.suppressWarnings(UNCHECKED))
+        .addCode(
+            "$1T provider = ($1T) $2N;",
+            providerOf(optionalKind.of(typeVariable)),
+            absentOptionalProviderFields.computeIfAbsent(
+                optionalKind,
+                kind -> {
+                  FieldSpec field = absentOptionalProviderField(kind);
+                  componentImplementation.addField(ABSENT_OPTIONAL_FIELD, field);
+                  return field;
+                }))
+        .addCode("return provider;")
+        .build();
+  }
+
+  /**
+   * Creates a field specification for a {@code Provider<Optional<T>>} that always returns an absent
+   * value.
+   */
+  private FieldSpec absentOptionalProviderField(OptionalKind optionalKind) {
+    return FieldSpec.builder(
+            PROVIDER,
+            String.format("ABSENT_%s_PROVIDER", optionalKind.name()),
+            PRIVATE,
+            STATIC,
+            FINAL)
+        .addAnnotation(AnnotationSpecs.suppressWarnings(RAWTYPES))
+        .initializer("$T.create($L)", InstanceFactory.class, optionalKind.absentValueExpression())
+        .addJavadoc(
+            "A {@link $T} that returns {@code $L}.",
+            Provider.class,
+            optionalKind.absentValueExpression())
+        .build();
+  }
+
+  /** Information about the type of a factory for present bindings. */
+  @AutoValue
+  abstract static class PresentFactorySpec {
+    /** Whether the factory is a {@link Provider} or a {@link Producer}. */
+    abstract FrameworkType frameworkType();
+
+    /** What kind of {@code Optional} is returned. */
+    abstract OptionalKind optionalKind();
+
+    /** The kind of request satisfied by the value of the {@code Optional}. */
+    abstract RequestKind valueKind();
+
+    /** The type variable for the factory class. */
+    TypeVariableName typeVariable() {
+      return TypeVariableName.get("T");
+    }
+
+    /** The type contained by the {@code Optional}. */
+    TypeName valueType() {
+      return requestTypeName(valueKind(), typeVariable());
+    }
+
+    /** The type provided or produced by the factory. */
+    ParameterizedTypeName optionalType() {
+      return optionalKind().of(valueType());
+    }
+
+    /** The type of the factory. */
+    ParameterizedTypeName factoryType() {
+      return frameworkType().frameworkClassOf(optionalType());
+    }
+
+    /** The type of the delegate provider or producer. */
+    ParameterizedTypeName delegateType() {
+      return frameworkType().frameworkClassOf(typeVariable());
+    }
+
+    /** Returns the superclass the generated factory should have, if any. */
+    Optional<ParameterizedTypeName> superclass() {
+      switch (frameworkType()) {
+        case PRODUCER_NODE:
+          // TODO(cgdecker): This probably isn't a big issue for now, but it's possible this
+          // shouldn't be an AbstractProducer:
+          // - As AbstractProducer, it'll only call the delegate's get() method once and then cache
+          //   that result (essentially) rather than calling the delegate's get() method each time
+          //   its get() method is called (which was what it did before the cancellation change).
+          // - It's not 100% clear to me whether the view-creation methods should return a view of
+          //   the same view created by the delegate or if they should just return their own views.
+          return Optional.of(abstractProducerOf(optionalType()));
+        default:
+          return Optional.empty();
+      }
+    }
+
+    /** Returns the superinterface the generated factory should have, if any. */
+    Optional<ParameterizedTypeName> superinterface() {
+      switch (frameworkType()) {
+        case PROVIDER:
+          return Optional.of(factoryType());
+        default:
+          return Optional.empty();
+      }
+    }
+
+    /** Returns the name of the factory method to generate. */
+    String factoryMethodName() {
+      switch (frameworkType()) {
+        case PROVIDER:
+          return "get";
+        case PRODUCER_NODE:
+          return "compute";
+      }
+      throw new AssertionError(frameworkType());
+    }
+
+    /** The name of the factory class. */
+    String factoryClassName() {
+      return new StringBuilder("Present")
+          .append(UPPER_UNDERSCORE.to(UPPER_CAMEL, optionalKind().name()))
+          .append(UPPER_UNDERSCORE.to(UPPER_CAMEL, valueKind().toString()))
+          .append(frameworkType().frameworkClass().getSimpleName())
+          .toString();
+    }
+
+    private static PresentFactorySpec of(ContributionBinding binding) {
+      return new AutoValue_OptionalFactories_PresentFactorySpec(
+          FrameworkType.forBindingType(binding.bindingType()),
+          OptionalType.from(binding.key()).kind(),
+          getOnlyElement(binding.dependencies()).kind());
+    }
+  }
+
+  /**
+   * Returns an expression for an instance of a nested class that implements {@code
+   * Provider<Optional<T>>} or {@code Producer<Optional<T>>} for a present optional binding, where
+   * {@code T} represents dependency requests of that kind.
+   *
+   * <ul>
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#INSTANCE}, the class implements
+   *       {@code ProviderOrProducer<Optional<T>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PROVIDER}, the class implements
+   *       {@code Provider<Optional<Provider<T>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#LAZY}, the class implements {@code
+   *       Provider<Optional<Lazy<T>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PROVIDER_OF_LAZY}, the class
+   *       implements {@code Provider<Optional<Provider<Lazy<T>>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PRODUCER}, the class implements
+   *       {@code Producer<Optional<Producer<T>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PRODUCED}, the class implements
+   *       {@code Producer<Optional<Produced<T>>>}.
+   * </ul>
+   *
+   * @param delegateFactory an expression for a {@link Provider} or {@link Producer} of the
+   *     underlying type
+   */
+  CodeBlock presentOptionalFactory(ContributionBinding binding, CodeBlock delegateFactory) {
+    return CodeBlock.of(
+        "$N.of($L)",
+        presentFactoryClasses.computeIfAbsent(
+            PresentFactorySpec.of(binding),
+            spec -> {
+              TypeSpec type = presentOptionalFactoryClass(spec);
+              componentImplementation.addType(PRESENT_FACTORY, type);
+              return type;
+            }),
+        delegateFactory);
+  }
+
+  private TypeSpec presentOptionalFactoryClass(PresentFactorySpec spec) {
+    FieldSpec delegateField =
+        FieldSpec.builder(spec.delegateType(), "delegate", PRIVATE, FINAL).build();
+    ParameterSpec delegateParameter = ParameterSpec.builder(delegateField.type, "delegate").build();
+    TypeSpec.Builder factoryClassBuilder =
+        classBuilder(spec.factoryClassName())
+            .addTypeVariable(spec.typeVariable())
+            .addModifiers(PRIVATE, STATIC, FINAL)
+            .addJavadoc(
+                "A {@code $T} that uses a delegate {@code $T}.",
+                spec.factoryType(),
+                delegateField.type);
+
+    spec.superclass().ifPresent(factoryClassBuilder::superclass);
+    spec.superinterface().ifPresent(factoryClassBuilder::addSuperinterface);
+
+    return factoryClassBuilder
+        .addField(delegateField)
+        .addMethod(
+            constructorBuilder()
+                .addModifiers(PRIVATE)
+                .addParameter(delegateParameter)
+                .addCode(
+                    "this.$N = $T.checkNotNull($N);",
+                    delegateField,
+                    Preconditions.class,
+                    delegateParameter)
+                .build())
+        .addMethod(presentOptionalFactoryGetMethod(spec, delegateField))
+        .addMethod(
+            methodBuilder("of")
+                .addModifiers(PRIVATE, STATIC)
+                .addTypeVariable(spec.typeVariable())
+                .returns(spec.factoryType())
+                .addParameter(delegateParameter)
+                .addCode(
+                    "return new $L<$T>($N);",
+                    spec.factoryClassName(),
+                    spec.typeVariable(),
+                    delegateParameter)
+                .build())
+        .build();
+  }
+
+  private MethodSpec presentOptionalFactoryGetMethod(
+      PresentFactorySpec spec, FieldSpec delegateField) {
+    MethodSpec.Builder getMethodBuilder =
+        methodBuilder(spec.factoryMethodName()).addAnnotation(Override.class).addModifiers(PUBLIC);
+
+    switch (spec.frameworkType()) {
+      case PROVIDER:
+        return getMethodBuilder
+            .returns(spec.optionalType())
+            .addCode(
+                "return $L;",
+                spec.optionalKind()
+                    .presentExpression(
+                        FrameworkType.PROVIDER.to(
+                            spec.valueKind(), CodeBlock.of("$N", delegateField))))
+            .build();
+
+      case PRODUCER_NODE:
+        getMethodBuilder.returns(listenableFutureOf(spec.optionalType()));
+
+        switch (spec.valueKind()) {
+          case FUTURE: // return a ListenableFuture<Optional<ListenableFuture<T>>>
+          case PRODUCER: // return a ListenableFuture<Optional<Producer<T>>>
+            return getMethodBuilder
+                .addCode(
+                    "return $T.immediateFuture($L);",
+                    Futures.class,
+                    spec.optionalKind()
+                        .presentExpression(
+                            FrameworkType.PRODUCER_NODE.to(
+                                spec.valueKind(), CodeBlock.of("$N", delegateField))))
+                .build();
+
+          case INSTANCE: // return a ListenableFuture<Optional<T>>
+            return getMethodBuilder
+                .addCode(
+                    "return $L;",
+                    transformFutureToOptional(
+                        spec.optionalKind(),
+                        spec.typeVariable(),
+                        CodeBlock.of("$N.get()", delegateField)))
+                .build();
+
+          case PRODUCED: // return a ListenableFuture<Optional<Produced<T>>>
+            return getMethodBuilder
+                .addCode(
+                    "return $L;",
+                    transformFutureToOptional(
+                        spec.optionalKind(),
+                        spec.valueType(),
+                        CodeBlock.of(
+                            "$T.createFutureProduced($N.get())", Producers.class, delegateField)))
+                .build();
+
+          default:
+            throw new UnsupportedOperationException(
+                spec.factoryType() + " objects are not supported");
+        }
+    }
+    throw new AssertionError(spec.frameworkType());
+  }
+
+  /**
+   * An expression that uses {@link Futures#transform(ListenableFuture, Function, Executor)} to
+   * transform a {@code ListenableFuture<inputType>} into a {@code
+   * ListenableFuture<Optional<inputType>>}.
+   *
+   * @param inputFuture an expression of type {@code ListenableFuture<inputType>}
+   */
+  private static CodeBlock transformFutureToOptional(
+      OptionalKind optionalKind, TypeName inputType, CodeBlock inputFuture) {
+    return CodeBlock.of(
+        "$T.transform($L, $L, $T.directExecutor())",
+        Futures.class,
+        inputFuture,
+        anonymousClassBuilder("")
+            .addSuperinterface(
+                ParameterizedTypeName.get(
+                    ClassName.get(Function.class), inputType, optionalKind.of(inputType)))
+            .addMethod(
+                methodBuilder("apply")
+                    .addAnnotation(Override.class)
+                    .addModifiers(PUBLIC)
+                    .returns(optionalKind.of(inputType))
+                    .addParameter(inputType, "input")
+                    .addCode("return $L;", optionalKind.presentExpression(CodeBlock.of("input")))
+                    .build())
+            .build(),
+        MoreExecutors.class);
+  }
+}
diff --git a/java/dagger/internal/codegen/OptionalFactoryInstanceCreationExpression.java b/java/dagger/internal/codegen/OptionalFactoryInstanceCreationExpression.java
new file mode 100644
index 0000000..ba9e25f
--- /dev/null
+++ b/java/dagger/internal/codegen/OptionalFactoryInstanceCreationExpression.java
@@ -0,0 +1,67 @@
+/*
+ * 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.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+
+/**
+ * A {@link FrameworkInstanceCreationExpression} for {@link dagger.model.BindingKind#OPTIONAL
+ * optional bindings}.
+ */
+final class OptionalFactoryInstanceCreationExpression
+    implements FrameworkInstanceCreationExpression {
+  private final OptionalFactories optionalFactories;
+  private final ContributionBinding binding;
+  private final ComponentImplementation componentImplementation;
+  private final ComponentBindingExpressions componentBindingExpressions;
+
+  OptionalFactoryInstanceCreationExpression(
+      OptionalFactories optionalFactories,
+      ContributionBinding binding,
+      ComponentImplementation componentImplementation,
+      ComponentBindingExpressions componentBindingExpressions) {
+    this.optionalFactories = optionalFactories;
+    this.binding = binding;
+    this.componentImplementation = componentImplementation;
+    this.componentBindingExpressions = componentBindingExpressions;
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    return binding.dependencies().isEmpty()
+        ? optionalFactories.absentOptionalProvider(binding)
+        : optionalFactories.presentOptionalFactory(
+            binding,
+            componentBindingExpressions
+                .getDependencyExpression(
+                    bindingRequest(
+                        getOnlyElement(binding.dependencies()).key(), binding.frameworkType()),
+                    componentImplementation.name())
+                .codeBlock());
+  }
+
+  @Override
+  public boolean useInnerSwitchingProvider() {
+    // Share providers for empty optionals from OptionalFactories so we don't have numerous
+    // switch cases that all return Optional.empty().
+    return !binding.dependencies().isEmpty();
+  }
+}
diff --git a/java/dagger/internal/codegen/OptionalType.java b/java/dagger/internal/codegen/OptionalType.java
new file mode 100644
index 0000000..0fdbf68
--- /dev/null
+++ b/java/dagger/internal/codegen/OptionalType.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkArgument;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Equivalence;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import dagger.model.Key;
+import java.util.Optional;
+import javax.lang.model.element.Name;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVisitor;
+import javax.lang.model.util.SimpleTypeVisitor8;
+
+/**
+ * Information about an {@code Optional} {@link TypeMirror}.
+ *
+ * <p>{@link com.google.common.base.Optional} and {@link java.util.Optional} are supported.
+ */
+@AutoValue
+abstract class OptionalType {
+
+  /** A variant of {@code Optional}. */
+  enum OptionalKind {
+    /** {@link com.google.common.base.Optional}. */
+    GUAVA_OPTIONAL(com.google.common.base.Optional.class, "absent"),
+
+    /** {@link java.util.Optional}. */
+    JDK_OPTIONAL(java.util.Optional.class, "empty"),
+    ;
+
+    private final Class<?> clazz;
+    private final String absentFactoryMethodName;
+
+    OptionalKind(Class<?> clazz, String absentFactoryMethodName) {
+      this.clazz = clazz;
+      this.absentFactoryMethodName = absentFactoryMethodName;
+    }
+
+    /** Returns {@code valueType} wrapped in the correct class. */
+    ParameterizedTypeName of(TypeName valueType) {
+      return ParameterizedTypeName.get(ClassName.get(clazz), valueType);
+    }
+
+    /** Returns an expression for the absent/empty value. */
+    CodeBlock absentValueExpression() {
+      return CodeBlock.of("$T.$L()", clazz, absentFactoryMethodName);
+    }
+
+    /**
+     * Returns an expression for the absent/empty value, parameterized with {@link #valueType()}.
+     */
+    CodeBlock parameterizedAbsentValueExpression(OptionalType optionalType) {
+      return CodeBlock.of("$T.<$T>$L()", clazz, optionalType.valueType(), absentFactoryMethodName);
+    }
+
+    /** Returns an expression for the present {@code value}. */
+    CodeBlock presentExpression(CodeBlock value) {
+      return CodeBlock.of("$T.of($L)", clazz, value);
+    }
+
+    /**
+     * Returns an expression for the present {@code value}, returning {@code Optional<Object>} no
+     * matter what type the value is.
+     */
+    CodeBlock presentObjectExpression(CodeBlock value) {
+      return CodeBlock.of("$T.<$T>of($L)", clazz, Object.class, value);
+    }
+  }
+
+  private static final TypeVisitor<Optional<OptionalKind>, Void> OPTIONAL_KIND =
+      new SimpleTypeVisitor8<Optional<OptionalKind>, Void>(Optional.empty()) {
+        @Override
+        public Optional<OptionalKind> visitDeclared(DeclaredType t, Void p) {
+          for (OptionalKind optionalKind : OptionalKind.values()) {
+            Name qualifiedName = MoreElements.asType(t.asElement()).getQualifiedName();
+            if (qualifiedName.contentEquals(optionalKind.clazz.getCanonicalName())) {
+              return Optional.of(optionalKind);
+            }
+          }
+          return Optional.empty();
+        }
+      };
+
+  /**
+   * The optional type itself, wrapped using {@link MoreTypes#equivalence()}.
+   *
+   * @deprecated Use {@link #declaredOptionalType()} instead.
+   */
+  @Deprecated
+  protected abstract Equivalence.Wrapper<DeclaredType> wrappedDeclaredOptionalType();
+
+  /** The optional type itself. */
+  @SuppressWarnings("deprecation")
+  DeclaredType declaredOptionalType() {
+    return wrappedDeclaredOptionalType().get();
+  }
+  
+  /** Which {@code Optional} type is used. */
+  OptionalKind kind() {
+    return declaredOptionalType().accept(OPTIONAL_KIND, null).get();
+  }
+
+  /** The value type. */
+  TypeMirror valueType() {
+    return declaredOptionalType().getTypeArguments().get(0);
+  }
+
+  /** Returns {@code true} if {@code type} is an {@code Optional} type. */
+  static boolean isOptional(TypeMirror type) {
+    return type.accept(OPTIONAL_KIND, null).isPresent();
+  }
+
+  /** Returns {@code true} if {@code key.type()} is an {@code Optional} type. */
+  static boolean isOptional(Key key) {
+    return isOptional(key.type());
+  }
+
+  /**
+   * Returns a {@link OptionalType} for {@code type}.
+   *
+   * @throws IllegalArgumentException if {@code type} is not an {@code Optional} type
+   */
+  static OptionalType from(TypeMirror type) {
+    checkArgument(isOptional(type), "%s must be an Optional", type);
+    return new AutoValue_OptionalType(MoreTypes.equivalence().wrap(MoreTypes.asDeclared(type)));
+  }
+
+  /**
+   * Returns a {@link OptionalType} for {@code key}'s {@link Key#type() type}.
+   *
+   * @throws IllegalArgumentException if {@code key.type()} is not an {@code Optional} type
+   */
+  static OptionalType from(Key key) {
+    return from(key.type());
+  }
+}
diff --git a/java/dagger/internal/codegen/Optionals.java b/java/dagger/internal/codegen/Optionals.java
new file mode 100644
index 0000000..1021c35
--- /dev/null
+++ b/java/dagger/internal/codegen/Optionals.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Lists.asList;
+
+import java.util.Comparator;
+import java.util.Optional;
+import java.util.function.Function;
+
+/** Utilities for {@link Optional}s. */
+final class Optionals {
+  /**
+   * A {@link Comparator} that puts empty {@link Optional}s before present ones, and compares
+   * present {@link Optional}s by their values.
+   */
+  static <C extends Comparable<C>> Comparator<Optional<C>> optionalComparator() {
+    return Comparator.comparing((Optional<C> optional) -> optional.isPresent())
+        .thenComparing(Optional::get);
+  }
+
+  static <T> Comparator<Optional<T>> emptiesLast(Comparator<? super T> valueComparator) {
+    checkNotNull(valueComparator);
+    return Comparator.comparing(o -> o.orElse(null), Comparator.nullsLast(valueComparator));
+  }
+
+  /** Returns the first argument that is present, or empty if none are. */
+  @SafeVarargs
+  static <T> Optional<T> firstPresent(Optional<T> first, Optional<T> second, Optional<T>... rest) {
+    return asList(first, second, rest)
+        .stream()
+        .filter(Optional::isPresent)
+        .findFirst()
+        .orElse(Optional.empty());
+  }
+
+  /**
+   * Walks a chain of present optionals as defined by successive calls to {@code nextFunction},
+   * returning the value of the final optional that is present. The first optional in the chain is
+   * the result of {@code nextFunction(start)}.
+   */
+  static <T> T rootmostValue(T start, Function<T, Optional<T>> nextFunction) {
+    T current = start;
+    for (Optional<T> next = nextFunction.apply(start);
+        next.isPresent();
+        next = nextFunction.apply(current)) {
+      current = next.get();
+    }
+    return current;
+  }
+
+  private Optionals() {}
+}
diff --git a/java/dagger/internal/codegen/ParentComponent.java b/java/dagger/internal/codegen/ParentComponent.java
new file mode 100644
index 0000000..2d2b583
--- /dev/null
+++ b/java/dagger/internal/codegen/ParentComponent.java
@@ -0,0 +1,30 @@
+/*
+ * 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 java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import javax.inject.Qualifier;
+
+/**
+ * A {@link Qualifier} for bindings that are associated with a component implementation's
+ * parent component.
+ */
+@Retention(RUNTIME)
+@Qualifier
+@interface ParentComponent {}
diff --git a/java/dagger/internal/codegen/PerComponentImplementation.java b/java/dagger/internal/codegen/PerComponentImplementation.java
new file mode 100644
index 0000000..5d4ba18
--- /dev/null
+++ b/java/dagger/internal/codegen/PerComponentImplementation.java
@@ -0,0 +1,27 @@
+/*
+ * 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 java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import javax.inject.Scope;
+
+/** A {@link Scope} that encompasses a single component implementation. */
+@Retention(RUNTIME)
+@Scope
+@interface PerComponentImplementation {}
diff --git a/java/dagger/internal/codegen/PerGeneratedFile.java b/java/dagger/internal/codegen/PerGeneratedFile.java
new file mode 100644
index 0000000..c30e67a
--- /dev/null
+++ b/java/dagger/internal/codegen/PerGeneratedFile.java
@@ -0,0 +1,30 @@
+/*
+ * 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 java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import javax.inject.Scope;
+
+/**
+ * A {@link Scope} that encompasses a top-level component implementation and any of its inner
+ * descendant component implementations in the same generated file.
+ */
+@Retention(RUNTIME)
+@Scope
+@interface PerGeneratedFile {}
diff --git a/java/dagger/internal/codegen/PrivateMethodBindingExpression.java b/java/dagger/internal/codegen/PrivateMethodBindingExpression.java
new file mode 100644
index 0000000..482c123
--- /dev/null
+++ b/java/dagger/internal/codegen/PrivateMethodBindingExpression.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.PRIVATE_METHOD;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+
+/**
+ * A binding expression that wraps the dependency expressions in a private, no-arg method.
+ *
+ * <p>Dependents of this binding expression will just call the no-arg private method.
+ */
+final class PrivateMethodBindingExpression extends MethodBindingExpression {
+  private final BindingRequest request;
+  private final ComponentImplementation componentImplementation;
+  private String methodName;
+
+  PrivateMethodBindingExpression(
+      BindingRequest request,
+      ResolvedBindings resolvedBindings,
+      MethodImplementationStrategy methodImplementationStrategy,
+      BindingExpression wrappedBindingExpression,
+      ComponentImplementation componentImplementation,
+      DaggerTypes types) {
+    super(
+        request,
+        resolvedBindings,
+        methodImplementationStrategy,
+        wrappedBindingExpression,
+        componentImplementation,
+        types);
+    this.request = checkNotNull(request);
+    this.componentImplementation = checkNotNull(componentImplementation);
+  }
+
+  @Override
+  protected void addMethod() {
+    if (methodName == null) {
+      // Have to set methodName field before implementing the method in order to handle recursion.
+      methodName = componentImplementation.getUniqueMethodName(request);
+      // TODO(user): Fix the order that these generated methods are written to the component.
+      componentImplementation.addMethod(
+          PRIVATE_METHOD,
+          methodBuilder(methodName)
+              .addModifiers(PRIVATE)
+              .returns(TypeName.get(returnType()))
+              .addCode(methodBody())
+              .build());
+    }
+  }
+
+  @Override
+  protected String methodName() {
+    checkState(methodName != null, "addMethod() must be called before methodName()");
+    return methodName;
+  }
+}
diff --git a/java/dagger/internal/codegen/ProcessingEnvironmentCompilerOptions.java b/java/dagger/internal/codegen/ProcessingEnvironmentCompilerOptions.java
new file mode 100644
index 0000000..cf2475d
--- /dev/null
+++ b/java/dagger/internal/codegen/ProcessingEnvironmentCompilerOptions.java
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2019 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.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Sets.immutableEnumSet;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.FeatureStatus.DISABLED;
+import static dagger.internal.codegen.FeatureStatus.ENABLED;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.EMIT_MODIFIABLE_METADATA_ANNOTATIONS;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.EXPERIMENTAL_ANDROID_MODE;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.FAST_INIT;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.FLOATING_BINDS_METHODS;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.FORCE_USE_SERIALIZED_COMPONENT_IMPLEMENTATIONS;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.FORMAT_GENERATED_SOURCE;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.WRITE_PRODUCER_NAME_IN_TOKEN;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.KeyOnlyOption.HEADER_COMPILATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.KeyOnlyOption.USE_GRADLE_INCREMENTAL_PROCESSING;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.DISABLE_INTER_COMPONENT_SCOPE_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.EXPLICIT_BINDING_CONFLICTS_WITH_INJECT;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.FULL_BINDING_GRAPH_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.MODULE_HAS_DIFFERENT_SCOPES_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.NULLABLE_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.PRIVATE_MEMBER_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.STATIC_MEMBER_VALIDATION;
+import static dagger.internal.codegen.ValidationType.ERROR;
+import static dagger.internal.codegen.ValidationType.NONE;
+import static dagger.internal.codegen.ValidationType.WARNING;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Stream.concat;
+
+import com.google.common.base.Ascii;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import dagger.producers.Produces;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+final class ProcessingEnvironmentCompilerOptions extends CompilerOptions {
+  /** Returns a valid {@link CompilerOptions} parsed from the processing environment. */
+  static CompilerOptions create(ProcessingEnvironment processingEnvironment) {
+    return new ProcessingEnvironmentCompilerOptions(processingEnvironment).checkValid();
+  }
+
+  private final ProcessingEnvironment processingEnvironment;
+  private final Map<EnumOption<?>, Object> enumOptions = new HashMap<>();
+  private final Map<EnumOption<?>, ImmutableMap<String, ? extends Enum<?>>> allCommandLineOptions =
+      new HashMap<>();
+
+  private ProcessingEnvironmentCompilerOptions(ProcessingEnvironment processingEnvironment) {
+    this.processingEnvironment = processingEnvironment;
+  }
+
+  @Override
+  boolean usesProducers() {
+    return processingEnvironment.getElementUtils().getTypeElement(Produces.class.getCanonicalName())
+        != null;
+  }
+
+  @Override
+  boolean headerCompilation() {
+    return isEnabled(HEADER_COMPILATION);
+  }
+
+  @Override
+  boolean fastInit() {
+    return isEnabled(FAST_INIT);
+  }
+
+  @Override
+  boolean formatGeneratedSource() {
+    return isEnabled(FORMAT_GENERATED_SOURCE);
+  }
+
+  @Override
+  boolean writeProducerNameInToken() {
+    return isEnabled(WRITE_PRODUCER_NAME_IN_TOKEN);
+  }
+
+  @Override
+  Diagnostic.Kind nullableValidationKind() {
+    return diagnosticKind(NULLABLE_VALIDATION);
+  }
+
+  @Override
+  Diagnostic.Kind privateMemberValidationKind() {
+    return diagnosticKind(PRIVATE_MEMBER_VALIDATION);
+  }
+
+  @Override
+  Diagnostic.Kind staticMemberValidationKind() {
+    return diagnosticKind(STATIC_MEMBER_VALIDATION);
+  }
+
+  @Override
+  boolean ignorePrivateAndStaticInjectionForComponent() {
+    return isEnabled(IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT);
+  }
+
+  @Override
+  ValidationType scopeCycleValidationType() {
+    return parseOption(DISABLE_INTER_COMPONENT_SCOPE_VALIDATION);
+  }
+
+  @Override
+  boolean warnIfInjectionFactoryNotGeneratedUpstream() {
+    return isEnabled(WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM);
+  }
+
+  @Override
+  boolean aheadOfTimeSubcomponents() {
+    return isEnabled(EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS);
+  }
+
+  @Override
+  boolean forceUseSerializedComponentImplementations() {
+    return isEnabled(FORCE_USE_SERIALIZED_COMPONENT_IMPLEMENTATIONS);
+  }
+
+  @Override
+  boolean emitModifiableMetadataAnnotations() {
+    return isEnabled(EMIT_MODIFIABLE_METADATA_ANNOTATIONS);
+  }
+
+  @Override
+  boolean useGradleIncrementalProcessing() {
+    return isEnabled(USE_GRADLE_INCREMENTAL_PROCESSING);
+  }
+
+  @Override
+  ValidationType fullBindingGraphValidationType(TypeElement element) {
+    return fullBindingGraphValidationType();
+  }
+
+  private ValidationType fullBindingGraphValidationType() {
+    return parseOption(FULL_BINDING_GRAPH_VALIDATION);
+  }
+
+  @Override
+  Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind() {
+    return diagnosticKind(MODULE_HAS_DIFFERENT_SCOPES_VALIDATION);
+  }
+
+  @Override
+  ValidationType explicitBindingConflictsWithInjectValidationType() {
+    return parseOption(EXPLICIT_BINDING_CONFLICTS_WITH_INJECT);
+  }
+
+  private boolean isEnabled(KeyOnlyOption keyOnlyOption) {
+    return processingEnvironment.getOptions().containsKey(keyOnlyOption.toString());
+  }
+
+  private boolean isEnabled(Feature feature) {
+    return parseOption(feature).equals(ENABLED);
+  }
+
+  private Diagnostic.Kind diagnosticKind(Validation validation) {
+    return parseOption(validation).diagnosticKind().get();
+  }
+
+  @SuppressWarnings("CheckReturnValue")
+  private ProcessingEnvironmentCompilerOptions checkValid() {
+    for (KeyOnlyOption keyOnlyOption : KeyOnlyOption.values()) {
+      isEnabled(keyOnlyOption);
+    }
+    for (Feature feature : Feature.values()) {
+      parseOption(feature);
+    }
+    for (Validation validation : Validation.values()) {
+      parseOption(validation);
+    }
+    noLongerRecognized(EXPERIMENTAL_ANDROID_MODE);
+    noLongerRecognized(FLOATING_BINDS_METHODS);
+    return this;
+  }
+
+  private void noLongerRecognized(CommandLineOption commandLineOption) {
+    if (processingEnvironment.getOptions().containsKey(commandLineOption.toString())) {
+      processingEnvironment
+          .getMessager()
+          .printMessage(
+              Diagnostic.Kind.WARNING, commandLineOption + " is no longer recognized by Dagger");
+    }
+  }
+
+  private interface CommandLineOption {
+    /** The key of the option (appears after "-A"). */
+    @Override
+    String toString();
+
+    /**
+     * Returns all aliases besides {@link #toString()}, such as old names for an option, in order of
+     * precedence.
+     */
+    default ImmutableList<String> aliases() {
+      return ImmutableList.of();
+    }
+
+    /** All the command-line names for this option, in order of precedence. */
+    default Stream<String> allNames() {
+      return concat(Stream.of(toString()), aliases().stream());
+    }
+  }
+
+  /** An option that can be set on the command line. */
+  private interface EnumOption<E extends Enum<E>> extends CommandLineOption {
+    /** The default value for this option. */
+    E defaultValue();
+
+    /** The valid values for this option. */
+    Set<E> validValues();
+  }
+
+  enum KeyOnlyOption implements CommandLineOption {
+    HEADER_COMPILATION {
+      @Override
+      public String toString() {
+        return "experimental_turbine_hjar";
+      }
+    },
+
+    USE_GRADLE_INCREMENTAL_PROCESSING {
+      @Override
+      public String toString() {
+        return "dagger.gradle.incremental";
+      }
+    },
+  }
+
+  /**
+   * A feature that can be enabled or disabled on the command line by setting {@code -Akey=ENABLED}
+   * or {@code -Akey=DISABLED}.
+   */
+  enum Feature implements EnumOption<FeatureStatus> {
+    FAST_INIT,
+
+    EXPERIMENTAL_ANDROID_MODE,
+
+    FORMAT_GENERATED_SOURCE,
+
+    WRITE_PRODUCER_NAME_IN_TOKEN,
+
+    WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM,
+
+    IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT,
+
+    EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS,
+
+    FORCE_USE_SERIALIZED_COMPONENT_IMPLEMENTATIONS,
+
+    EMIT_MODIFIABLE_METADATA_ANNOTATIONS(ENABLED),
+
+    FLOATING_BINDS_METHODS,
+    ;
+
+    final FeatureStatus defaultValue;
+
+    Feature() {
+      this(DISABLED);
+    }
+
+    Feature(FeatureStatus defaultValue) {
+      this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public FeatureStatus defaultValue() {
+      return defaultValue;
+    }
+
+    @Override
+    public Set<FeatureStatus> validValues() {
+      return EnumSet.allOf(FeatureStatus.class);
+    }
+
+    @Override
+    public String toString() {
+      return optionName(this);
+    }
+  }
+
+  /** The diagnostic kind or validation type for a kind of validation. */
+  enum Validation implements EnumOption<ValidationType> {
+    DISABLE_INTER_COMPONENT_SCOPE_VALIDATION(),
+
+    NULLABLE_VALIDATION(ERROR, WARNING),
+
+    PRIVATE_MEMBER_VALIDATION(ERROR, WARNING),
+
+    STATIC_MEMBER_VALIDATION(ERROR, WARNING),
+
+    /** Whether to validate full binding graphs for components, subcomponents, and modules. */
+    FULL_BINDING_GRAPH_VALIDATION(NONE, ERROR, WARNING) {
+      @Override
+      public ImmutableList<String> aliases() {
+        return ImmutableList.of("dagger.moduleBindingValidation");
+      }
+    },
+
+    /**
+     * How to report conflicting scoped bindings when validating partial binding graphs associated
+     * with modules.
+     */
+    MODULE_HAS_DIFFERENT_SCOPES_VALIDATION(ERROR, WARNING),
+
+    /**
+     * How to report that an explicit binding in a subcomponent conflicts with an {@code @Inject}
+     * constructor used in an ancestor component.
+     */
+    EXPLICIT_BINDING_CONFLICTS_WITH_INJECT(WARNING, ERROR, NONE),
+    ;
+
+    final ValidationType defaultType;
+    final ImmutableSet<ValidationType> validTypes;
+
+    Validation() {
+      this(ERROR, WARNING, NONE);
+    }
+
+    Validation(ValidationType defaultType, ValidationType... moreValidTypes) {
+      this.defaultType = defaultType;
+      this.validTypes = immutableEnumSet(defaultType, moreValidTypes);
+    }
+
+    @Override
+    public ValidationType defaultValue() {
+      return defaultType;
+    }
+
+    @Override
+    public Set<ValidationType> validValues() {
+      return validTypes;
+    }
+
+    @Override
+    public String toString() {
+      return optionName(this);
+    }
+  }
+
+  private static String optionName(Enum<? extends EnumOption<?>> option) {
+    return "dagger." + UPPER_UNDERSCORE.to(LOWER_CAMEL, option.name());
+  }
+
+  /** The supported command-line options. */
+  static ImmutableSet<String> supportedOptions() {
+    // need explicit type parameter to avoid a runtime stream error
+    return Stream.<CommandLineOption[]>of(
+            KeyOnlyOption.values(), Feature.values(), Validation.values())
+        .flatMap(Arrays::stream)
+        .flatMap(CommandLineOption::allNames)
+        .collect(toImmutableSet());
+  }
+
+  /**
+   * Returns the value for the option as set on the command line by any name, or the default value
+   * if not set.
+   *
+   * <p>If more than one name is used to set the value, but all names specify the same value,
+   * reports a warning and returns that value.
+   *
+   * <p>If more than one name is used to set the value, and not all names specify the same value,
+   * reports an error and returns the default value.
+   */
+  private <T extends Enum<T>> T parseOption(EnumOption<T> option) {
+    @SuppressWarnings("unchecked") // we only put covariant values into the map
+    T value = (T) enumOptions.computeIfAbsent(option, this::parseOptionUncached);
+    return value;
+  }
+
+  private <T extends Enum<T>> T parseOptionUncached(EnumOption<T> option) {
+    ImmutableMap<String, T> values = parseOptionWithAllNames(option);
+
+    // If no value is specified, return the default value.
+    if (values.isEmpty()) {
+      return option.defaultValue();
+    }
+
+    // If all names have the same value, return that.
+    if (values.asMultimap().inverse().keySet().size() == 1) {
+      // Warn if an option was set with more than one name. That would be an error if the values
+      // differed.
+      if (values.size() > 1) {
+        reportUseOfDifferentNamesForOption(Diagnostic.Kind.WARNING, option, values.keySet());
+      }
+      return values.values().asList().get(0);
+    }
+
+    // If different names have different values, report an error and return the default
+    // value.
+    reportUseOfDifferentNamesForOption(Diagnostic.Kind.ERROR, option, values.keySet());
+    return option.defaultValue();
+  }
+
+  private void reportUseOfDifferentNamesForOption(
+      Diagnostic.Kind diagnosticKind, EnumOption<?> option, ImmutableSet<String> usedNames) {
+    processingEnvironment
+        .getMessager()
+        .printMessage(
+            diagnosticKind,
+            String.format(
+                "Only one of the equivalent options (%s) should be used; prefer -A%s",
+                usedNames.stream().map(name -> "-A" + name).collect(joining(", ")), option));
+  }
+
+  private <T extends Enum<T>> ImmutableMap<String, T> parseOptionWithAllNames(
+      EnumOption<T> option) {
+    @SuppressWarnings("unchecked") // map is covariant
+    ImmutableMap<String, T> aliasValues =
+        (ImmutableMap<String, T>)
+            allCommandLineOptions.computeIfAbsent(option, this::parseOptionWithAllNamesUncached);
+    return aliasValues;
+  }
+
+  private <T extends Enum<T>> ImmutableMap<String, T> parseOptionWithAllNamesUncached(
+      EnumOption<T> option) {
+    ImmutableMap.Builder<String, T> values = ImmutableMap.builder();
+    getUsedNames(option)
+        .forEach(
+            name -> parseOptionWithName(option, name).ifPresent(value -> values.put(name, value)));
+    return values.build();
+  }
+
+  private <T extends Enum<T>> Optional<T> parseOptionWithName(EnumOption<T> option, String key) {
+    checkArgument(processingEnvironment.getOptions().containsKey(key), "key %s not found", key);
+    String stringValue = processingEnvironment.getOptions().get(key);
+    if (stringValue == null) {
+      processingEnvironment
+          .getMessager()
+          .printMessage(Diagnostic.Kind.ERROR, "Processor option -A" + key + " needs a value");
+    } else {
+      try {
+        T value =
+            Enum.valueOf(option.defaultValue().getDeclaringClass(), Ascii.toUpperCase(stringValue));
+        if (option.validValues().contains(value)) {
+          return Optional.of(value);
+        }
+      } catch (IllegalArgumentException e) {
+        // handled below
+      }
+      processingEnvironment
+          .getMessager()
+          .printMessage(
+              Diagnostic.Kind.ERROR,
+              String.format(
+                  "Processor option -A%s may only have the values %s "
+                      + "(case insensitive), found: %s",
+                  key, option.validValues(), stringValue));
+    }
+    return Optional.empty();
+  }
+
+  private Stream<String> getUsedNames(CommandLineOption option) {
+    return option.allNames().filter(name -> processingEnvironment.getOptions().containsKey(name));
+  }
+}
diff --git a/java/dagger/internal/codegen/ProcessingEnvironmentModule.java b/java/dagger/internal/codegen/ProcessingEnvironmentModule.java
index 8a535fe..1730574 100644
--- a/java/dagger/internal/codegen/ProcessingEnvironmentModule.java
+++ b/java/dagger/internal/codegen/ProcessingEnvironmentModule.java
@@ -16,18 +16,15 @@
 
 package dagger.internal.codegen;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import com.google.googlejavaformat.java.filer.FormattingFiler;
-import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
 import dagger.Reusable;
-import dagger.internal.codegen.SpiModule.ProcessorClassLoader;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions;
-import dagger.internal.codegen.compileroption.ProcessingOptions;
 import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.spi.BindingGraphPlugin;
 import java.util.Map;
+import java.util.Optional;
 import javax.annotation.processing.Filer;
 import javax.annotation.processing.Messager;
 import javax.annotation.processing.ProcessingEnvironment;
@@ -36,25 +33,27 @@
 
 /** Bindings that depend on the {@link ProcessingEnvironment}. */
 @Module
-interface ProcessingEnvironmentModule {
-  @Binds
-  @Reusable // to avoid parsing options more than once
-  CompilerOptions bindCompilerOptions(
-      ProcessingEnvironmentCompilerOptions processingEnvironmentCompilerOptions);
+final class ProcessingEnvironmentModule {
+
+  private final ProcessingEnvironment processingEnvironment;
+
+  ProcessingEnvironmentModule(ProcessingEnvironment processingEnvironment) {
+    this.processingEnvironment = checkNotNull(processingEnvironment);
+  }
 
   @Provides
   @ProcessingOptions
-  static Map<String, String> processingOptions(ProcessingEnvironment processingEnvironment) {
+  Map<String, String> processingOptions() {
     return processingEnvironment.getOptions();
   }
 
   @Provides
-  static Messager messager(ProcessingEnvironment processingEnvironment) {
+  Messager messager() {
     return processingEnvironment.getMessager();
   }
 
   @Provides
-  static Filer filer(CompilerOptions compilerOptions, ProcessingEnvironment processingEnvironment) {
+  Filer filer(CompilerOptions compilerOptions) {
     if (compilerOptions.headerCompilation() || !compilerOptions.formatGeneratedSource()) {
       return processingEnvironment.getFiler();
     } else {
@@ -63,23 +62,28 @@
   }
 
   @Provides
-  static Types types(ProcessingEnvironment processingEnvironment) {
+  Types types() {
     return processingEnvironment.getTypeUtils();
   }
 
   @Provides
-  static SourceVersion sourceVersion(ProcessingEnvironment processingEnvironment) {
+  SourceVersion sourceVersion() {
     return processingEnvironment.getSourceVersion();
   }
 
   @Provides
-  static DaggerElements daggerElements(ProcessingEnvironment processingEnvironment) {
+  DaggerElements daggerElements() {
     return new DaggerElements(processingEnvironment);
   }
 
   @Provides
-  @ProcessorClassLoader
-  static ClassLoader processorClassloader(ProcessingEnvironment processingEnvironment) {
-    return BindingGraphPlugin.class.getClassLoader();
+  @Reusable // to avoid parsing options more than once
+  CompilerOptions compilerOptions() {
+    return ProcessingEnvironmentCompilerOptions.create(processingEnvironment);
+  }
+
+  @Provides
+  Optional<DaggerStatisticsRecorder> daggerStatisticsRecorder() {
+    return Optional.empty();
   }
 }
diff --git a/java/dagger/internal/codegen/ProcessingOptions.java b/java/dagger/internal/codegen/ProcessingOptions.java
new file mode 100644
index 0000000..105452a
--- /dev/null
+++ b/java/dagger/internal/codegen/ProcessingOptions.java
@@ -0,0 +1,30 @@
+/*
+ * 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 java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import javax.inject.Qualifier;
+
+/**
+ * A qualifier for the {@link javax.annotation.processing.ProcessingEnvironment#getOptions()
+ * processing options} passed to the current invocation of {@code javac}.
+ */
+@Retention(RUNTIME)
+@Qualifier
+@interface ProcessingOptions {}
diff --git a/java/dagger/internal/codegen/ProcessingRoundCacheModule.java b/java/dagger/internal/codegen/ProcessingRoundCacheModule.java
index 2373cd2..b56cc30 100644
--- a/java/dagger/internal/codegen/ProcessingRoundCacheModule.java
+++ b/java/dagger/internal/codegen/ProcessingRoundCacheModule.java
@@ -18,14 +18,6 @@
 
 import dagger.Binds;
 import dagger.Module;
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.ModuleDescriptor;
-import dagger.internal.codegen.kotlin.KotlinMetadataFactory;
-import dagger.internal.codegen.validation.AnyBindingMethodValidator;
-import dagger.internal.codegen.validation.ComponentCreatorValidator;
-import dagger.internal.codegen.validation.ComponentValidator;
-import dagger.internal.codegen.validation.InjectValidator;
 import dagger.multibindings.IntoSet;
 
 /**
@@ -36,14 +28,6 @@
 interface ProcessingRoundCacheModule {
   @Binds
   @IntoSet
-  ClearableCache anyBindingMethodValidator(AnyBindingMethodValidator cache);
-
-  @Binds
-  @IntoSet
-  ClearableCache injectValidator(InjectValidator cache);
-
-  @Binds
-  @IntoSet
   ClearableCache moduleDescriptorFactory(ModuleDescriptor.Factory cache);
 
   @Binds
@@ -52,13 +36,5 @@
 
   @Binds
   @IntoSet
-  ClearableCache componentValidator(ComponentValidator cache);
-
-  @Binds
-  @IntoSet
-  ClearableCache componentCreatorValidator(ComponentCreatorValidator cache);
-
-  @Binds
-  @IntoSet
-  ClearableCache kotlinMetadata(KotlinMetadataFactory cache);
+  ClearableCache componentImplementationFactory(ComponentImplementationFactory cache);
 }
diff --git a/java/dagger/internal/codegen/ProducerCreationExpression.java b/java/dagger/internal/codegen/ProducerCreationExpression.java
new file mode 100644
index 0000000..1dd7a1c
--- /dev/null
+++ b/java/dagger/internal/codegen/ProducerCreationExpression.java
@@ -0,0 +1,48 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+
+/**
+ * A {@link dagger.producers.Producer} creation expression for a {@link
+ * dagger.producers.Produces @Produces}-annotated module method.
+ */
+// TODO(dpb): Resolve with InjectionOrProvisionProviderCreationExpression.
+final class ProducerCreationExpression implements FrameworkInstanceCreationExpression {
+
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final ContributionBinding binding;
+
+  ProducerCreationExpression(
+      ContributionBinding binding, ComponentBindingExpressions componentBindingExpressions) {
+    this.binding = checkNotNull(binding);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    return CodeBlock.of(
+        "$T.create($L)",
+        generatedClassNameForBinding(binding),
+        componentBindingExpressions.getCreateMethodArgumentsCodeBlock(binding));
+  }
+}
diff --git a/java/dagger/internal/codegen/ProducerEntryPointView.java b/java/dagger/internal/codegen/ProducerEntryPointView.java
new file mode 100644
index 0000000..87b5a4a
--- /dev/null
+++ b/java/dagger/internal/codegen/ProducerEntryPointView.java
@@ -0,0 +1,110 @@
+/*
+ * 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 dagger.internal.codegen.ComponentImplementation.FieldSpecKind.FRAMEWORK_FIELD;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.RequestKind;
+import dagger.producers.Producer;
+import dagger.producers.internal.CancellationListener;
+import dagger.producers.internal.Producers;
+import java.util.Optional;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A factory of {@linkplain Producers#entryPointViewOf(Producer, CancellationListener) entry point
+ * views} of {@link Producer}s.
+ */
+final class ProducerEntryPointView {
+  private final DaggerTypes types;
+
+  ProducerEntryPointView(DaggerTypes types) {
+    this.types = types;
+  }
+
+  /**
+   * Returns an expression for an {@linkplain Producers#entryPointViewOf(Producer,
+   * CancellationListener) entry point view} of a producer if the component method returns a {@link
+   * Producer} or {@link com.google.common.util.concurrent.ListenableFuture}.
+   *
+   * <p>This is intended to be a replacement implementation for {@link
+   * BindingExpression#getDependencyExpressionForComponentMethod(ComponentMethodDescriptor,
+   * ComponentImplementation)}, and in cases where {@link Optional#empty()} is returned, callers
+   * should call {@code super.getDependencyExpressionForComponentMethod()}.
+   */
+  Optional<Expression> getProducerEntryPointField(
+      BindingExpression producerExpression,
+      ComponentMethodDescriptor componentMethod,
+      ComponentImplementation component) {
+    if (component.componentDescriptor().isProduction()
+        && (componentMethod.dependencyRequest().get().kind().equals(RequestKind.FUTURE)
+            || componentMethod.dependencyRequest().get().kind().equals(RequestKind.PRODUCER))) {
+      return Optional.of(
+          Expression.create(
+              fieldType(componentMethod),
+              "$N",
+              createField(producerExpression, componentMethod, component)));
+    } else {
+      // If the component isn't a production component, it won't implement CancellationListener and
+      // as such we can't create an entry point. But this binding must also just be a Producer from
+      // Provider anyway in that case, so there shouldn't be an issue.
+      // TODO(b/116855531): Is it really intended that a non-production component can have Producer
+      // entry points?
+      return Optional.empty();
+    }
+  }
+
+  private FieldSpec createField(
+      BindingExpression producerExpression,
+      ComponentMethodDescriptor componentMethod,
+      ComponentImplementation component) {
+    // TODO(cgdecker): Use a FrameworkFieldInitializer for this?
+    // Though I don't think we need the once-only behavior of that, since I think
+    // getComponentMethodImplementation will only be called once anyway
+    String methodName = componentMethod.methodElement().getSimpleName().toString();
+    FieldSpec field =
+        FieldSpec.builder(
+                TypeName.get(fieldType(componentMethod)),
+                component.getUniqueFieldName(methodName + "EntryPoint"),
+                PRIVATE)
+            .build();
+    component.addField(FRAMEWORK_FIELD, field);
+
+    CodeBlock fieldInitialization =
+        CodeBlock.of(
+            "this.$N = $T.entryPointViewOf($L, this);",
+            field,
+            Producers.class,
+            producerExpression.getDependencyExpression(component.name()).codeBlock());
+    component.addInitialization(fieldInitialization);
+
+    return field;
+  }
+
+  // TODO(cgdecker): Can we use producerExpression.getDependencyExpression().type() instead of
+  // needing to (re)compute this?
+  private TypeMirror fieldType(ComponentMethodDescriptor componentMethod) {
+    return types.wrapType(componentMethod.dependencyRequest().get().key().type(), Producer.class);
+  }
+}
diff --git a/java/dagger/internal/codegen/ProducerFactoryGenerator.java b/java/dagger/internal/codegen/ProducerFactoryGenerator.java
new file mode 100644
index 0000000..3f2bef4
--- /dev/null
+++ b/java/dagger/internal/codegen/ProducerFactoryGenerator.java
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Verify.verifyNotNull;
+import static com.squareup.javapoet.ClassName.OBJECT;
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.GwtCompatibility.gwtIncompatibleAnnotation;
+import static dagger.internal.codegen.SourceFiles.bindingTypeElementTypeVariableNames;
+import static dagger.internal.codegen.SourceFiles.generateBindingFieldsForDependencies;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+import static dagger.internal.codegen.SourceFiles.parameterizedGeneratedTypeNameForBinding;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.FUTURES;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCERS;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER_TOKEN;
+import static dagger.internal.codegen.javapoet.TypeNames.VOID_CLASS;
+import static dagger.internal.codegen.javapoet.TypeNames.listOf;
+import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.javapoet.TypeNames.producedOf;
+import static java.util.stream.Collectors.joining;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PROTECTED;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.javapoet.AnnotationSpecs;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import dagger.producers.Producer;
+import dagger.producers.internal.AbstractProducesMethodProducer;
+import dagger.producers.internal.Producers;
+import java.util.Map;
+import java.util.Optional;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Generates {@link Producer} implementations from {@link ProductionBinding} instances.
+ */
+final class ProducerFactoryGenerator extends SourceFileGenerator<ProductionBinding> {
+  private final CompilerOptions compilerOptions;
+  private final KeyFactory keyFactory;
+
+  @Inject
+  ProducerFactoryGenerator(
+      Filer filer,
+      DaggerElements elements,
+      SourceVersion sourceVersion,
+      CompilerOptions compilerOptions,
+      KeyFactory keyFactory) {
+    super(filer, elements, sourceVersion);
+    this.compilerOptions = compilerOptions;
+    this.keyFactory = keyFactory;
+  }
+
+  @Override
+  ClassName nameGeneratedType(ProductionBinding binding) {
+    return generatedClassNameForBinding(binding);
+  }
+
+  @Override
+  Element originatingElement(ProductionBinding binding) {
+    // we only create factories for bindings that have a binding element
+    return binding.bindingElement().get();
+  }
+
+  @Override
+  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, ProductionBinding binding) {
+    // We don't want to write out resolved bindings -- we want to write out the generic version.
+    checkArgument(!binding.unresolved().isPresent());
+    checkArgument(binding.bindingElement().isPresent());
+
+    TypeName providedTypeName = TypeName.get(binding.contributedType());
+    TypeName futureTypeName = listenableFutureOf(providedTypeName);
+
+    TypeSpec.Builder factoryBuilder =
+        classBuilder(generatedTypeName)
+            .addAnnotation(
+                // TODO(beder): examine if we can remove this or prevent subtypes of Future from
+                // being produced
+                AnnotationSpec.builder(SuppressWarnings.class)
+                    .addMember("value", "$S", "FutureReturnValueIgnored")
+                    .build())
+            .addModifiers(PUBLIC, FINAL)
+            .addTypeVariables(bindingTypeElementTypeVariableNames(binding));
+
+    UniqueNameSet uniqueFieldNames = new UniqueNameSet();
+    ImmutableMap.Builder<Key, FieldSpec> fieldsBuilder = ImmutableMap.builder();
+
+    MethodSpec.Builder constructorBuilder = constructorBuilder().addModifiers(PRIVATE);
+
+    Optional<FieldSpec> moduleField =
+        binding.requiresModuleInstance()
+            ? Optional.of(
+                addFieldAndConstructorParameter(
+                    factoryBuilder,
+                    constructorBuilder,
+                    uniqueFieldNames.getUniqueName("module"),
+                    TypeName.get(binding.bindingTypeElement().get().asType())))
+            : Optional.empty();
+
+    String[] executorParameterName = new String[1];
+    String[] monitorParameterName = new String[1];
+    Map<Key, FrameworkField> bindingFieldsForDependencies =
+        generateBindingFieldsForDependencies(binding);
+    bindingFieldsForDependencies.forEach(
+        (key, bindingField) -> {
+          String fieldName = uniqueFieldNames.getUniqueName(bindingField.name());
+          if (key.equals(keyFactory.forProductionImplementationExecutor())) {
+            executorParameterName[0] = fieldName;
+            constructorBuilder.addParameter(bindingField.type(), executorParameterName[0]);
+          } else if (key.equals(keyFactory.forProductionComponentMonitor())) {
+            monitorParameterName[0] = fieldName;
+            constructorBuilder.addParameter(bindingField.type(), monitorParameterName[0]);
+          } else {
+            FieldSpec field =
+                addFieldAndConstructorParameter(
+                    factoryBuilder, constructorBuilder, fieldName, bindingField.type());
+            fieldsBuilder.put(key, field);
+          }
+        });
+    ImmutableMap<Key, FieldSpec> fields = fieldsBuilder.build();
+
+    constructorBuilder.addStatement(
+        "super($N, $L, $N)",
+        verifyNotNull(monitorParameterName[0]),
+        producerTokenConstruction(generatedTypeName, binding),
+        verifyNotNull(executorParameterName[0]));
+
+    if (binding.requiresModuleInstance()) {
+      assignField(constructorBuilder, moduleField.get(), null);
+    }
+
+    fields.forEach(
+        (key, field) -> {
+          ParameterizedTypeName type = bindingFieldsForDependencies.get(key).type();
+          assignField(constructorBuilder, field, type);
+        });
+
+    MethodSpec.Builder collectDependenciesBuilder =
+        methodBuilder("collectDependencies")
+            .addAnnotation(Override.class)
+            .addModifiers(PROTECTED);
+
+    ImmutableList<DependencyRequest> asyncDependencies = asyncDependencies(binding);
+    for (DependencyRequest dependency : asyncDependencies) {
+      TypeName futureType = listenableFutureOf(asyncDependencyType(dependency));
+      CodeBlock futureAccess = CodeBlock.of("$N.get()", fields.get(dependency.key()));
+      collectDependenciesBuilder.addStatement(
+          "$T $L = $L",
+          futureType,
+          dependencyFutureName(dependency),
+          dependency.kind().equals(RequestKind.PRODUCED)
+              ? CodeBlock.of("$T.createFutureProduced($L)", PRODUCERS, futureAccess)
+              : futureAccess);
+    }
+    FutureTransform futureTransform = FutureTransform.create(fields, binding, asyncDependencies);
+
+    collectDependenciesBuilder
+        .returns(listenableFutureOf(futureTransform.applyArgType()))
+        .addStatement("return $L", futureTransform.futureCodeBlock());
+
+    MethodSpec.Builder callProducesMethod =
+        methodBuilder("callProducesMethod")
+            .returns(futureTypeName)
+            .addAnnotation(Override.class)
+            .addModifiers(PUBLIC)
+            .addParameter(futureTransform.applyArgType(), futureTransform.applyArgName())
+            .addExceptions(getThrownTypeNames(binding.thrownTypes()))
+            .addCode(
+                getInvocationCodeBlock(
+                    binding, providedTypeName, futureTransform.parameterCodeBlocks()));
+    if (futureTransform.hasUncheckedCast()) {
+      callProducesMethod.addAnnotation(AnnotationSpecs.suppressWarnings(UNCHECKED));
+    }
+
+    MethodSpec constructor = constructorBuilder.build();
+    factoryBuilder
+        .superclass(
+            ParameterizedTypeName.get(
+                ClassName.get(AbstractProducesMethodProducer.class),
+                futureTransform.applyArgType(),
+                providedTypeName))
+        .addMethod(constructor)
+        .addMethod(staticFactoryMethod(binding, constructor))
+        .addMethod(collectDependenciesBuilder.build())
+        .addMethod(callProducesMethod.build());
+
+    gwtIncompatibleAnnotation(binding).ifPresent(factoryBuilder::addAnnotation);
+
+    // TODO(gak): write a sensible toString
+    return Optional.of(factoryBuilder);
+  }
+
+  private MethodSpec staticFactoryMethod(ProductionBinding binding, MethodSpec constructor) {
+    return MethodSpec.methodBuilder("create")
+        .addModifiers(PUBLIC, STATIC)
+        .returns(parameterizedGeneratedTypeNameForBinding(binding))
+        .addTypeVariables(bindingTypeElementTypeVariableNames(binding))
+        .addParameters(constructor.parameters)
+        .addStatement(
+            "return new $T($L)",
+            parameterizedGeneratedTypeNameForBinding(binding),
+            constructor.parameters.stream()
+                .map(p -> CodeBlock.of("$N", p.name))
+                .collect(toParametersCodeBlock()))
+        .build();
+  }
+
+  // TODO(ronshapiro): consolidate versions of these
+  private static FieldSpec addFieldAndConstructorParameter(
+      TypeSpec.Builder typeBuilder,
+      MethodSpec.Builder constructorBuilder,
+      String variableName,
+      TypeName variableType) {
+    FieldSpec field = FieldSpec.builder(variableType, variableName, PRIVATE, FINAL).build();
+    typeBuilder.addField(field);
+    constructorBuilder.addParameter(field.type, field.name);
+    return field;
+  }
+
+  private static void assignField(
+      MethodSpec.Builder constructorBuilder, FieldSpec field, ParameterizedTypeName type) {
+    if (type != null && type.rawType.equals(TypeNames.PRODUCER)) {
+      constructorBuilder.addStatement(
+          "this.$1N = $2T.nonCancellationPropagatingViewOf($1N)", field, Producers.class);
+    } else {
+      constructorBuilder.addStatement("this.$1N = $1N", field);
+    }
+  }
+
+  /** Returns a list of dependencies that are generated asynchronously. */
+  private static ImmutableList<DependencyRequest> asyncDependencies(Binding binding) {
+    final ImmutableMap<DependencyRequest, FrameworkDependency> frameworkDependencies =
+        binding.dependenciesToFrameworkDependenciesMap();
+    return FluentIterable.from(binding.dependencies())
+        .filter(
+            dependency ->
+                isAsyncDependency(dependency)
+                    && frameworkDependencies
+                        .get(dependency)
+                        .frameworkClass()
+                        .equals(Producer.class))
+        .toList();
+  }
+
+  private CodeBlock producerTokenConstruction(
+      ClassName generatedTypeName, ProductionBinding binding) {
+    CodeBlock producerTokenArgs =
+        compilerOptions.writeProducerNameInToken()
+            ? CodeBlock.of(
+                "$S",
+                String.format(
+                    "%s#%s",
+                    ClassName.get(binding.bindingTypeElement().get()),
+                    binding.bindingElement().get().getSimpleName()))
+            : CodeBlock.of("$T.class", generatedTypeName);
+    return CodeBlock.of("$T.create($L)", PRODUCER_TOKEN, producerTokenArgs);
+  }
+
+  /** Returns a name of the variable representing this dependency's future. */
+  private static String dependencyFutureName(DependencyRequest dependency) {
+    return dependency.requestElement().get().getSimpleName() + "Future";
+  }
+
+  /** Represents the transformation of an input future by a producer method. */
+  abstract static class FutureTransform {
+    protected final ImmutableMap<Key, FieldSpec> fields;
+    protected final ProductionBinding binding;
+
+    FutureTransform(ImmutableMap<Key, FieldSpec> fields, ProductionBinding binding) {
+      this.fields = fields;
+      this.binding = binding;
+    }
+
+    /** The code block representing the future that should be transformed. */
+    abstract CodeBlock futureCodeBlock();
+
+    /** The type of the argument to the apply method. */
+    abstract TypeName applyArgType();
+
+    /** The name of the argument to the apply method */
+    abstract String applyArgName();
+
+    /** The code blocks to be passed to the produces method itself. */
+    abstract ImmutableList<CodeBlock> parameterCodeBlocks();
+
+    /** Whether the transform method has an unchecked cast. */
+    boolean hasUncheckedCast() {
+      return false;
+    }
+
+    CodeBlock frameworkTypeUsageStatement(DependencyRequest dependency) {
+      return SourceFiles.frameworkTypeUsageStatement(
+          CodeBlock.of("$N", fields.get(dependency.key())), dependency.kind());
+    }
+
+    static FutureTransform create(
+        ImmutableMap<Key, FieldSpec> fields,
+        ProductionBinding binding,
+        ImmutableList<DependencyRequest> asyncDependencies) {
+      if (asyncDependencies.isEmpty()) {
+        return new NoArgFutureTransform(fields, binding);
+      } else if (asyncDependencies.size() == 1) {
+        return new SingleArgFutureTransform(
+            fields, binding, Iterables.getOnlyElement(asyncDependencies));
+      } else {
+        return new MultiArgFutureTransform(fields, binding, asyncDependencies);
+      }
+    }
+  }
+
+  static final class NoArgFutureTransform extends FutureTransform {
+    NoArgFutureTransform(ImmutableMap<Key, FieldSpec> fields, ProductionBinding binding) {
+      super(fields, binding);
+    }
+
+    @Override
+    CodeBlock futureCodeBlock() {
+      return CodeBlock.of("$T.<$T>immediateFuture(null)", FUTURES, VOID_CLASS);
+    }
+
+    @Override
+    TypeName applyArgType() {
+      return VOID_CLASS;
+    }
+
+    @Override
+    String applyArgName() {
+      return "ignoredVoidArg";
+    }
+
+    @Override
+    ImmutableList<CodeBlock> parameterCodeBlocks() {
+      return binding.explicitDependencies().stream()
+          .map(this::frameworkTypeUsageStatement)
+          .collect(toImmutableList());
+    }
+  }
+
+  static final class SingleArgFutureTransform extends FutureTransform {
+    private final DependencyRequest asyncDependency;
+
+    SingleArgFutureTransform(
+        ImmutableMap<Key, FieldSpec> fields,
+        ProductionBinding binding,
+        DependencyRequest asyncDependency) {
+      super(fields, binding);
+      this.asyncDependency = asyncDependency;
+    }
+
+    @Override
+    CodeBlock futureCodeBlock() {
+      return CodeBlock.of("$L", dependencyFutureName(asyncDependency));
+    }
+
+    @Override
+    TypeName applyArgType() {
+      return asyncDependencyType(asyncDependency);
+    }
+
+    @Override
+    String applyArgName() {
+      String argName = asyncDependency.requestElement().get().getSimpleName().toString();
+      if (argName.equals("module")) {
+        return "moduleArg";
+      }
+      return argName;
+    }
+
+    @Override
+    ImmutableList<CodeBlock> parameterCodeBlocks() {
+      ImmutableList.Builder<CodeBlock> parameterCodeBlocks = ImmutableList.builder();
+      for (DependencyRequest dependency : binding.explicitDependencies()) {
+        // We really want to compare instances here, because asyncDependency is an element in the
+        // set binding.dependencies().
+        if (dependency == asyncDependency) {
+          parameterCodeBlocks.add(CodeBlock.of("$L", applyArgName()));
+        } else {
+          parameterCodeBlocks.add(frameworkTypeUsageStatement(dependency));
+        }
+      }
+      return parameterCodeBlocks.build();
+    }
+  }
+
+  static final class MultiArgFutureTransform extends FutureTransform {
+    private final ImmutableList<DependencyRequest> asyncDependencies;
+
+    MultiArgFutureTransform(
+        ImmutableMap<Key, FieldSpec> fields,
+        ProductionBinding binding,
+        ImmutableList<DependencyRequest> asyncDependencies) {
+      super(fields, binding);
+      this.asyncDependencies = asyncDependencies;
+    }
+
+    @Override
+    CodeBlock futureCodeBlock() {
+      return CodeBlock.of(
+          "$T.<$T>allAsList($L)",
+          FUTURES,
+          OBJECT,
+          asyncDependencies
+              .stream()
+              .map(ProducerFactoryGenerator::dependencyFutureName)
+              .collect(joining(", ")));
+    }
+
+    @Override
+    TypeName applyArgType() {
+      return listOf(OBJECT);
+    }
+
+    @Override
+    String applyArgName() {
+      return "args";
+    }
+
+    @Override
+    ImmutableList<CodeBlock> parameterCodeBlocks() {
+      int argIndex = 0;
+      ImmutableList.Builder<CodeBlock> codeBlocks = ImmutableList.builder();
+      for (DependencyRequest dependency : binding.explicitDependencies()) {
+        if (isAsyncDependency(dependency)) {
+          codeBlocks.add(
+              CodeBlock.of(
+                  "($T) $L.get($L)", asyncDependencyType(dependency), applyArgName(), argIndex));
+          argIndex++;
+        } else {
+          codeBlocks.add(frameworkTypeUsageStatement(dependency));
+        }
+      }
+      return codeBlocks.build();
+    }
+
+    @Override
+    boolean hasUncheckedCast() {
+      return true;
+    }
+  }
+
+  private static boolean isAsyncDependency(DependencyRequest dependency) {
+    switch (dependency.kind()) {
+      case INSTANCE:
+      case PRODUCED:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  private static TypeName asyncDependencyType(DependencyRequest dependency) {
+    TypeName keyName = TypeName.get(dependency.key().type());
+    switch (dependency.kind()) {
+      case INSTANCE:
+        return keyName;
+      case PRODUCED:
+        return producedOf(keyName);
+      default:
+        throw new AssertionError();
+    }
+  }
+
+  /**
+   * Creates a code block for the invocation of the producer method from the module, which should be
+   * used entirely within a method body.
+   *
+   * @param binding The binding to generate the invocation code block for.
+   * @param providedTypeName The type name that should be provided by this producer.
+   * @param parameterCodeBlocks The code blocks for all the parameters to the producer method.
+   */
+  private CodeBlock getInvocationCodeBlock(
+      ProductionBinding binding,
+      TypeName providedTypeName,
+      ImmutableList<CodeBlock> parameterCodeBlocks) {
+    CodeBlock moduleCodeBlock =
+        CodeBlock.of(
+            "$L.$L($L)",
+            binding.requiresModuleInstance()
+                ? "module"
+                : CodeBlock.of("$T", ClassName.get(binding.bindingTypeElement().get())),
+            binding.bindingElement().get().getSimpleName(),
+            makeParametersCodeBlock(parameterCodeBlocks));
+
+    final CodeBlock returnCodeBlock;
+    switch (binding.productionKind().get()) {
+      case IMMEDIATE:
+        returnCodeBlock =
+            CodeBlock.of("$T.<$T>immediateFuture($L)", FUTURES, providedTypeName, moduleCodeBlock);
+        break;
+      case FUTURE:
+        returnCodeBlock = moduleCodeBlock;
+        break;
+      case SET_OF_FUTURE:
+        returnCodeBlock = CodeBlock.of("$T.allAsSet($L)", PRODUCERS, moduleCodeBlock);
+        break;
+      default:
+        throw new AssertionError();
+    }
+    return CodeBlock.of("return $L;", returnCodeBlock);
+  }
+
+  /**
+   * Converts the list of thrown types into type names.
+   *
+   * @param thrownTypes the list of thrown types.
+   */
+  private FluentIterable<? extends TypeName> getThrownTypeNames(
+      Iterable<? extends TypeMirror> thrownTypes) {
+    return FluentIterable.from(thrownTypes).transform(TypeName::get);
+  }
+}
diff --git a/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java b/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java
new file mode 100644
index 0000000..aca9756
--- /dev/null
+++ b/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java
@@ -0,0 +1,62 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.model.RequestKind;
+import dagger.producers.Producer;
+import java.util.Optional;
+
+/** An {@link Producer} creation expression for provision bindings. */
+final class ProducerFromProviderCreationExpression implements FrameworkInstanceCreationExpression {
+  private final ContributionBinding binding;
+  private final ComponentImplementation componentImplementation;
+  private final ComponentBindingExpressions componentBindingExpressions;
+
+  ProducerFromProviderCreationExpression(
+      ContributionBinding binding,
+      ComponentImplementation componentImplementation,
+      ComponentBindingExpressions componentBindingExpressions) {
+    this.binding = checkNotNull(binding);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    return FrameworkType.PROVIDER.to(
+        RequestKind.PRODUCER,
+        componentBindingExpressions
+            .getDependencyExpression(
+                bindingRequest(binding.key(), FrameworkType.PROVIDER),
+                componentImplementation.name())
+            .codeBlock());
+  }
+
+  @Override
+  public Optional<ClassName> alternativeFrameworkClass() {
+    return Optional.of(TypeNames.PRODUCER);
+  }
+
+  // TODO(ronshapiro): should this have a simple factory if the delegate expression is simple?
+}
diff --git a/java/dagger/internal/codegen/ProducerNodeInstanceBindingExpression.java b/java/dagger/internal/codegen/ProducerNodeInstanceBindingExpression.java
new file mode 100644
index 0000000..18818d5
--- /dev/null
+++ b/java/dagger/internal/codegen/ProducerNodeInstanceBindingExpression.java
@@ -0,0 +1,67 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+
+import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+
+/** Binding expression for producer node instances. */
+final class ProducerNodeInstanceBindingExpression extends FrameworkInstanceBindingExpression {
+  /** The component defining this binding. */
+  private final ComponentImplementation componentImplementation;
+  private final Key key;
+  private final ProducerEntryPointView producerEntryPointView;
+
+  ProducerNodeInstanceBindingExpression(
+      ResolvedBindings resolvedBindings,
+      FrameworkInstanceSupplier frameworkInstanceSupplier,
+      DaggerTypes types,
+      DaggerElements elements,
+      ComponentImplementation componentImplementation) {
+    super(resolvedBindings, frameworkInstanceSupplier, types, elements);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.key = resolvedBindings.key();
+    this.producerEntryPointView = new ProducerEntryPointView(types);
+  }
+
+  @Override
+  protected FrameworkType frameworkType() {
+    return FrameworkType.PRODUCER_NODE;
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    Expression result = super.getDependencyExpression(requestingClass);
+    componentImplementation.addCancellableProducerKey(key);
+    return result;
+  }
+
+  @Override
+  Expression getDependencyExpressionForComponentMethod(
+      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
+    return producerEntryPointView
+        .getProducerEntryPointField(this, componentMethod, component)
+        .orElseGet(
+            () -> super.getDependencyExpressionForComponentMethod(componentMethod, component));
+  }
+}
diff --git a/java/dagger/internal/codegen/ProducesMethodValidator.java b/java/dagger/internal/codegen/ProducesMethodValidator.java
new file mode 100644
index 0000000..bf45948
--- /dev/null
+++ b/java/dagger/internal/codegen/ProducesMethodValidator.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014 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.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.NO_SCOPING;
+import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_CONCRETE;
+import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.EXCEPTION;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.util.concurrent.ListenableFuture;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.multibindings.ElementsIntoSet;
+import dagger.producers.ProducerModule;
+import dagger.producers.Produces;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/** A validator for {@link Produces} methods. */
+final class ProducesMethodValidator extends BindingMethodValidator {
+
+  @Inject
+  ProducesMethodValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      DependencyRequestValidator dependencyRequestValidator) {
+    super(
+        elements,
+        types,
+        dependencyRequestValidator,
+        Produces.class,
+        ProducerModule.class,
+        MUST_BE_CONCRETE,
+        EXCEPTION,
+        ALLOWS_MULTIBINDINGS,
+        NO_SCOPING);
+  }
+
+  @Override
+  protected String elementsIntoSetNotASetMessage() {
+    return "@Produces methods of type set values must return a Set or ListenableFuture of Set";
+  }
+
+  @Override
+  protected String badTypeMessage() {
+    return "@Produces methods can return only a primitive, an array, a type variable, "
+        + "a declared type, or a ListenableFuture of one of those types";
+  }
+
+  @Override
+  protected ElementValidator elementValidator(ExecutableElement element) {
+    return new Validator(element);
+  }
+
+  private class Validator extends MethodValidator {
+    Validator(ExecutableElement element) {
+      super(element);
+    }
+
+    @Override
+    protected void checkAdditionalMethodProperties() {
+      checkNullable();
+    }
+
+    /** Adds a warning if a {@link Produces @Produces} method is declared nullable. */
+    // TODO(beder): Properly handle nullable with producer methods.
+    private void checkNullable() {
+      if (ConfigurationAnnotations.getNullableType(element).isPresent()) {
+        report.addWarning("@Nullable on @Produces methods does not do anything");
+      }
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>Allows {@code keyType} to be a {@link ListenableFuture} of an otherwise-valid key type.
+     */
+    @Override
+    protected void checkKeyType(TypeMirror keyType) {
+      Optional<TypeMirror> typeToCheck = unwrapListenableFuture(keyType);
+      if (typeToCheck.isPresent()) {
+        super.checkKeyType(typeToCheck.get());
+      }
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>Allows an {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} method to return
+     * a {@link ListenableFuture} of a {@link Set} as well.
+     */
+    @Override
+    protected void checkSetValuesType() {
+      Optional<TypeMirror> typeToCheck = unwrapListenableFuture(element.getReturnType());
+      if (typeToCheck.isPresent()) {
+        checkSetValuesType(typeToCheck.get());
+      }
+    }
+
+    private Optional<TypeMirror> unwrapListenableFuture(TypeMirror type) {
+      if (MoreTypes.isType(type) && MoreTypes.isTypeOf(ListenableFuture.class, type)) {
+        DeclaredType declaredType = MoreTypes.asDeclared(type);
+        if (declaredType.getTypeArguments().isEmpty()) {
+          report.addError("@Produces methods cannot return a raw ListenableFuture");
+          return Optional.empty();
+        } else {
+          return Optional.of((TypeMirror) getOnlyElement(declaredType.getTypeArguments()));
+        }
+      }
+      return Optional.of(type);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ProductionBinding.java b/java/dagger/internal/codegen/ProductionBinding.java
new file mode 100644
index 0000000..a22f21c
--- /dev/null
+++ b/java/dagger/internal/codegen/ProductionBinding.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2014 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 dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import java.util.Optional;
+import java.util.stream.Stream;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A value object representing the mechanism by which a {@link Key} can be produced.
+ */
+@AutoValue
+abstract class ProductionBinding extends ContributionBinding {
+
+  @Override
+  public BindingType bindingType() {
+    return BindingType.PRODUCTION;
+  }
+
+  @Override
+  abstract Optional<ProductionBinding> unresolved();
+
+  @Override
+  ImmutableSet<DependencyRequest> implicitDependencies() {
+    return Stream.of(executorRequest(), monitorRequest())
+        .filter(Optional::isPresent)
+        .map(Optional::get)
+        .collect(toImmutableSet());
+  }
+
+  /** What kind of object a {@code @Produces}-annotated method returns. */
+  enum ProductionKind {
+    /** A value. */
+    IMMEDIATE,
+    /** A {@code ListenableFuture<T>}. */
+    FUTURE,
+    /** A {@code Set<ListenableFuture<T>>}. */
+    SET_OF_FUTURE;
+
+    /** Returns the kind of object a {@code @Produces}-annotated method returns. */
+    static ProductionKind fromProducesMethod(ExecutableElement producesMethod) {
+      if (isFutureType(producesMethod.getReturnType())) {
+        return FUTURE;
+      } else if (ContributionType.fromBindingElement(producesMethod)
+              .equals(ContributionType.SET_VALUES)
+          && isFutureType(SetType.from(producesMethod.getReturnType()).elementType())) {
+        return SET_OF_FUTURE;
+      } else {
+        return IMMEDIATE;
+      }
+    }
+  }
+
+  /**
+   * Returns the kind of object the produces method returns. All production bindings from
+   * {@code @Produces} methods will have a production kind, but synthetic production bindings may
+   * not.
+   */
+  abstract Optional<ProductionKind> productionKind();
+
+  /** Returns the list of types in the throws clause of the method. */
+  abstract ImmutableList<? extends TypeMirror> thrownTypes();
+
+  /**
+   * If this production requires an executor, this will be the corresponding request.  All
+   * production bindings from {@code @Produces} methods will have an executor request, but
+   * synthetic production bindings may not.
+   */
+  abstract Optional<DependencyRequest> executorRequest();
+
+  /** If this production requires a monitor, this will be the corresponding request.  All
+   * production bindings from {@code @Produces} methods will have a monitor request, but synthetic
+   * production bindings may not.
+   */
+  abstract Optional<DependencyRequest> monitorRequest();
+
+  // Profiling determined that this method is called enough times that memoizing it had a measurable
+  // performance improvement for large components.
+  @Memoized
+  @Override
+  boolean requiresModuleInstance() {
+    return super.requiresModuleInstance();
+  }
+
+  static Builder builder() {
+    return new AutoValue_ProductionBinding.Builder()
+        .explicitDependencies(ImmutableList.<DependencyRequest>of())
+        .thrownTypes(ImmutableList.<TypeMirror>of());
+  }
+
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  // TODO(ronshapiro,dpb): simplify the equality semantics
+  @Override
+  public abstract boolean equals(Object obj);
+
+  @AutoValue.Builder
+  @CanIgnoreReturnValue
+  abstract static class Builder extends ContributionBinding.Builder<ProductionBinding, Builder> {
+
+    @Override
+    Builder dependencies(Iterable<DependencyRequest> dependencies) {
+      return explicitDependencies(dependencies);
+    }
+
+    abstract Builder explicitDependencies(Iterable<DependencyRequest> dependencies);
+
+    abstract Builder productionKind(ProductionKind productionKind);
+
+    @Override
+    abstract Builder unresolved(ProductionBinding unresolved);
+
+    abstract Builder thrownTypes(Iterable<? extends TypeMirror> thrownTypes);
+
+    abstract Builder executorRequest(DependencyRequest executorRequest);
+
+    abstract Builder monitorRequest(DependencyRequest monitorRequest);
+  }
+}
diff --git a/java/dagger/internal/codegen/ProviderInstanceBindingExpression.java b/java/dagger/internal/codegen/ProviderInstanceBindingExpression.java
new file mode 100644
index 0000000..60166de
--- /dev/null
+++ b/java/dagger/internal/codegen/ProviderInstanceBindingExpression.java
@@ -0,0 +1,41 @@
+/*
+ * 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 dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+
+/** Binding expression for provider instances. */
+final class ProviderInstanceBindingExpression extends FrameworkInstanceBindingExpression {
+
+  ProviderInstanceBindingExpression(
+      ResolvedBindings resolvedBindings,
+      FrameworkInstanceSupplier frameworkInstanceSupplier,
+      DaggerTypes types,
+      DaggerElements elements) {
+    super(
+        resolvedBindings,
+        frameworkInstanceSupplier,
+        types,
+        elements);
+  }
+
+  @Override
+  protected FrameworkType frameworkType() {
+    return FrameworkType.PROVIDER;
+  }
+}
diff --git a/java/dagger/internal/codegen/ProvidesMethodValidator.java b/java/dagger/internal/codegen/ProvidesMethodValidator.java
new file mode 100644
index 0000000..01e71ae
--- /dev/null
+++ b/java/dagger/internal/codegen/ProvidesMethodValidator.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 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 dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.ALLOWS_SCOPING;
+import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_CONCRETE;
+import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.RUNTIME_EXCEPTION;
+
+import com.google.common.collect.ImmutableSet;
+import dagger.Module;
+import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.producers.ProducerModule;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/** A validator for {@link Provides} methods. */
+final class ProvidesMethodValidator extends BindingMethodValidator {
+
+  private final DependencyRequestValidator dependencyRequestValidator;
+
+  @Inject
+  ProvidesMethodValidator(
+      DaggerElements elements,
+      DaggerTypes types,
+      DependencyRequestValidator dependencyRequestValidator) {
+    super(
+        elements,
+        types,
+        Provides.class,
+        ImmutableSet.of(Module.class, ProducerModule.class),
+        dependencyRequestValidator,
+        MUST_BE_CONCRETE,
+        RUNTIME_EXCEPTION,
+        ALLOWS_MULTIBINDINGS,
+        ALLOWS_SCOPING);
+    this.dependencyRequestValidator = dependencyRequestValidator;
+  }
+
+  @Override
+  protected ElementValidator elementValidator(ExecutableElement element) {
+    return new Validator(element);
+  }
+
+  private class Validator extends MethodValidator {
+    Validator(ExecutableElement element) {
+      super(element);
+    }
+
+    @Override
+    protected void checkAdditionalMethodProperties() {
+    }
+
+    /** Adds an error if a {@link Provides @Provides} method depends on a producer type. */
+    @Override
+    protected void checkParameter(VariableElement parameter) {
+      super.checkParameter(parameter);
+      dependencyRequestValidator.checkNotProducer(report, parameter);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ProvisionBinding.java b/java/dagger/internal/codegen/ProvisionBinding.java
new file mode 100644
index 0000000..306cb13
--- /dev/null
+++ b/java/dagger/internal/codegen/ProvisionBinding.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2014 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 dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.model.BindingKind.COMPONENT_PROVISION;
+import static dagger.model.BindingKind.PROVISION;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.model.BindingKind;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.Scope;
+import java.util.Optional;
+
+/**
+ * A value object representing the mechanism by which a {@link Key} can be provided.
+ */
+@AutoValue
+abstract class ProvisionBinding extends ContributionBinding {
+
+  @Override
+  @Memoized
+  ImmutableSet<DependencyRequest> explicitDependencies() {
+    return ImmutableSet.<DependencyRequest>builder()
+        .addAll(provisionDependencies())
+        .addAll(membersInjectionDependencies())
+        .build();
+  }
+
+  /**
+   * Dependencies necessary to invoke an {@code @Inject} constructor or {@code @Provides} method.
+   */
+  abstract ImmutableSet<DependencyRequest> provisionDependencies();
+
+  @Memoized
+  ImmutableSet<DependencyRequest> membersInjectionDependencies() {
+    return injectionSites()
+        .stream()
+        .flatMap(i -> i.dependencies().stream())
+        .collect(toImmutableSet());
+  }
+
+  /**
+   * {@link InjectionSite}s for all {@code @Inject} members if {@link #kind()} is {@link
+   * BindingKind#INJECTION}, otherwise empty.
+   */
+  abstract ImmutableSortedSet<InjectionSite> injectionSites();
+
+  @Override
+  public BindingType bindingType() {
+    return BindingType.PROVISION;
+  }
+
+  @Override
+  abstract Optional<ProvisionBinding> unresolved();
+
+  // TODO(ronshapiro): we should be able to remove this, but AutoValue barks on the Builder's scope
+  // method, saying that the method doesn't correspond to a property of ProvisionBinding
+  @Override
+  public abstract Optional<Scope> scope();
+
+  static Builder builder() {
+    return new AutoValue_ProvisionBinding.Builder()
+        .provisionDependencies(ImmutableSet.of())
+        .injectionSites(ImmutableSortedSet.of());
+  }
+
+  abstract Builder toBuilder();
+
+  private static final ImmutableSet<BindingKind> KINDS_TO_CHECK_FOR_NULL =
+      ImmutableSet.of(PROVISION, COMPONENT_PROVISION);
+
+  boolean shouldCheckForNull(CompilerOptions compilerOptions) {
+    return KINDS_TO_CHECK_FOR_NULL.contains(kind())
+        && !contributedPrimitiveType().isPresent()
+        && !nullableType().isPresent()
+        && compilerOptions.doCheckForNulls();
+  }
+
+  // Profiling determined that this method is called enough times that memoizing it had a measurable
+  // performance improvement for large components.
+  @Memoized
+  @Override
+  boolean requiresModuleInstance() {
+    return super.requiresModuleInstance();
+  }
+
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  // TODO(ronshapiro,dpb): simplify the equality semantics
+  @Override
+  public abstract boolean equals(Object obj);
+
+  @AutoValue.Builder
+  @CanIgnoreReturnValue
+  abstract static class Builder extends ContributionBinding.Builder<ProvisionBinding, Builder> {
+
+    @Override
+    Builder dependencies(Iterable<DependencyRequest> dependencies) {
+      return provisionDependencies(dependencies);
+    }
+
+    abstract Builder provisionDependencies(Iterable<DependencyRequest> provisionDependencies);
+
+    abstract Builder injectionSites(ImmutableSortedSet<InjectionSite> injectionSites);
+
+    @Override
+    abstract Builder unresolved(ProvisionBinding unresolved);
+
+    abstract Builder scope(Optional<Scope> scope);
+  }
+
+}
diff --git a/java/dagger/internal/codegen/ProvisionDependencyOnProducerBindingValidator.java b/java/dagger/internal/codegen/ProvisionDependencyOnProducerBindingValidator.java
new file mode 100644
index 0000000..2fb1a0e
--- /dev/null
+++ b/java/dagger/internal/codegen/ProvisionDependencyOnProducerBindingValidator.java
@@ -0,0 +1,115 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Verify.verify;
+import static dagger.internal.codegen.DaggerStreams.instancesOf;
+import static dagger.internal.codegen.RequestKinds.canBeSatisfiedByProductionBinding;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import dagger.model.BindingGraph;
+import dagger.model.BindingGraph.DependencyEdge;
+import dagger.model.BindingGraph.Node;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import java.util.stream.Stream;
+import javax.inject.Inject;
+
+/**
+ * Reports an error for each provision-only dependency request that is satisfied by a production
+ * binding.
+ */
+// TODO(b/29509141): Clarify the error.
+final class ProvisionDependencyOnProducerBindingValidator implements BindingGraphPlugin {
+
+  @Inject
+  ProvisionDependencyOnProducerBindingValidator() {}
+
+  @Override
+  public String pluginName() {
+    return "Dagger/ProviderDependsOnProducer";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    provisionDependenciesOnProductionBindings(bindingGraph)
+        .forEach(
+            provisionDependent ->
+                diagnosticReporter.reportDependency(
+                    ERROR,
+                    provisionDependent,
+                    provisionDependent.isEntryPoint()
+                        ? entryPointErrorMessage(provisionDependent)
+                        : dependencyErrorMessage(provisionDependent, bindingGraph)));
+  }
+
+  private Stream<DependencyEdge> provisionDependenciesOnProductionBindings(
+      BindingGraph bindingGraph) {
+    return bindingGraph.bindings().stream()
+        .filter(binding -> binding.isProduction())
+        .flatMap(binding -> incomingDependencies(binding, bindingGraph))
+        .filter(edge -> !dependencyCanUseProduction(edge, bindingGraph));
+  }
+
+  /** Returns the dependencies on {@code binding}. */
+  // TODO(dpb): Move to BindingGraph.
+  private Stream<DependencyEdge> incomingDependencies(
+      dagger.model.Binding binding, BindingGraph bindingGraph) {
+    return bindingGraph.network().inEdges(binding).stream()
+        .flatMap(instancesOf(DependencyEdge.class));
+  }
+
+  // TODO(ronshapiro): merge with MissingBindingValidator.dependencyCanUseProduction
+  private boolean dependencyCanUseProduction(DependencyEdge edge, BindingGraph bindingGraph) {
+    return edge.isEntryPoint()
+        ? canBeSatisfiedByProductionBinding(edge.dependencyRequest().kind())
+        : bindingRequestingDependency(edge, bindingGraph).isProduction();
+  }
+
+  /**
+   * Returns the binding that requests a dependency.
+   *
+   * @throws IllegalArgumentException if {@code dependency} is an {@linkplain
+   *     DependencyEdge#isEntryPoint() entry point}.
+   */
+  // TODO(dpb): Move to BindingGraph.
+  private dagger.model.Binding bindingRequestingDependency(
+      DependencyEdge dependency, BindingGraph bindingGraph) {
+    checkArgument(!dependency.isEntryPoint());
+    Node source = bindingGraph.network().incidentNodes(dependency).source();
+    verify(
+        source instanceof dagger.model.Binding,
+        "expected source of %s to be a binding, but was: %s",
+        dependency,
+        source);
+    return (dagger.model.Binding) source;
+  }
+
+  private String entryPointErrorMessage(DependencyEdge entryPoint) {
+    return String.format(
+        "%s is a provision entry-point, which cannot depend on a production.",
+        entryPoint.dependencyRequest().key());
+  }
+
+  private String dependencyErrorMessage(
+      DependencyEdge dependencyOnProduction, BindingGraph bindingGraph) {
+    return String.format(
+        "%s is a provision, which cannot depend on a production.",
+        bindingRequestingDependency(dependencyOnProduction, bindingGraph).key());
+  }
+}
diff --git a/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java b/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java
new file mode 100644
index 0000000..6eb92ac
--- /dev/null
+++ b/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java
@@ -0,0 +1,79 @@
+/*
+ * 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.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.MissingBindingFactory;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.producers.internal.MissingBindingProducer;
+import java.util.Optional;
+
+/**
+ * A {@link BindingExpression} that implements a method that encapsulates a binding that is not part
+ * of the binding graph when generating a final concrete implementation of a subcomponent. The
+ * implementation throws an exception. It is assumed that a binding may remain missing in a valid
+ * binding graph, because it's possible for there to be dependencies that are passively pruned when
+ * a non-leaf binding is re-defined (such as when {@code @Provides} bindings override
+ * {@code @Inject} bindings).
+ *
+ * <p>This method should never be invoked. If it is the exception indicates an issue within Dagger
+ * itself.
+ */
+final class PrunedConcreteMethodBindingExpression extends BindingExpression {
+  private static final CodeBlock METHOD_IMPLEMENTATION =
+      CodeBlock.of(
+          "throw new $T($S);",
+          UnsupportedOperationException.class,
+          "This binding is not part of the final binding graph. The key was requested by a binding "
+              + "that was believed to possibly be part of the graph, but is no longer requested. "
+              + "If this exception is thrown, it is the result of a Dagger bug.");
+
+  PrunedConcreteMethodBindingExpression() {}
+
+  @Override
+  CodeBlock getModifiableBindingMethodImplementation(
+      ModifiableBindingMethod modifiableBindingMethod,
+      ComponentImplementation component,
+      DaggerTypes types) {
+    Optional<FrameworkType> frameworkType = modifiableBindingMethod.request().frameworkType();
+    if (frameworkType.isPresent()) {
+      // If we make initializations replaceable, we can do away with these classes and this logic
+      // since the pruned framework instances will no longer be initialized
+      switch (frameworkType.get()) {
+        case PROVIDER:
+          return missingFrameworkInstance(MissingBindingFactory.class);
+        case PRODUCER_NODE:
+          return missingFrameworkInstance(MissingBindingProducer.class);
+      }
+      throw new AssertionError(frameworkType);
+    }
+    return METHOD_IMPLEMENTATION;
+  }
+
+  private static CodeBlock missingFrameworkInstance(Class<?> factoryClass) {
+    return CodeBlock.builder().addStatement("return $T.create()", factoryClass).build();
+  }
+
+  @Override
+  final Expression getDependencyExpression(ClassName requestingClass) {
+    throw new UnsupportedOperationException(
+        "Requesting a dependency expression for a pruned binding.");
+  }
+}
diff --git a/java/dagger/internal/codegen/RequestKinds.java b/java/dagger/internal/codegen/RequestKinds.java
new file mode 100644
index 0000000..aa17f5e
--- /dev/null
+++ b/java/dagger/internal/codegen/RequestKinds.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2014 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.isType;
+import static com.google.auto.common.MoreTypes.isTypeOf;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.javapoet.TypeNames.lazyOf;
+import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.javapoet.TypeNames.producedOf;
+import static dagger.internal.codegen.javapoet.TypeNames.producerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static dagger.internal.codegen.langmodel.DaggerTypes.checkTypePresent;
+import static dagger.model.RequestKind.INSTANCE;
+import static dagger.model.RequestKind.LAZY;
+import static dagger.model.RequestKind.PRODUCED;
+import static dagger.model.RequestKind.PRODUCER;
+import static dagger.model.RequestKind.PROVIDER;
+import static dagger.model.RequestKind.PROVIDER_OF_LAZY;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.squareup.javapoet.TypeName;
+import dagger.Lazy;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.RequestKind;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import javax.inject.Provider;
+import javax.lang.model.type.TypeMirror;
+
+/** Utility methods for {@link RequestKind}s. */
+final class RequestKinds {
+  /** Returns the type of a request of this kind for a key with a given type. */
+  static TypeMirror requestType(RequestKind requestKind, TypeMirror type, DaggerTypes types) {
+    switch (requestKind) {
+      case INSTANCE:
+        return type;
+
+      case PROVIDER_OF_LAZY:
+        return types.wrapType(requestType(LAZY, type, types), Provider.class);
+
+      case FUTURE:
+        return types.wrapType(type, ListenableFuture.class);
+
+      default:
+        return types.wrapType(type, frameworkClass(requestKind));
+    }
+  }
+
+  /** Returns the type of a request of this kind for a key with a given type. */
+  static TypeName requestTypeName(RequestKind requestKind, TypeName keyType) {
+    switch (requestKind) {
+      case INSTANCE:
+        return keyType;
+
+      case PROVIDER:
+        return providerOf(keyType);
+
+      case LAZY:
+        return lazyOf(keyType);
+
+      case PROVIDER_OF_LAZY:
+        return providerOf(lazyOf(keyType));
+
+      case PRODUCER:
+        return producerOf(keyType);
+
+      case PRODUCED:
+        return producedOf(keyType);
+
+      case FUTURE:
+        return listenableFutureOf(keyType);
+
+      default:
+        throw new AssertionError(requestKind);
+    }
+  }
+
+  private static final ImmutableMap<RequestKind, Class<?>> FRAMEWORK_CLASSES =
+      ImmutableMap.of(
+          PROVIDER, Provider.class,
+          LAZY, Lazy.class,
+          PRODUCER, Producer.class,
+          PRODUCED, Produced.class);
+
+  /** Returns the {@link RequestKind} that matches the wrapping types (if any) of {@code type}. */
+  static RequestKind getRequestKind(TypeMirror type) {
+    checkTypePresent(type);
+    for (RequestKind kind : FRAMEWORK_CLASSES.keySet()) {
+      if (matchesKind(kind, type)) {
+        if (kind.equals(PROVIDER) && matchesKind(LAZY, extractKeyType(kind, type))) {
+          return PROVIDER_OF_LAZY;
+        }
+        return kind;
+      }
+    }
+    return INSTANCE;
+  }
+
+  /**
+   * Returns {@code true} if {@code type} is a parameterized type of {@code kind}'s {@link
+   * #frameworkClass(RequestKind) framework class}.
+   */
+  private static boolean matchesKind(RequestKind kind, TypeMirror type) {
+    return isType(type)
+        && isTypeOf(frameworkClass(kind), type)
+        && !asDeclared(type).getTypeArguments().isEmpty();
+  }
+
+  /**
+   * Unwraps the framework class(es) of {@code requestKind} from {@code type}. If {@code
+   * requestKind} is {@link RequestKind#INSTANCE}, this acts as an identity function.
+   *
+   * @throws TypeNotPresentException if {@code type} is an {@link javax.lang.model.type.ErrorType},
+   *     which may mean that the type will be generated in a later round of processing
+   * @throws IllegalArgumentException if {@code type} is not wrapped with {@code requestKind}'s
+   *     framework class(es).
+   */
+  static TypeMirror extractKeyType(RequestKind requestKind, TypeMirror type) {
+    checkTypePresent(type);
+    switch (requestKind) {
+      case INSTANCE:
+        return type;
+      case PROVIDER_OF_LAZY:
+        return extractKeyType(LAZY, extractKeyType(PROVIDER, type));
+      default:
+        checkArgument(isType(type) && isTypeOf(frameworkClass(requestKind), type));
+        return getOnlyElement(MoreTypes.asDeclared(type).getTypeArguments());
+    }
+  }
+
+  /**
+   * A dagger- or {@code javax.inject}-defined class for {@code requestKind} that that can wrap
+   * another type but share the same {@link dagger.model.Key}.
+   *
+   * <p>For example, {@code Provider<String>} and {@code Lazy<String>} can both be requested if a
+   * key exists for {@code String}; they all share the same key.
+   *
+   * <p>This concept is not well defined and should probably be removed and inlined into the cases
+   * that need it. For example, {@link RequestKind#PROVIDER_OF_LAZY} has <em>2</em> wrapping
+   * classes, and {@link RequestKind#FUTURE} is wrapped with a {@link ListenableFuture}, but for
+   * historical/implementation reasons has not had an associated framework class.
+   */
+  static Class<?> frameworkClass(RequestKind requestKind) {
+    Class<?> result = FRAMEWORK_CLASSES.get(requestKind);
+    checkArgument(result != null, "no framework class for %s", requestKind);
+    return result;
+  }
+
+  /**
+   * Returns {@code true} if requests for {@code requestKind} can be satisfied by a production
+   * binding.
+   */
+  static boolean canBeSatisfiedByProductionBinding(RequestKind requestKind) {
+    switch (requestKind) {
+      case INSTANCE:
+      case PROVIDER:
+      case LAZY:
+      case PROVIDER_OF_LAZY:
+      case MEMBERS_INJECTION:
+        return false;
+      case PRODUCER:
+      case PRODUCED:
+      case FUTURE:
+        return true;
+    }
+    throw new AssertionError();
+  }
+
+  /**
+   * Returns true if {@code requestKind} is always derived from a {@link RequestKind#PROVIDER}
+   * instance.
+   */
+  static boolean isDerivedFromProvider(RequestKind requestKind) {
+    switch (requestKind) {
+      case LAZY:
+      case PROVIDER_OF_LAZY:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  private RequestKinds() {}
+}
diff --git a/java/dagger/internal/codegen/ResolvedBindings.java b/java/dagger/internal/codegen/ResolvedBindings.java
new file mode 100644
index 0000000..814995a
--- /dev/null
+++ b/java/dagger/internal/codegen/ResolvedBindings.java
@@ -0,0 +1,264 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import dagger.internal.codegen.ContributionType.HasContributionType;
+import dagger.model.Key;
+import dagger.model.Scope;
+import java.util.Optional;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * The collection of bindings that have been resolved for a key. For valid graphs, contains exactly
+ * one binding.
+ *
+ * <p>Separate {@link ResolvedBindings} instances should be used if a {@link
+ * MembersInjectionBinding} and a {@link ProvisionBinding} for the same key exist in the same
+ * component. (This will only happen if a type has an {@code @Inject} constructor and members, the
+ * component has a members injection method, and the type is also requested normally.)
+ */
+@AutoValue
+abstract class ResolvedBindings implements HasContributionType {
+  /**
+   * The binding key for which the {@link #bindings()} have been resolved.
+   */
+  abstract Key key();
+
+  /**
+   * The {@link ContributionBinding}s for {@link #key()} indexed by the component that owns the
+   * binding. Each key in the multimap is a part of the same component ancestry.
+   */
+  abstract ImmutableSetMultimap<TypeElement, ContributionBinding> allContributionBindings();
+
+  /**
+   * The {@link MembersInjectionBinding}s for {@link #key()} indexed by the component that owns the
+   * binding.  Each key in the map is a part of the same component ancestry.
+   */
+  abstract ImmutableMap<TypeElement, MembersInjectionBinding> allMembersInjectionBindings();
+
+  /** The multibinding declarations for {@link #key()}. */
+  abstract ImmutableSet<MultibindingDeclaration> multibindingDeclarations();
+
+  /** The subcomponent declarations for {@link #key()}. */
+  abstract ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations();
+
+  /**
+   * The optional binding declarations for {@link #key()}.
+   */
+  abstract ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations();
+
+  // Computing the hash code is an expensive operation.
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  // Suppresses ErrorProne warning that hashCode was overridden w/o equals
+  @Override
+  public abstract boolean equals(Object other);
+
+  /** All bindings for {@link #key()}, indexed by the component that owns the binding. */
+  final ImmutableSetMultimap<TypeElement, ? extends Binding> allBindings() {
+    return !allMembersInjectionBindings().isEmpty()
+        ? allMembersInjectionBindings().asMultimap()
+        : allContributionBindings();
+  }
+
+  /** All bindings for {@link #key()}, regardless of which component owns them. */
+  final ImmutableCollection<? extends Binding> bindings() {
+    return allBindings().values();
+  }
+
+  /**
+   * Returns the single binding.
+   *
+   * @throws IllegalStateException if there is not exactly one element in {@link #bindings()}, which
+   *     will never happen for contributions in valid graphs
+   */
+  final Binding binding() {
+    return getOnlyElement(bindings());
+  }
+
+  /**
+   * {@code true} if there are no {@link #bindings()}, {@link #multibindingDeclarations()}, {@link
+   * #optionalBindingDeclarations()}, or {@link #subcomponentDeclarations()}.
+   */
+  final boolean isEmpty() {
+    return allMembersInjectionBindings().isEmpty()
+        && allContributionBindings().isEmpty()
+        && multibindingDeclarations().isEmpty()
+        && optionalBindingDeclarations().isEmpty()
+        && subcomponentDeclarations().isEmpty();
+  }
+
+  /** All bindings for {@link #key()} that are owned by a component. */
+  ImmutableSet<? extends Binding> bindingsOwnedBy(ComponentDescriptor component) {
+    return allBindings().get(component.typeElement());
+  }
+
+  /**
+   * All contribution bindings, regardless of owning component. Empty if this is a members-injection
+   * binding.
+   */
+  @Memoized
+  ImmutableSet<ContributionBinding> contributionBindings() {
+    // TODO(ronshapiro): consider optimizing ImmutableSet.copyOf(Collection) for small immutable
+    // collections so that it doesn't need to call toArray(). Even though this method is memoized,
+    // toArray() can take ~150ms for large components, and there are surely other places in the
+    // processor that can benefit from this.
+    return ImmutableSet.copyOf(allContributionBindings().values());
+  }
+
+  /** The component that owns {@code binding}. */
+  final TypeElement owningComponent(ContributionBinding binding) {
+    checkArgument(
+        contributionBindings().contains(binding),
+        "binding is not resolved for %s: %s",
+        key(),
+        binding);
+    return getOnlyElement(allContributionBindings().inverse().get(binding));
+  }
+
+  /**
+   * The members-injection binding, regardless of owning component. Absent if these are contribution
+   * bindings, or if there is no members-injection binding because the type fails validation.
+   */
+  final Optional<MembersInjectionBinding> membersInjectionBinding() {
+    return allMembersInjectionBindings().isEmpty()
+        ? Optional.empty()
+        : Optional.of(Iterables.getOnlyElement(allMembersInjectionBindings().values()));
+  }
+
+  /** Creates a {@link ResolvedBindings} for contribution bindings. */
+  static ResolvedBindings forContributionBindings(
+      Key key,
+      Multimap<TypeElement, ContributionBinding> contributionBindings,
+      Iterable<MultibindingDeclaration> multibindings,
+      Iterable<SubcomponentDeclaration> subcomponentDeclarations,
+      Iterable<OptionalBindingDeclaration> optionalBindingDeclarations) {
+    return new AutoValue_ResolvedBindings(
+        key,
+        ImmutableSetMultimap.copyOf(contributionBindings),
+        ImmutableMap.of(),
+        ImmutableSet.copyOf(multibindings),
+        ImmutableSet.copyOf(subcomponentDeclarations),
+        ImmutableSet.copyOf(optionalBindingDeclarations));
+  }
+
+  /**
+   * Creates a {@link ResolvedBindings} for members injection bindings.
+   */
+  static ResolvedBindings forMembersInjectionBinding(
+      Key key,
+      ComponentDescriptor owningComponent,
+      MembersInjectionBinding ownedMembersInjectionBinding) {
+    return new AutoValue_ResolvedBindings(
+        key,
+        ImmutableSetMultimap.of(),
+        ImmutableMap.of(owningComponent.typeElement(), ownedMembersInjectionBinding),
+        ImmutableSet.of(),
+        ImmutableSet.of(),
+        ImmutableSet.of());
+  }
+
+  /**
+   * Creates a {@link ResolvedBindings} appropriate for when there are no bindings for the key.
+   */
+  static ResolvedBindings noBindings(Key key) {
+    return new AutoValue_ResolvedBindings(
+        key,
+        ImmutableSetMultimap.of(),
+        ImmutableMap.of(),
+        ImmutableSet.of(),
+        ImmutableSet.of(),
+        ImmutableSet.of());
+  }
+
+  /**
+   * {@code true} if this is a multibinding contribution.
+   */
+  boolean isMultibindingContribution() {
+    return contributionBindings().size() == 1
+        && contributionBinding().contributionType().isMultibinding();
+  }
+
+  /**
+   * Returns the single contribution binding.
+   *
+   * @throws IllegalStateException if there is not exactly one element in
+   *     {@link #contributionBindings()}, which will never happen for contributions in valid graphs
+   */
+  ContributionBinding contributionBinding() {
+    return getOnlyElement(contributionBindings());
+  }
+
+  /**
+   * The binding type for these bindings. If there are {@link #multibindingDeclarations()} or {@link
+   * #subcomponentDeclarations()} but no {@link #bindings()}, returns {@link BindingType#PROVISION}.
+   *
+   * @throws IllegalStateException if {@link #isEmpty()} or the binding types conflict
+   */
+  final BindingType bindingType() {
+    checkState(!isEmpty(), "empty bindings for %s", key());
+    if (allBindings().isEmpty()
+        && (!multibindingDeclarations().isEmpty() || !subcomponentDeclarations().isEmpty())) {
+      // Only multibinding declarations, so assume provision.
+      return BindingType.PROVISION;
+    }
+    ImmutableSet<BindingType> bindingTypes = bindingTypes();
+    checkState(bindingTypes.size() == 1, "conflicting binding types: %s", bindings());
+    return getOnlyElement(bindingTypes);
+  }
+
+  /** The binding types for {@link #bindings()}. */
+  @Memoized
+  ImmutableSet<BindingType> bindingTypes() {
+    return bindings().stream().map(Binding::bindingType).collect(toImmutableSet());
+  }
+
+  /**
+   * The contribution type for these bindings.
+   *
+   * @throws IllegalStateException if there is not exactly one element in {@link
+   *     #contributionBindings()}, which will never happen for contributions in valid graphs
+   */
+  @Override
+  public ContributionType contributionType() {
+    return contributionBinding().contributionType();
+  }
+
+  /**
+   * The scope associated with the single binding.
+   *
+   * @throws IllegalStateException if {@link #bindings()} does not have exactly one element
+   */
+  Optional<Scope> scope() {
+    return binding().scope();
+  }
+}
diff --git a/java/dagger/internal/codegen/Scopes.java b/java/dagger/internal/codegen/Scopes.java
new file mode 100644
index 0000000..252f712
--- /dev/null
+++ b/java/dagger/internal/codegen/Scopes.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 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.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.DiagnosticFormatting.stripCommonTypePrefixes;
+
+import com.google.auto.common.AnnotationMirrors;
+import com.google.common.collect.ImmutableSet;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.model.Scope;
+import dagger.producers.ProductionScope;
+import java.lang.annotation.Annotation;
+import java.util.Optional;
+import javax.inject.Singleton;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/** Common names and convenience methods for {@link Scope}s. */
+final class Scopes {
+  /**
+   * Creates a {@link Scope} object from the {@link javax.inject.Scope}-annotated annotation type.
+   */
+  static Scope scope(TypeElement scopeType) {
+    return Scope.scope(SimpleAnnotationMirror.of(scopeType));
+  }
+
+  /** Returns a representation for {@link ProductionScope @ProductionScope} scope. */
+  static Scope productionScope(DaggerElements elements) {
+    return scope(elements, ProductionScope.class);
+  }
+
+  /** Returns a representation for {@link Singleton @Singleton} scope. */
+  static Scope singletonScope(DaggerElements elements) {
+    return scope(elements, Singleton.class);
+  }
+
+  private static Scope scope(
+      DaggerElements elements, Class<? extends Annotation> scopeAnnotationClass) {
+    return scope(elements.getTypeElement(scopeAnnotationClass));
+  }
+
+  /**
+   * Returns at most one associated scoped annotation from the source code element, throwing an
+   * exception if there are more than one.
+   */
+  static Optional<Scope> uniqueScopeOf(Element element) {
+    // TODO(ronshapiro): Use MoreCollectors.toOptional() once we can use guava-jre
+    return Optional.ofNullable(getOnlyElement(scopesOf(element), null));
+  }
+
+  /**
+   * Returns the readable source representation (name with @ prefix) of the scope's annotation type.
+   *
+   * <p>It's readable source because it has had common package prefixes removed, e.g.
+   * {@code @javax.inject.Singleton} is returned as {@code @Singleton}.
+   */
+  static String getReadableSource(Scope scope) {
+    return stripCommonTypePrefixes(scope.toString());
+  }
+
+  /** Returns all of the associated scopes for a source code element. */
+  static ImmutableSet<Scope> scopesOf(Element element) {
+    return AnnotationMirrors.getAnnotatedAnnotations(element, javax.inject.Scope.class)
+        .stream()
+        .map(Scope::scope)
+        .collect(toImmutableSet());
+  }
+}
diff --git a/java/dagger/internal/codegen/SetBindingExpression.java b/java/dagger/internal/codegen/SetBindingExpression.java
new file mode 100644
index 0000000..5efb85f
--- /dev/null
+++ b/java/dagger/internal/codegen/SetBindingExpression.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2017 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.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.SetBuilder;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import java.util.Collections;
+import java.util.Optional;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/** A binding expression for multibound sets. */
+final class SetBindingExpression extends MultibindingExpression {
+  private final ProvisionBinding binding;
+  private final BindingGraph graph;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+
+  SetBindingExpression(
+      ResolvedBindings resolvedBindings,
+      ComponentImplementation componentImplementation,
+      BindingGraph graph,
+      ComponentBindingExpressions componentBindingExpressions,
+      DaggerTypes types,
+      DaggerElements elements) {
+    super(resolvedBindings, componentImplementation);
+    this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
+    this.graph = graph;
+    this.componentBindingExpressions = componentBindingExpressions;
+    this.types = types;
+    this.elements = elements;
+  }
+
+  @Override
+  protected Expression buildDependencyExpression(ClassName requestingClass) {
+    Optional<CodeBlock> superMethodCall = superMethodCall();
+    // TODO(ronshapiro): We should also make an ImmutableSet version of SetFactory
+    boolean isImmutableSetAvailable = isImmutableSetAvailable();
+    // TODO(ronshapiro, gak): Use Sets.immutableEnumSet() if it's available?
+    if (isImmutableSetAvailable
+        && binding.dependencies().stream().allMatch(this::isSingleValue)
+        && !superMethodCall.isPresent()) {
+      return Expression.create(
+          immutableSetType(),
+          CodeBlock.builder()
+              .add("$T.", ImmutableSet.class)
+              .add(maybeTypeParameter(requestingClass))
+              .add(
+                  "of($L)",
+                  binding
+                      .dependencies()
+                      .stream()
+                      .map(dependency -> getContributionExpression(dependency, requestingClass))
+                      .collect(toParametersCodeBlock()))
+              .build());
+    }
+    switch (binding.dependencies().size()) {
+      case 0:
+        return collectionsStaticFactoryInvocation(requestingClass, CodeBlock.of("emptySet()"));
+      case 1:
+        {
+          DependencyRequest dependency = getOnlyElement(binding.dependencies());
+          CodeBlock contributionExpression = getContributionExpression(dependency, requestingClass);
+          if (isSingleValue(dependency)) {
+            return collectionsStaticFactoryInvocation(
+                requestingClass, CodeBlock.of("singleton($L)", contributionExpression));
+          } else if (isImmutableSetAvailable) {
+            return Expression.create(
+                immutableSetType(),
+                CodeBlock.builder()
+                    .add("$T.", ImmutableSet.class)
+                    .add(maybeTypeParameter(requestingClass))
+                    .add("copyOf($L)", contributionExpression)
+                    .build());
+          }
+        }
+        // fall through
+      default:
+        CodeBlock.Builder instantiation = CodeBlock.builder();
+        instantiation
+            .add("$T.", isImmutableSetAvailable ? ImmutableSet.class : SetBuilder.class)
+            .add(maybeTypeParameter(requestingClass));
+        if (isImmutableSetBuilderWithExpectedSizeAvailable()) {
+          instantiation.add("builderWithExpectedSize($L)", binding.dependencies().size());
+        } else if (isImmutableSetAvailable) {
+          instantiation.add("builder()");
+        } else {
+          instantiation.add("newSetBuilder($L)", binding.dependencies().size());
+        }
+        for (DependencyRequest dependency : getNewContributions(binding.dependencies())) {
+          String builderMethod = isSingleValue(dependency) ? "add" : "addAll";
+          instantiation.add(
+              ".$L($L)", builderMethod, getContributionExpression(dependency, requestingClass));
+        }
+        if (superMethodCall.isPresent()) {
+          instantiation.add(CodeBlock.of(".addAll($L)", superMethodCall.get()));
+        }
+        instantiation.add(".build()");
+        return Expression.create(
+            isImmutableSetAvailable ? immutableSetType() : binding.key().type(),
+            instantiation.build());
+    }
+  }
+
+  private DeclaredType immutableSetType() {
+    return types.getDeclaredType(
+        elements.getTypeElement(ImmutableSet.class), SetType.from(binding.key()).elementType());
+  }
+
+  private CodeBlock getContributionExpression(
+      DependencyRequest dependency, ClassName requestingClass) {
+    return componentBindingExpressions
+        .getDependencyExpression(bindingRequest(dependency), requestingClass)
+        .codeBlock();
+  }
+
+  private Expression collectionsStaticFactoryInvocation(
+      ClassName requestingClass, CodeBlock methodInvocation) {
+    return Expression.create(
+        binding.key().type(),
+        CodeBlock.builder()
+            .add("$T.", Collections.class)
+            .add(maybeTypeParameter(requestingClass))
+            .add(methodInvocation)
+            .build());
+  }
+
+  private CodeBlock maybeTypeParameter(ClassName requestingClass) {
+    TypeMirror elementType = SetType.from(binding.key()).elementType();
+    return isTypeAccessibleFrom(elementType, requestingClass.packageName())
+        ? CodeBlock.of("<$T>", elementType)
+        : CodeBlock.of("");
+  }
+
+  private boolean isSingleValue(DependencyRequest dependency) {
+    return graph
+        .contributionBindings()
+        .get(dependency.key())
+        .contributionBinding()
+        .contributionType()
+        .equals(ContributionType.SET);
+  }
+
+  private boolean isImmutableSetBuilderWithExpectedSizeAvailable() {
+    if (isImmutableSetAvailable()) {
+      return methodsIn(elements.getTypeElement(ImmutableSet.class).getEnclosedElements())
+          .stream()
+          .anyMatch(method -> method.getSimpleName().contentEquals("builderWithExpectedSize"));
+    }
+    return false;
+  }
+
+  private boolean isImmutableSetAvailable() {
+    return elements.getTypeElement(ImmutableSet.class) != null;
+  }
+}
diff --git a/java/dagger/internal/codegen/SetFactoryCreationExpression.java b/java/dagger/internal/codegen/SetFactoryCreationExpression.java
new file mode 100644
index 0000000..9712091
--- /dev/null
+++ b/java/dagger/internal/codegen/SetFactoryCreationExpression.java
@@ -0,0 +1,103 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.SourceFiles.setFactoryClassName;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.model.DependencyRequest;
+import dagger.producers.Produced;
+import java.util.Optional;
+
+/** A factory creation expression for a multibound set. */
+final class SetFactoryCreationExpression extends MultibindingFactoryCreationExpression {
+
+  private final ComponentImplementation componentImplementation;
+  private final BindingGraph graph;
+  private final ContributionBinding binding;
+
+  SetFactoryCreationExpression(
+      ContributionBinding binding,
+      ComponentImplementation componentImplementation,
+      ComponentBindingExpressions componentBindingExpressions,
+      BindingGraph graph) {
+    super(binding, componentImplementation, componentBindingExpressions);
+    this.binding = checkNotNull(binding);
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.graph = checkNotNull(graph);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", setFactoryClassName(binding));
+    if (!useRawType()) {
+      SetType setType = SetType.from(binding.key());
+      builder.add(
+          "<$T>",
+          setType.elementsAreTypeOf(Produced.class)
+              ? setType.unwrappedElementType(Produced.class)
+              : setType.elementType());
+    }
+
+    int individualProviders = 0;
+    int setProviders = 0;
+    CodeBlock.Builder builderMethodCalls = CodeBlock.builder();
+    String methodNameSuffix =
+        binding.bindingType().equals(BindingType.PROVISION) ? "Provider" : "Producer";
+
+    Optional<CodeBlock> superContributions = superContributions();
+    if (superContributions.isPresent()) {
+      // TODO(b/117833324): consider decomposing the Provider<Set<Provider>> and adding the
+      // individual contributions separately from the collection contributions. Though this may
+      // actually not be doable/desirable if the super provider instance is a DelegateFactory or
+      // another internal type that is not SetFactory
+      builderMethodCalls.add(".addCollection$N($L)", methodNameSuffix, superContributions.get());
+      setProviders++;
+    }
+
+    for (DependencyRequest dependency : dependenciesToImplement()) {
+      ContributionType contributionType =
+          graph.contributionBindings().get(dependency.key()).contributionType();
+      String methodNamePrefix;
+      switch (contributionType) {
+        case SET:
+          individualProviders++;
+          methodNamePrefix = "add";
+          break;
+        case SET_VALUES:
+          setProviders++;
+          methodNamePrefix = "addCollection";
+          break;
+        default:
+          throw new AssertionError(dependency + " is not a set multibinding");
+      }
+
+      builderMethodCalls.add(
+          ".$N$N($L)",
+          methodNamePrefix,
+          methodNameSuffix,
+          multibindingDependencyExpression(dependency));
+    }
+    builder.add("builder($L, $L)", individualProviders, setProviders);
+    builder.add(builderMethodCalls.build());
+
+    componentImplementation.registerImplementedMultibinding(binding, bindingRequest());
+
+    return builder.add(".build()").build();
+  }
+}
diff --git a/java/dagger/internal/codegen/SetType.java b/java/dagger/internal/codegen/SetType.java
new file mode 100644
index 0000000..e4fa584
--- /dev/null
+++ b/java/dagger/internal/codegen/SetType.java
@@ -0,0 +1,120 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+
+import com.google.auto.common.MoreTypes;
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Equivalence;
+import dagger.model.Key;
+import java.util.Set;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Information about a {@link Set} {@link TypeMirror}.
+ */
+@AutoValue
+abstract class SetType {
+  /**
+   * The set type itself, wrapped using {@link MoreTypes#equivalence()}. Use
+   * {@link #declaredSetType()} instead.
+   */
+  protected abstract Equivalence.Wrapper<DeclaredType> wrappedDeclaredSetType();
+  
+  /**
+   * The set type itself.
+   */
+  DeclaredType declaredSetType() {
+    return wrappedDeclaredSetType().get();
+  }
+
+  /**
+   * {@code true} if the set type is the raw {@link Set} type.
+   */
+  boolean isRawType() {
+    return declaredSetType().getTypeArguments().isEmpty();
+  }
+
+  /**
+   * The element type.
+   */
+  TypeMirror elementType() {
+    return declaredSetType().getTypeArguments().get(0);
+  }
+
+  /**
+   * {@code true} if {@link #elementType()} is a {@code clazz}.
+   */
+  boolean elementsAreTypeOf(Class<?> clazz) {
+    return MoreTypes.isType(elementType()) && MoreTypes.isTypeOf(clazz, elementType());
+  }
+
+  /**
+   * {@code T} if {@link #elementType()} is a {@code WrappingClass<T>}.
+   *
+   * @throws IllegalStateException if {@link #elementType()} is not a {@code WrappingClass<T>}
+   * @throws IllegalArgumentException if {@code wrappingClass} does not have exactly one type
+   *     parameter
+   */
+  TypeMirror unwrappedElementType(Class<?> wrappingClass) {
+    checkArgument(
+        wrappingClass.getTypeParameters().length == 1,
+        "%s must have exactly one type parameter",
+        wrappingClass);
+    checkArgument(
+        elementsAreTypeOf(wrappingClass),
+        "expected elements to be %s, but this type is %s",
+        wrappingClass,
+        declaredSetType());
+    return MoreTypes.asDeclared(elementType()).getTypeArguments().get(0);
+  }
+
+  /**
+   * {@code true} if {@code type} is a {@link Set} type.
+   */
+  static boolean isSet(TypeMirror type) {
+    return MoreTypes.isType(type) && MoreTypes.isTypeOf(Set.class, type);
+  }
+
+  /**
+   * {@code true} if {@code key.type()} is a {@link Set} type.
+   */
+  static boolean isSet(Key key) {
+    return isSet(key.type());
+  }
+
+  /**
+   * Returns a {@link SetType} for {@code type}.
+   *
+   * @throws IllegalArgumentException if {@code type} is not a {@link Set} type
+   */
+  static SetType from(TypeMirror type) {
+    checkArgument(isSet(type), "%s must be a Set", type);
+    return new AutoValue_SetType(MoreTypes.equivalence().wrap(MoreTypes.asDeclared(type)));
+  }
+
+  /**
+   * Returns a {@link SetType} for {@code key}'s {@link Key#type() type}.
+   *
+   * @throws IllegalArgumentException if {@code key.type()} is not a {@link Set} type
+   */
+  static SetType from(Key key) {
+    return from (key.type());
+  }
+}
diff --git a/java/dagger/internal/codegen/SimpleAnnotationMirror.java b/java/dagger/internal/codegen/SimpleAnnotationMirror.java
new file mode 100644
index 0000000..505c8ea
--- /dev/null
+++ b/java/dagger/internal/codegen/SimpleAnnotationMirror.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkArgument;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.base.Functions;
+import com.google.common.base.Joiner;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+
+/** A representation of an annotation. */
+final class SimpleAnnotationMirror implements AnnotationMirror {
+  private final TypeElement annotationType;
+  private final ImmutableMap<String, ? extends AnnotationValue> namedValues;
+  private final ImmutableMap<ExecutableElement, ? extends AnnotationValue> elementValues;
+
+  private SimpleAnnotationMirror(
+      TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
+    checkArgument(
+        annotationType.getKind().equals(ElementKind.ANNOTATION_TYPE),
+        "annotationType must be an annotation: %s",
+        annotationType);
+    checkArgument(
+        FluentIterable.from(methodsIn(annotationType.getEnclosedElements()))
+            .transform(element -> element.getSimpleName().toString())
+            .toSet()
+            .equals(namedValues.keySet()),
+        "namedValues must have values for exactly the members in %s: %s",
+        annotationType,
+        namedValues);
+    this.annotationType = annotationType;
+    this.namedValues = ImmutableMap.copyOf(namedValues);
+    this.elementValues =
+        Maps.toMap(
+            methodsIn(annotationType.getEnclosedElements()),
+            Functions.compose(
+                Functions.forMap(namedValues), element -> element.getSimpleName().toString()));
+  }
+
+  @Override
+  public DeclaredType getAnnotationType() {
+    return MoreTypes.asDeclared(annotationType.asType());
+  }
+
+  @Override
+  public Map<ExecutableElement, ? extends AnnotationValue> getElementValues() {
+    return elementValues;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder("@").append(annotationType.getQualifiedName());
+    if (!namedValues.isEmpty()) {
+      builder
+          .append('(')
+          .append(Joiner.on(", ").withKeyValueSeparator(" = ").join(namedValues))
+          .append(')');
+    }
+    return builder.toString();
+  }
+
+  /**
+   * An object representing an annotation instance.
+   *
+   * @param annotationType must be an annotation type with no members
+   */
+  static AnnotationMirror of(TypeElement annotationType) {
+    return of(annotationType, ImmutableMap.<String, AnnotationValue>of());
+  }
+
+  /**
+   * An object representing an annotation instance.
+   *
+   * @param annotationType must be an annotation type
+   * @param namedValues a value for every annotation member, including those with defaults, indexed
+   *     by simple name
+   */
+  static AnnotationMirror of(
+      TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
+    return new SimpleAnnotationMirror(annotationType, namedValues);
+  }
+}
diff --git a/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java b/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java
new file mode 100644
index 0000000..909d7ae
--- /dev/null
+++ b/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 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.common.base.Preconditions.checkNotNull;
+
+/** A simple binding expression for instance requests. Does not scope. */
+abstract class SimpleInvocationBindingExpression extends BindingExpression {
+  // TODO(dpb): Take ContributionBinding instead of ResolvedBindings.
+  private final ResolvedBindings resolvedBindings;
+
+  SimpleInvocationBindingExpression(ResolvedBindings resolvedBindings) {
+    this.resolvedBindings = checkNotNull(resolvedBindings);
+  }
+
+  @Override
+  boolean requiresMethodEncapsulation() {
+    return !resolvedBindings.contributionBinding().dependencies().isEmpty();
+  }
+}
diff --git a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
new file mode 100644
index 0000000..805ac7b
--- /dev/null
+++ b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2016 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.MoreElements.asExecutable;
+import static com.google.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.InjectionMethods.ProvisionMethod.requiresInjectionMethod;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.InjectionMethods.ProvisionMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.DependencyRequest;
+import java.util.Optional;
+import java.util.function.Function;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A binding expression that invokes methods or constructors directly (without attempting to scope)
+ * {@link dagger.model.RequestKind#INSTANCE} requests.
+ */
+final class SimpleMethodBindingExpression extends SimpleInvocationBindingExpression {
+  private final CompilerOptions compilerOptions;
+  private final ProvisionBinding provisionBinding;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final MembersInjectionMethods membersInjectionMethods;
+  private final ComponentRequirementExpressions componentRequirementExpressions;
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+  private final SourceVersion sourceVersion;
+
+  SimpleMethodBindingExpression(
+      ResolvedBindings resolvedBindings,
+      CompilerOptions compilerOptions,
+      ComponentBindingExpressions componentBindingExpressions,
+      MembersInjectionMethods membersInjectionMethods,
+      ComponentRequirementExpressions componentRequirementExpressions,
+      DaggerTypes types,
+      DaggerElements elements,
+      SourceVersion sourceVersion) {
+    super(resolvedBindings);
+    this.compilerOptions = compilerOptions;
+    this.provisionBinding = (ProvisionBinding) resolvedBindings.contributionBinding();
+    checkArgument(
+        provisionBinding.implicitDependencies().isEmpty(),
+        "framework deps are not currently supported");
+    checkArgument(provisionBinding.bindingElement().isPresent());
+    this.componentBindingExpressions = componentBindingExpressions;
+    this.membersInjectionMethods = membersInjectionMethods;
+    this.componentRequirementExpressions = componentRequirementExpressions;
+    this.types = types;
+    this.elements = elements;
+    this.sourceVersion = sourceVersion;
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    ImmutableMap<DependencyRequest, Expression> arguments =
+        ImmutableMap.copyOf(
+            Maps.asMap(
+                provisionBinding.dependencies(),
+                request -> dependencyArgument(request, requestingClass)));
+    Function<DependencyRequest, CodeBlock> argumentsFunction =
+        request -> arguments.get(request).codeBlock();
+    return requiresInjectionMethod(
+            provisionBinding,
+            arguments.values().asList(),
+            compilerOptions,
+            requestingClass.packageName(),
+            types)
+        ? invokeInjectionMethod(argumentsFunction, requestingClass)
+        : invokeMethod(argumentsFunction, requestingClass);
+  }
+
+  private Expression invokeMethod(
+      Function<DependencyRequest, CodeBlock> argumentsFunction,
+      ClassName requestingClass) {
+    // TODO(dpb): align this with the contents of InlineMethods.create
+    CodeBlock arguments =
+        provisionBinding.dependencies().stream()
+            .map(argumentsFunction)
+            .collect(toParametersCodeBlock());
+    ExecutableElement method = asExecutable(provisionBinding.bindingElement().get());
+    CodeBlock invocation;
+    switch (method.getKind()) {
+      case CONSTRUCTOR:
+        invocation = CodeBlock.of("new $T($L)", constructorTypeName(requestingClass), arguments);
+        break;
+      case METHOD:
+        CodeBlock module =
+            moduleReference(requestingClass)
+                .orElse(CodeBlock.of("$T", provisionBinding.bindingTypeElement().get()));
+        invocation = CodeBlock.of("$L.$L($L)", module, method.getSimpleName(), arguments);
+        break;
+      default:
+        throw new IllegalStateException();
+    }
+
+    return Expression.create(simpleMethodReturnType(), invocation);
+  }
+
+  private TypeName constructorTypeName(ClassName requestingClass) {
+    DeclaredType type = MoreTypes.asDeclared(provisionBinding.key().type());
+    TypeName typeName = TypeName.get(type);
+    if (type.getTypeArguments()
+        .stream()
+        .allMatch(t -> isTypeAccessibleFrom(t, requestingClass.packageName()))) {
+      return typeName;
+    }
+    return rawTypeName(typeName);
+  }
+
+  private Expression invokeInjectionMethod(
+      Function<DependencyRequest, CodeBlock> argumentsFunction, ClassName requestingClass) {
+    return injectMembers(
+        ProvisionMethod.invoke(
+            provisionBinding,
+            argumentsFunction,
+            requestingClass,
+            moduleReference(requestingClass),
+            compilerOptions,
+            elements));
+  }
+
+  private Expression dependencyArgument(DependencyRequest dependency, ClassName requestingClass) {
+    return componentBindingExpressions.getDependencyArgumentExpression(dependency, requestingClass);
+  }
+
+  private Expression injectMembers(CodeBlock instance) {
+    if (provisionBinding.injectionSites().isEmpty()) {
+      return Expression.create(simpleMethodReturnType(), instance);
+    }
+    if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
+      // Java 7 type inference can't figure out that instance in
+      // injectParameterized(Parameterized_Factory.newParameterized()) is Parameterized<T> and not
+      // Parameterized<Object>
+      if (!MoreTypes.asDeclared(provisionBinding.key().type()).getTypeArguments().isEmpty()) {
+        TypeName keyType = TypeName.get(provisionBinding.key().type());
+        instance = CodeBlock.of("($T) ($T) $L", keyType, rawTypeName(keyType), instance);
+      }
+    }
+    MethodSpec membersInjectionMethod = membersInjectionMethods.getOrCreate(provisionBinding.key());
+    TypeMirror returnType =
+        membersInjectionMethod.returnType.equals(TypeName.OBJECT)
+            ? elements.getTypeElement(Object.class).asType()
+            : provisionBinding.key().type();
+    return Expression.create(returnType, CodeBlock.of("$N($L)", membersInjectionMethod, instance));
+  }
+
+  private Optional<CodeBlock> moduleReference(ClassName requestingClass) {
+    return provisionBinding.requiresModuleInstance()
+        ? provisionBinding
+            .contributingModule()
+            .map(Element::asType)
+            .map(ComponentRequirement::forModule)
+            .map(module -> componentRequirementExpressions.getExpression(module, requestingClass))
+        : Optional.empty();
+  }
+
+  private TypeMirror simpleMethodReturnType() {
+    return provisionBinding.contributedPrimitiveType().orElse(provisionBinding.key().type());
+  }
+}
diff --git a/java/dagger/internal/codegen/SimpleTypeAnnotationValue.java b/java/dagger/internal/codegen/SimpleTypeAnnotationValue.java
new file mode 100644
index 0000000..7f043db
--- /dev/null
+++ b/java/dagger/internal/codegen/SimpleTypeAnnotationValue.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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 javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.AnnotationValueVisitor;
+import javax.lang.model.type.TypeMirror;
+
+/** An {@link AnnotationValue} that contains a {@link TypeMirror}. */
+final class SimpleTypeAnnotationValue implements AnnotationValue {
+  private final TypeMirror value;
+
+  SimpleTypeAnnotationValue(TypeMirror value) {
+    this.value = value;
+  }
+
+  @Override
+  public TypeMirror getValue() {
+    return value;
+  }
+
+  @Override
+  public String toString() {
+    return value + ".class";
+  }
+
+  @Override
+  public <R, P> R accept(AnnotationValueVisitor<R, P> visitor, P parameter) {
+    return visitor.visitType(getValue(), parameter);
+  }
+}
diff --git a/java/dagger/internal/codegen/SourceFileGenerationException.java b/java/dagger/internal/codegen/SourceFileGenerationException.java
new file mode 100644
index 0000000..07c1c68
--- /dev/null
+++ b/java/dagger/internal/codegen/SourceFileGenerationException.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 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.common.base.Preconditions.checkNotNull;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.squareup.javapoet.ClassName;
+import java.util.Optional;
+import javax.annotation.processing.Messager;
+import javax.lang.model.element.Element;
+
+/**
+ * An exception thrown to indicate that a source file could not be generated.
+ *
+ * <p>This exception <b>should not</b> be used to report detectable, logical errors as it may mask
+ * other errors that might have been caught upon further processing. Use a {@link ValidationReport}
+ * for that.
+ */
+final class SourceFileGenerationException extends Exception {
+  private final Element associatedElement;
+
+  SourceFileGenerationException(
+      Optional<ClassName> generatedClassName, Throwable cause, Element associatedElement) {
+    super(createMessage(generatedClassName, cause.getMessage()), cause);
+    this.associatedElement = checkNotNull(associatedElement);
+  }
+
+  private static String createMessage(Optional<ClassName> generatedClassName, String message) {
+    return String.format("Could not generate %s: %s.",
+        generatedClassName.isPresent()
+            ? generatedClassName.get()
+            : "unknown file",
+        message);
+  }
+
+  void printMessageTo(Messager messager) {
+    messager.printMessage(ERROR, getMessage(), associatedElement);
+  }
+}
diff --git a/java/dagger/internal/codegen/SourceFileGenerator.java b/java/dagger/internal/codegen/SourceFileGenerator.java
new file mode 100644
index 0000000..7dddc2f
--- /dev/null
+++ b/java/dagger/internal/codegen/SourceFileGenerator.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014 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.GeneratedAnnotations.generatedAnnotation;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Throwables;
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.Optional;
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.Messager;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+
+/**
+ * A template class that provides a framework for properly handling IO while generating source files
+ * from an annotation processor.  Particularly, it makes a best effort to ensure that files that
+ * fail to write successfully are deleted.
+ *
+ * @param <T> The input type from which source is to be generated.
+ */
+abstract class SourceFileGenerator<T> {
+  private static final String GENERATED_COMMENTS = "https://dagger.dev";
+
+  private final Filer filer;
+  private final DaggerElements elements;
+  private final SourceVersion sourceVersion;
+
+  SourceFileGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
+    this.filer = checkNotNull(filer);
+    this.elements = checkNotNull(elements);
+    this.sourceVersion = checkNotNull(sourceVersion);
+  }
+
+  SourceFileGenerator(SourceFileGenerator<T> delegate) {
+    this(delegate.filer, delegate.elements, delegate.sourceVersion);
+  }
+
+  /**
+   * Generates a source file to be compiled for {@code T}. Writes any generation exception to {@code
+   * messager} and does not throw.
+   */
+  void generate(T input, Messager messager) {
+    try {
+      generate(input);
+    } catch (SourceFileGenerationException e) {
+      e.printMessageTo(messager);
+    }
+  }
+
+  /** Generates a source file to be compiled for {@code T}. */
+  void generate(T input) throws SourceFileGenerationException {
+    ClassName generatedTypeName = nameGeneratedType(input);
+    Optional<TypeSpec.Builder> type = write(generatedTypeName, input);
+    if (!type.isPresent()) {
+      return;
+    }
+    try {
+      buildJavaFile(generatedTypeName, input, type.get()).writeTo(filer);
+    } catch (Exception e) {
+      // if the code above threw a SFGE, use that
+      Throwables.propagateIfPossible(e, SourceFileGenerationException.class);
+      // otherwise, throw a new one
+      throw new SourceFileGenerationException(
+          Optional.empty(), e, originatingElement(input));
+    }
+  }
+
+  private JavaFile buildJavaFile(
+      ClassName generatedTypeName, T input, TypeSpec.Builder typeSpecBuilder) {
+    typeSpecBuilder.addOriginatingElement(originatingElement(input));
+    Optional<AnnotationSpec> generatedAnnotation =
+        generatedAnnotation(elements, sourceVersion)
+            .map(
+                annotation ->
+                    AnnotationSpec.builder(ClassName.get(annotation))
+                        .addMember("value", "$S", "dagger.internal.codegen.ComponentProcessor")
+                        .addMember("comments", "$S", GENERATED_COMMENTS)
+                        .build());
+    generatedAnnotation.ifPresent(typeSpecBuilder::addAnnotation);
+    JavaFile.Builder javaFileBuilder =
+        JavaFile.builder(generatedTypeName.packageName(), typeSpecBuilder.build())
+            .skipJavaLangImports(true);
+    if (!generatedAnnotation.isPresent()) {
+      javaFileBuilder.addFileComment("Generated by Dagger ($L).", GENERATED_COMMENTS);
+    }
+    return javaFileBuilder.build();
+  }
+
+  /**
+   * Implementations should return the {@link ClassName} for the top-level type to be generated.
+   */
+  abstract ClassName nameGeneratedType(T input);
+
+  /** Returns the originating element of the generating type. */
+  abstract Element originatingElement(T input);
+
+  /**
+   * Returns a {@link TypeSpec.Builder type} to be generated for {@code T}, or {@link
+   * Optional#empty()} if no file should be generated.
+   */
+  // TODO(ronshapiro): write() makes more sense in JavaWriter where all writers are mutable.
+  // consider renaming to something like typeBuilder() which conveys the mutability of the result
+  abstract Optional<TypeSpec.Builder> write(ClassName generatedTypeName, T input);
+}
diff --git a/java/dagger/internal/codegen/SourceFileGeneratorsModule.java b/java/dagger/internal/codegen/SourceFileGeneratorsModule.java
index 426afae..c32262a 100644
--- a/java/dagger/internal/codegen/SourceFileGeneratorsModule.java
+++ b/java/dagger/internal/codegen/SourceFileGeneratorsModule.java
@@ -18,49 +18,48 @@
 
 import dagger.Module;
 import dagger.Provides;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.MembersInjectionBinding;
-import dagger.internal.codegen.binding.ProductionBinding;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.writing.FactoryGenerator;
-import dagger.internal.codegen.writing.HjarSourceFileGenerator;
-import dagger.internal.codegen.writing.MembersInjectorGenerator;
-import dagger.internal.codegen.writing.ModuleGenerator;
-import dagger.internal.codegen.writing.ModuleProxies.ModuleConstructorProxyGenerator;
-import dagger.internal.codegen.writing.ProducerFactoryGenerator;
+import dagger.internal.codegen.SourceFileGeneratorsModule.ComponentModule;
+import dagger.internal.codegen.SourceFileGeneratorsModule.MembersInjectionModule;
+import dagger.internal.codegen.SourceFileGeneratorsModule.ProductionModule;
+import dagger.internal.codegen.SourceFileGeneratorsModule.ProvisionModule;
 import javax.lang.model.element.TypeElement;
 
-@Module
-abstract class SourceFileGeneratorsModule {
-
-  @Provides
-  static SourceFileGenerator<ProvisionBinding> factoryGenerator(
-      FactoryGenerator generator, CompilerOptions compilerOptions) {
-    return hjarWrapper(generator, compilerOptions);
+@Module(
+    includes = {
+      ProvisionModule.class,
+      ProductionModule.class,
+      MembersInjectionModule.class,
+      ComponentModule.class
+    })
+interface SourceFileGeneratorsModule {
+  @Module
+  abstract class GeneratorModule<T, G extends SourceFileGenerator<T>> {
+    @Provides
+    SourceFileGenerator<T> generator(G generator, CompilerOptions compilerOptions) {
+      return compilerOptions.headerCompilation()
+          ? HjarSourceFileGenerator.wrap(generator)
+          : generator;
+    }
   }
 
-  @Provides
-  static SourceFileGenerator<ProductionBinding> producerFactoryGenerator(
-      ProducerFactoryGenerator generator, CompilerOptions compilerOptions) {
-    return hjarWrapper(generator, compilerOptions);
-  }
+  @Module
+  class ProvisionModule extends GeneratorModule<ProvisionBinding, FactoryGenerator> {}
 
-  @Provides
-  static SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator(
-      MembersInjectorGenerator generator, CompilerOptions compilerOptions) {
-    return hjarWrapper(generator, compilerOptions);
-  }
+  @Module
+  class ProductionModule extends GeneratorModule<ProductionBinding, ProducerFactoryGenerator> {}
 
+  @Module
+  class MembersInjectionModule
+      extends GeneratorModule<MembersInjectionBinding, MembersInjectorGenerator> {}
+
+  @Module
+  class ComponentModule extends GeneratorModule<BindingGraph, ComponentGenerator> {}
+
+  // the abstract module is not available because we're using a qualifier
   @Provides
   @ModuleGenerator
-  static SourceFileGenerator<TypeElement> moduleConstructorProxyGenerator(
+  static SourceFileGenerator<TypeElement> generator(
       ModuleConstructorProxyGenerator generator, CompilerOptions compilerOptions) {
-    return hjarWrapper(generator, compilerOptions);
-  }
-
-  private static <T> SourceFileGenerator<T> hjarWrapper(
-      SourceFileGenerator<T> generator, CompilerOptions compilerOptions) {
     return compilerOptions.headerCompilation()
         ? HjarSourceFileGenerator.wrap(generator)
         : generator;
diff --git a/java/dagger/internal/codegen/SourceFiles.java b/java/dagger/internal/codegen/SourceFiles.java
new file mode 100644
index 0000000..fd93d0d
--- /dev/null
+++ b/java/dagger/internal/codegen/SourceFiles.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2014 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.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_CAMEL;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.Optionals.optionalComparator;
+import static dagger.internal.codegen.javapoet.TypeNames.DOUBLE_CHECK;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_OF_PRODUCED_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_OF_PRODUCER_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_PROVIDER_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER_OF_LAZY;
+import static dagger.internal.codegen.javapoet.TypeNames.SET_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.SET_OF_PRODUCED_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.SET_PRODUCER;
+import static dagger.model.BindingKind.INJECTION;
+import static dagger.model.BindingKind.MULTIBOUND_MAP;
+import static dagger.model.BindingKind.MULTIBOUND_SET;
+import static java.util.Comparator.comparing;
+import static javax.lang.model.SourceVersion.isName;
+
+import com.google.auto.common.MoreElements;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.SetFactory;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import dagger.producers.internal.SetOfProducedProducer;
+import dagger.producers.internal.SetProducer;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import javax.inject.Provider;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+
+/**
+ * Utilities for generating files.
+ */
+class SourceFiles {
+
+  private static final Joiner CLASS_FILE_NAME_JOINER = Joiner.on('_');
+
+  /**
+   * Sorts {@link DependencyRequest} instances in an order likely to reflect their logical
+   * importance.
+   */
+  static final Comparator<DependencyRequest> DEPENDENCY_ORDERING =
+      // put fields before parameters
+      comparing(
+              (DependencyRequest request) -> request.requestElement().map(Element::getKind),
+              optionalComparator())
+          // order by dependency kind
+          .thenComparing(DependencyRequest::kind)
+          // then sort by name
+          .thenComparing(
+              request ->
+                  request.requestElement().map(element -> element.getSimpleName().toString()),
+              optionalComparator());
+
+  /**
+   * Generates names and keys for the factory class fields needed to hold the framework classes for
+   * all of the dependencies of {@code binding}. It is responsible for choosing a name that
+   *
+   * <ul>
+   * <li>represents all of the dependency requests for this key
+   * <li>is <i>probably</i> associated with the type being bound
+   * <li>is unique within the class
+   * </ul>
+   *
+   * @param binding must be an unresolved binding (type parameters must match its type element's)
+   */
+  static ImmutableMap<Key, FrameworkField> generateBindingFieldsForDependencies(
+      Binding binding) {
+    checkArgument(!binding.unresolved().isPresent(), "binding must be unresolved: %s", binding);
+
+    ImmutableMap.Builder<Key, FrameworkField> bindingFields = ImmutableMap.builder();
+    for (Binding.DependencyAssociation dependencyAssociation : binding.dependencyAssociations()) {
+      FrameworkDependency frameworkDependency = dependencyAssociation.frameworkDependency();
+      bindingFields.put(
+          frameworkDependency.key(),
+          FrameworkField.create(
+              ClassName.get(frameworkDependency.frameworkClass()),
+              TypeName.get(frameworkDependency.key().type()),
+              fieldNameForDependency(dependencyAssociation.dependencyRequests())));
+    }
+    return bindingFields.build();
+  }
+
+  private static String fieldNameForDependency(ImmutableSet<DependencyRequest> dependencyRequests) {
+    // collect together all of the names that we would want to call the provider
+    ImmutableSet<String> dependencyNames =
+        dependencyRequests.stream().map(DependencyVariableNamer::name).collect(toImmutableSet());
+
+    if (dependencyNames.size() == 1) {
+      // if there's only one name, great! use it!
+      return Iterables.getOnlyElement(dependencyNames);
+    } else {
+      // in the event that a field is being used for a bunch of deps with different names,
+      // add all the names together with "And"s in the middle. E.g.: stringAndS
+      Iterator<String> namesIterator = dependencyNames.iterator();
+      String first = namesIterator.next();
+      StringBuilder compositeNameBuilder = new StringBuilder(first);
+      while (namesIterator.hasNext()) {
+        compositeNameBuilder
+            .append("And")
+            .append(CaseFormat.LOWER_CAMEL.to(UPPER_CAMEL, namesIterator.next()));
+      }
+      return compositeNameBuilder.toString();
+    }
+  }
+
+  static CodeBlock frameworkTypeUsageStatement(
+      CodeBlock frameworkTypeMemberSelect, RequestKind dependencyKind) {
+    switch (dependencyKind) {
+      case LAZY:
+        return CodeBlock.of("$T.lazy($L)", DOUBLE_CHECK, frameworkTypeMemberSelect);
+      case INSTANCE:
+      case FUTURE:
+        return CodeBlock.of("$L.get()", frameworkTypeMemberSelect);
+      case PROVIDER:
+      case PRODUCER:
+        return frameworkTypeMemberSelect;
+      case PROVIDER_OF_LAZY:
+        return CodeBlock.of("$T.create($L)", PROVIDER_OF_LAZY, frameworkTypeMemberSelect);
+      default: // including PRODUCED
+        throw new AssertionError(dependencyKind);
+    }
+  }
+
+  /**
+   * Returns a mapping of {@link DependencyRequest}s to {@link CodeBlock}s that {@linkplain
+   * #frameworkTypeUsageStatement(CodeBlock, RequestKind) use them}.
+   */
+  static ImmutableMap<DependencyRequest, CodeBlock> frameworkFieldUsages(
+      ImmutableSet<DependencyRequest> dependencies, ImmutableMap<Key, FieldSpec> fields) {
+    return Maps.toMap(
+        dependencies,
+        dep ->
+            frameworkTypeUsageStatement(CodeBlock.of("$N", fields.get(dep.key())), dep.kind()));
+  }
+
+  /**
+   * Returns the generated factory or members injector name for a binding.
+   */
+  static ClassName generatedClassNameForBinding(Binding binding) {
+    switch (binding.bindingType()) {
+      case PROVISION:
+      case PRODUCTION:
+        ContributionBinding contribution = (ContributionBinding) binding;
+        switch (contribution.kind()) {
+          case INJECTION:
+          case PROVISION:
+          case PRODUCTION:
+            return elementBasedClassName(
+                MoreElements.asExecutable(binding.bindingElement().get()), "Factory");
+
+          default:
+            throw new AssertionError();
+        }
+
+      case MEMBERS_INJECTION:
+        return membersInjectorNameForType(
+            ((MembersInjectionBinding) binding).membersInjectedType());
+    }
+    throw new AssertionError();
+  }
+
+  /**
+   * Calculates an appropriate {@link ClassName} for a generated class that is based on {@code
+   * element}, appending {@code suffix} at the end.
+   *
+   * <p>This will always return a {@linkplain ClassName#topLevelClassName() top level class name},
+   * even if {@code element}'s enclosing class is a nested type.
+   */
+  static ClassName elementBasedClassName(ExecutableElement element, String suffix) {
+    ClassName enclosingClassName =
+        ClassName.get(MoreElements.asType(element.getEnclosingElement()));
+    String methodName =
+        element.getKind().equals(ElementKind.CONSTRUCTOR)
+            ? ""
+            : LOWER_CAMEL.to(UPPER_CAMEL, element.getSimpleName().toString());
+    return ClassName.get(
+        enclosingClassName.packageName(),
+        classFileName(enclosingClassName) + "_" + methodName + suffix);
+  }
+
+  static TypeName parameterizedGeneratedTypeNameForBinding(Binding binding) {
+    ClassName className = generatedClassNameForBinding(binding);
+    ImmutableList<TypeVariableName> typeParameters = bindingTypeElementTypeVariableNames(binding);
+    return typeParameters.isEmpty()
+        ? className
+        : ParameterizedTypeName.get(className, Iterables.toArray(typeParameters, TypeName.class));
+  }
+
+  static ClassName membersInjectorNameForType(TypeElement typeElement) {
+    return siblingClassName(typeElement,  "_MembersInjector");
+  }
+
+  static String classFileName(ClassName className) {
+    return CLASS_FILE_NAME_JOINER.join(className.simpleNames());
+  }
+
+  static ClassName generatedMonitoringModuleName(
+      TypeElement componentElement) {
+    return siblingClassName(componentElement, "_MonitoringModule");
+  }
+
+  // TODO(ronshapiro): when JavaPoet migration is complete, replace the duplicated code
+  // which could use this.
+  private static ClassName siblingClassName(TypeElement typeElement, String suffix) {
+    ClassName className = ClassName.get(typeElement);
+    return className.topLevelClassName().peerClass(classFileName(className) + suffix);
+  }
+
+  /**
+   * The {@link java.util.Set} factory class name appropriate for set bindings.
+   *
+   * <ul>
+   * <li>{@link SetFactory} for provision bindings.
+   * <li>{@link SetProducer} for production bindings for {@code Set<T>}.
+   * <li>{@link SetOfProducedProducer} for production bindings for {@code Set<Produced<T>>}.
+   * </ul>
+   */
+  static ClassName setFactoryClassName(ContributionBinding binding) {
+    checkArgument(binding.kind().equals(MULTIBOUND_SET));
+    if (binding.bindingType().equals(BindingType.PROVISION)) {
+      return SET_FACTORY;
+    } else {
+      SetType setType = SetType.from(binding.key());
+      return setType.elementsAreTypeOf(Produced.class) ? SET_OF_PRODUCED_PRODUCER : SET_PRODUCER;
+    }
+  }
+
+  /** The {@link java.util.Map} factory class name appropriate for map bindings. */
+  static ClassName mapFactoryClassName(ContributionBinding binding) {
+    checkState(binding.kind().equals(MULTIBOUND_MAP), binding.kind());
+    MapType mapType = MapType.from(binding.key());
+    switch (binding.bindingType()) {
+      case PROVISION:
+        return mapType.valuesAreTypeOf(Provider.class) ? MAP_PROVIDER_FACTORY : MAP_FACTORY;
+      case PRODUCTION:
+        return mapType.valuesAreFrameworkType()
+            ? mapType.valuesAreTypeOf(Producer.class)
+                ? MAP_OF_PRODUCER_PRODUCER
+                : MAP_OF_PRODUCED_PRODUCER
+            : MAP_PRODUCER;
+      default:
+        throw new IllegalArgumentException(binding.bindingType().toString());
+    }
+  }
+
+  static ImmutableList<TypeVariableName> bindingTypeElementTypeVariableNames(Binding binding) {
+    if (binding instanceof ContributionBinding) {
+      ContributionBinding contributionBinding = (ContributionBinding) binding;
+      if (!contributionBinding.kind().equals(INJECTION)
+          && !contributionBinding.requiresModuleInstance()) {
+        return ImmutableList.of();
+      }
+    }
+    List<? extends TypeParameterElement> typeParameters =
+        binding.bindingTypeElement().get().getTypeParameters();
+    return typeParameters.stream().map(TypeVariableName::get).collect(toImmutableList());
+  }
+
+  /**
+   * Returns a name to be used for variables of the given {@linkplain TypeElement type}. Prefer
+   * semantically meaningful variable names, but if none can be derived, this will produce something
+   * readable.
+   */
+  // TODO(gak): maybe this should be a function of TypeMirrors instead of Elements?
+  static String simpleVariableName(TypeElement typeElement) {
+    String candidateName = UPPER_CAMEL.to(LOWER_CAMEL, typeElement.getSimpleName().toString());
+    String variableName = protectAgainstKeywords(candidateName);
+    verify(isName(variableName), "'%s' was expected to be a valid variable name");
+    return variableName;
+  }
+
+  static String protectAgainstKeywords(String candidateName) {
+    switch (candidateName) {
+      case "package":
+        return "pkg";
+      case "boolean":
+        return "b";
+      case "double":
+        return "d";
+      case "byte":
+        return "b";
+      case "int":
+        return "i";
+      case "short":
+        return "s";
+      case "char":
+        return "c";
+      case "void":
+        return "v";
+      case "class":
+        return "clazz";
+      case "float":
+        return "f";
+      case "long":
+        return "l";
+      default:
+        return SourceVersion.isKeyword(candidateName) ? candidateName + '_' : candidateName;
+    }
+  }
+
+  private SourceFiles() {}
+}
diff --git a/java/dagger/internal/codegen/SpiModule.java b/java/dagger/internal/codegen/SpiModule.java
index a4f537b..a8f13e1 100644
--- a/java/dagger/internal/codegen/SpiModule.java
+++ b/java/dagger/internal/codegen/SpiModule.java
@@ -24,7 +24,6 @@
 import com.google.common.collect.ImmutableSet;
 import dagger.Module;
 import dagger.Provides;
-import dagger.internal.codegen.validation.BindingGraphValidator;
 import dagger.spi.BindingGraphPlugin;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
@@ -41,21 +40,16 @@
   @Provides
   @Singleton
   static ImmutableSet<BindingGraphPlugin> externalPlugins(
-      @TestingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins,
-      @ProcessorClassLoader ClassLoader processorClassLoader) {
+      @TestingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins) {
     return testingPlugins.orElseGet(
         () ->
             ImmutableSet.copyOf(
-                ServiceLoader.load(BindingGraphPlugin.class, processorClassLoader)));
+                ServiceLoader.load(
+                    BindingGraphPlugin.class, BindingGraphValidator.class.getClassLoader())));
   }
 
   @Qualifier
   @Retention(RUNTIME)
   @Target({FIELD, PARAMETER, METHOD})
   @interface TestingPlugins {}
-
-  @Qualifier
-  @Retention(RUNTIME)
-  @Target({PARAMETER, METHOD})
-  @interface ProcessorClassLoader {}
 }
diff --git a/java/dagger/internal/codegen/SubcomponentCreatorBindingEdgeImpl.java b/java/dagger/internal/codegen/SubcomponentCreatorBindingEdgeImpl.java
new file mode 100644
index 0000000..c97024e
--- /dev/null
+++ b/java/dagger/internal/codegen/SubcomponentCreatorBindingEdgeImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.DaggerStreams.presentValues;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static java.util.stream.Collectors.joining;
+
+import com.google.common.collect.ImmutableSet;
+import dagger.model.BindingGraph.SubcomponentCreatorBindingEdge;
+import javax.lang.model.element.TypeElement;
+
+/** An implementation of {@link SubcomponentCreatorBindingEdge}. */
+final class SubcomponentCreatorBindingEdgeImpl implements SubcomponentCreatorBindingEdge {
+
+  private final ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations;
+
+  SubcomponentCreatorBindingEdgeImpl(
+      ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
+    this.subcomponentDeclarations = subcomponentDeclarations;
+  }
+
+  @Override
+  public ImmutableSet<TypeElement> declaringModules() {
+    return subcomponentDeclarations.stream()
+        .map(SubcomponentDeclaration::contributingModule)
+        .flatMap(presentValues())
+        .collect(toImmutableSet());
+  }
+
+  @Override
+  public String toString() {
+    return "subcomponent declared by "
+        + (subcomponentDeclarations.size() == 1
+            ? getOnlyElement(declaringModules()).getQualifiedName()
+            : declaringModules().stream()
+                .map(TypeElement::getQualifiedName)
+                .collect(joining(", ", "{", "}")));
+  }
+}
diff --git a/java/dagger/internal/codegen/SubcomponentCreatorBindingExpression.java b/java/dagger/internal/codegen/SubcomponentCreatorBindingExpression.java
new file mode 100644
index 0000000..b415d3f
--- /dev/null
+++ b/java/dagger/internal/codegen/SubcomponentCreatorBindingExpression.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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.squareup.javapoet.ClassName;
+import dagger.internal.codegen.javapoet.Expression;
+import javax.lang.model.type.TypeMirror;
+
+/** A binding expression for a subcomponent creator that just invokes the constructor. */
+final class SubcomponentCreatorBindingExpression extends SimpleInvocationBindingExpression {
+  private final TypeMirror creatorType;
+  private final String creatorImplementationName;
+
+  SubcomponentCreatorBindingExpression(
+      ResolvedBindings resolvedBindings, String creatorImplementationName) {
+    super(resolvedBindings);
+    this.creatorType = resolvedBindings.key().type();
+    this.creatorImplementationName = creatorImplementationName;
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    return Expression.create(creatorType, "new $L()", creatorImplementationName);
+  }
+}
diff --git a/java/dagger/internal/codegen/SubcomponentDeclaration.java b/java/dagger/internal/codegen/SubcomponentDeclaration.java
new file mode 100644
index 0000000..5677857
--- /dev/null
+++ b/java/dagger/internal/codegen/SubcomponentDeclaration.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 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.AnnotationMirrors.getAnnotationElementAndValue;
+import static dagger.internal.codegen.ConfigurationAnnotations.getSubcomponentCreator;
+
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.collect.ImmutableSet;
+import dagger.model.Key;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * A declaration for a subcomponent that is included in a module via {@link
+ * dagger.Module#subcomponents()}.
+ */
+@AutoValue
+abstract class SubcomponentDeclaration extends BindingDeclaration {
+  /**
+   * Key for the {@link dagger.Subcomponent.Builder} or {@link
+   * dagger.producers.ProductionSubcomponent.Builder} of {@link #subcomponentType()}.
+   */
+  @Override
+  public abstract Key key();
+
+  /**
+   * The type element that defines the {@link dagger.Subcomponent} or {@link
+   * dagger.producers.ProductionSubcomponent} for this declaration.
+   */
+  abstract TypeElement subcomponentType();
+
+  /** The module annotation. */
+  abstract ModuleAnnotation moduleAnnotation();
+
+  @Memoized
+  @Override
+  public abstract int hashCode();
+
+  @Override
+  public abstract boolean equals(Object obj);
+
+  static class Factory {
+    private final KeyFactory keyFactory;
+
+    @Inject
+    Factory(KeyFactory keyFactory) {
+      this.keyFactory = keyFactory;
+    }
+
+    ImmutableSet<SubcomponentDeclaration> forModule(TypeElement module) {
+      ImmutableSet.Builder<SubcomponentDeclaration> declarations = ImmutableSet.builder();
+      ModuleAnnotation moduleAnnotation = ModuleAnnotation.moduleAnnotation(module).get();
+      Element subcomponentAttribute =
+          getAnnotationElementAndValue(moduleAnnotation.annotation(), "subcomponents").getKey();
+      for (TypeElement subcomponent : moduleAnnotation.subcomponents()) {
+        declarations.add(
+            new AutoValue_SubcomponentDeclaration(
+                Optional.of(subcomponentAttribute),
+                Optional.of(module),
+                keyFactory.forSubcomponentCreator(
+                    getSubcomponentCreator(subcomponent).get().asType()),
+                subcomponent,
+                moduleAnnotation));
+      }
+      return declarations.build();
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/SubcomponentFactoryMethodValidator.java b/java/dagger/internal/codegen/SubcomponentFactoryMethodValidator.java
new file mode 100644
index 0000000..0c6a006
--- /dev/null
+++ b/java/dagger/internal/codegen/SubcomponentFactoryMethodValidator.java
@@ -0,0 +1,154 @@
+/*
+ * 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.internal.codegen.langmodel.DaggerTypes;
+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 SubcomponentFactoryMethodValidator implements BindingGraphPlugin {
+
+  private final DaggerTypes types;
+  private final Map<ComponentNode, Set<TypeElement>> inheritedModulesCache = new HashMap<>();
+
+  @Inject
+  SubcomponentFactoryMethodValidator(DaggerTypes types) {
+    this.types = types;
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/SubcomponentFactoryMethodMissingModule";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    if (!bindingGraph.rootComponentNode().isRealComponent()
+        || bindingGraph.rootComponentNode().isSubcomponent()) {
+      // We don't know all the modules that might be owned by the child until we know the real root
+      // component, which we don't if the root component node is really a module or a subcomponent.
+      return;
+    }
+    bindingGraph.network().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.network().incidentNodes(edge).target();
+    SetView<TypeElement> modulesOwnedByChild = ownedModules(child, graph);
+    return graph.bindings().stream()
+        // bindings owned by child
+        .filter(binding -> binding.componentPath().equals(child.componentPath()))
+        // that require a module instance
+        .filter(binding -> binding.requiresModuleInstance())
+        .map(binding -> 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.network().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().moduleTypes(),
+        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
+            .network()
+            .incidentNodes(edge)
+            .target()
+            .componentPath()
+            .currentComponent()
+            .getQualifiedName(),
+        Joiner.on(", ").join(missingModules));
+  }
+}
diff --git a/java/dagger/internal/codegen/SubcomponentNames.java b/java/dagger/internal/codegen/SubcomponentNames.java
new file mode 100644
index 0000000..f2ffd83
--- /dev/null
+++ b/java/dagger/internal/codegen/SubcomponentNames.java
@@ -0,0 +1,182 @@
+/*
+ * 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.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.DaggerStreams.toImmutableMap;
+import static java.lang.Character.isUpperCase;
+import static java.lang.String.format;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimaps;
+import dagger.model.Key;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Holds the unique simple names for all subcomponents, keyed by their {@link ComponentDescriptor}
+ * and {@link Key} of the subcomponent builder.
+ */
+final class SubcomponentNames {
+  private static final Splitter QUALIFIED_NAME_SPLITTER = Splitter.on('.');
+
+  private final ImmutableMap<ComponentDescriptor, String> namesByDescriptor;
+  private final ImmutableMap<Key, ComponentDescriptor> descriptorsByCreatorKey;
+
+  SubcomponentNames(BindingGraph graph, KeyFactory keyFactory) {
+    this.namesByDescriptor = namesByDescriptor(graph);
+    this.descriptorsByCreatorKey = descriptorsByCreatorKey(keyFactory, namesByDescriptor.keySet());
+  }
+
+  /** Returns the simple component name for the given {@link ComponentDescriptor}. */
+  String get(ComponentDescriptor componentDescriptor) {
+    return namesByDescriptor.get(componentDescriptor);
+  }
+
+  /**
+   * Returns the simple name for the subcomponent creator implementation with the given {@link Key}.
+   */
+  String getCreatorName(Key key) {
+    return getCreatorName(descriptorsByCreatorKey.get(key));
+  }
+
+  /**
+   * Returns the simple name for the subcomponent creator implementation for the given {@link
+   * ComponentDescriptor}.
+   */
+  String getCreatorName(ComponentDescriptor componentDescriptor) {
+    checkArgument(componentDescriptor.creatorDescriptor().isPresent());
+    ComponentCreatorDescriptor creatorDescriptor = componentDescriptor.creatorDescriptor().get();
+    return get(componentDescriptor) + creatorDescriptor.kind().typeName();
+  }
+
+  private static ImmutableMap<ComponentDescriptor, String> namesByDescriptor(BindingGraph graph) {
+    ImmutableListMultimap<String, ComponentDescriptor> componentDescriptorsBySimpleName =
+        Multimaps.index(
+            graph.componentDescriptors(),
+            componentDescriptor -> componentDescriptor.typeElement().getSimpleName().toString());
+    ImmutableMap<ComponentDescriptor, Namer> componentNamers =
+        qualifiedNames(graph.componentDescriptors());
+    Map<ComponentDescriptor, String> subcomponentImplSimpleNames = new LinkedHashMap<>();
+    componentDescriptorsBySimpleName
+        .asMap()
+        .values()
+        .forEach(
+            components ->
+                subcomponentImplSimpleNames.putAll(
+                    disambiguateConflictingSimpleNames(components, componentNamers)));
+    subcomponentImplSimpleNames.remove(graph.componentDescriptor());
+    return ImmutableMap.copyOf(subcomponentImplSimpleNames);
+  }
+
+  private static ImmutableMap<Key, ComponentDescriptor> descriptorsByCreatorKey(
+      KeyFactory keyFactory, ImmutableSet<ComponentDescriptor> subcomponents) {
+    return subcomponents.stream()
+        .filter(subcomponent -> subcomponent.creatorDescriptor().isPresent())
+        .collect(
+            toImmutableMap(
+                subcomponent ->
+                    keyFactory.forSubcomponentCreator(
+                        subcomponent.creatorDescriptor().get().typeElement().asType()),
+                subcomponent -> subcomponent));
+  }
+
+  private static ImmutableBiMap<ComponentDescriptor, String> disambiguateConflictingSimpleNames(
+      Collection<ComponentDescriptor> components,
+      ImmutableMap<ComponentDescriptor, Namer> componentNamers) {
+    Map<String, ComponentDescriptor> generatedSimpleNames = new LinkedHashMap<>();
+
+    // Let's see if we can get away with using simpleName() everywhere.
+    for (ComponentDescriptor component : components) {
+      Namer namer = componentNamers.get(component);
+      if (generatedSimpleNames.containsKey(namer.simpleName())) {
+        break;
+      }
+      generatedSimpleNames.put(namer.simpleName(), component);
+    }
+
+    if (generatedSimpleNames.size() != components.size()) {
+      // Simple approach didn't work out, let's use more complicated names.
+      // We keep them small to fix https://github.com/google/dagger/issues/421.
+      generatedSimpleNames.clear();
+      UniqueNameSet nameSet = new UniqueNameSet();
+      for (ComponentDescriptor component : components) {
+        Namer namer = componentNamers.get(component);
+        String simpleName = namer.simpleName();
+        String basePrefix = namer.uniquingPrefix();
+        generatedSimpleNames.put(
+            format("%s_%s", nameSet.getUniqueName(basePrefix), simpleName), component);
+      }
+    }
+    return ImmutableBiMap.copyOf(generatedSimpleNames).inverse();
+  }
+
+  private static ImmutableMap<ComponentDescriptor, Namer> qualifiedNames(
+      Iterable<ComponentDescriptor> componentDescriptors) {
+    ImmutableMap.Builder<ComponentDescriptor, Namer> builder = ImmutableMap.builder();
+    for (ComponentDescriptor component : componentDescriptors) {
+      builder.put(component, new Namer(component.typeElement()));
+    }
+    return builder.build();
+  }
+
+  private static final class Namer {
+    final TypeElement typeElement;
+
+    Namer(TypeElement typeElement) {
+      this.typeElement = typeElement;
+    }
+
+    String simpleName() {
+      return typeElement.getSimpleName().toString();
+    }
+
+    /** Returns a prefix that could make {@link #simpleName()} more unique. */
+    String uniquingPrefix() {
+      String containerName = typeElement.getEnclosingElement().getSimpleName().toString();
+
+      // If parent element looks like a class, use its initials as a prefix.
+      if (!containerName.isEmpty() && isUpperCase(containerName.charAt(0))) {
+        return CharMatcher.javaLowerCase().removeFrom(containerName);
+      }
+
+      // Not in a normally named class. Prefix with the initials of the elements leading here.
+      Name qualifiedName = typeElement.getQualifiedName();
+      Iterator<String> pieces = QUALIFIED_NAME_SPLITTER.split(qualifiedName).iterator();
+      StringBuilder b = new StringBuilder();
+
+      while (pieces.hasNext()) {
+        String next = pieces.next();
+        if (pieces.hasNext()) {
+          b.append(next.charAt(0));
+        }
+      }
+
+      // Note that a top level class in the root package will be prefixed "$_".
+      return b.length() > 0 ? b.toString() : "$";
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/SwitchingProviders.java b/java/dagger/internal/codegen/SwitchingProviders.java
new file mode 100644
index 0000000..29633d9
--- /dev/null
+++ b/java/dagger/internal/codegen/SwitchingProviders.java
@@ -0,0 +1,227 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getLast;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeSpec;
+import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.model.Key;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Keeps track of all provider expression requests for a component.
+ *
+ * <p>The provider expression request will be satisfied by a single generated {@code Provider} inner
+ * class that can provide instances for all types by switching on an id.
+ */
+// TODO(ronshapiro): either merge this with InnerSwitchingProviders, or repurpose this for
+// SwitchingProducers
+abstract class SwitchingProviders {
+  /**
+   * Defines the {@linkplain Expression expressions} for a switch case in a {@code SwitchProvider}
+   * for a particular binding.
+   */
+  // TODO(user): Consider handling SwitchingProviders with dependency arguments in this class,
+  // then we wouldn't need the getProviderExpression method.
+  // TODO(user): Consider making this an abstract class with equals/hashCode defined by the key
+  // and then using this class directly in Map types instead of Key.
+  interface SwitchCase {
+    /** Returns the {@link Key} for this switch case. */
+    Key key();
+
+    /** Returns the {@link Expression} that returns the provided instance for this case. */
+    Expression getReturnExpression(ClassName switchingProviderClass);
+
+    /**
+     * Returns the {@link Expression} that returns the {@code SwitchProvider} instance for this
+     * case.
+     */
+    Expression getProviderExpression(ClassName switchingProviderClass, int switchId);
+  }
+
+  /**
+   * Each switch size is fixed at 100 cases each and put in its own method. This is to limit the
+   * size of the methods so that we don't reach the "huge" method size limit for Android that will
+   * prevent it from being AOT compiled in some versions of Android (b/77652521). This generally
+   * starts to happen around 1500 cases, but we are choosing 100 to be safe.
+   */
+  // TODO(user): Include a proguard_spec in the Dagger library to prevent inlining these methods?
+  // TODO(ronshapiro): Consider making this configurable via a flag.
+  private static final int MAX_CASES_PER_SWITCH = 100;
+
+  private static final long MAX_CASES_PER_CLASS = MAX_CASES_PER_SWITCH * MAX_CASES_PER_SWITCH;
+  private static final TypeVariableName T = TypeVariableName.get("T");
+
+  /**
+   * Maps a {@link Key} to an instance of a {@link SwitchingProviderBuilder}. Each group of {@code
+   * MAX_CASES_PER_CLASS} keys will share the same instance.
+   */
+  private final Map<Key, SwitchingProviderBuilder> switchingProviderBuilders =
+      new LinkedHashMap<>();
+
+  private final ComponentImplementation componentImplementation;
+  private final ClassName owningComponent;
+  private final DaggerTypes types;
+  private final UniqueNameSet switchingProviderNames = new UniqueNameSet();
+
+  SwitchingProviders(ComponentImplementation componentImplementation, DaggerTypes types) {
+    this.componentImplementation = checkNotNull(componentImplementation);
+    this.types = checkNotNull(types);
+    this.owningComponent = checkNotNull(componentImplementation).name();
+  }
+
+  /** Returns the {@link TypeSpec} for a {@code SwitchingProvider} based on the given builder. */
+  protected abstract TypeSpec createSwitchingProviderType(TypeSpec.Builder builder);
+
+  /**
+   * Returns the {@link Expression} that returns the {@code SwitchProvider} instance for the case.
+   */
+  protected final Expression getProviderExpression(SwitchCase switchCase) {
+    return switchingProviderBuilders
+        .computeIfAbsent(switchCase.key(), key -> getSwitchingProviderBuilder())
+        .getProviderExpression(switchCase);
+  }
+
+  private SwitchingProviderBuilder getSwitchingProviderBuilder() {
+    if (switchingProviderBuilders.size() % MAX_CASES_PER_CLASS == 0) {
+      String name = switchingProviderNames.getUniqueName("SwitchingProvider");
+      SwitchingProviderBuilder switchingProviderBuilder =
+          new SwitchingProviderBuilder(owningComponent.nestedClass(name));
+      componentImplementation.addSwitchingProvider(switchingProviderBuilder::build);
+      return switchingProviderBuilder;
+    }
+    return getLast(switchingProviderBuilders.values());
+  }
+
+  // TODO(user): Consider just merging this class with SwitchingProviders.
+  private final class SwitchingProviderBuilder {
+    // Keep the switch cases ordered by switch id. The switch Ids are assigned in pre-order
+    // traversal, but the switch cases are assigned in post-order traversal of the binding graph.
+    private final Map<Integer, CodeBlock> switchCases = new TreeMap<>();
+    private final Map<Key, Integer> switchIds = new HashMap<>();
+    private final ClassName switchingProviderType;
+
+    SwitchingProviderBuilder(ClassName switchingProviderType) {
+      this.switchingProviderType = checkNotNull(switchingProviderType);
+    }
+
+    Expression getProviderExpression(SwitchCase switchCase) {
+      Key key = switchCase.key();
+      if (!switchIds.containsKey(key)) {
+        int switchId = switchIds.size();
+        switchIds.put(key, switchId);
+        switchCases.put(switchId, createSwitchCaseCodeBlock(switchCase));
+      }
+      return switchCase.getProviderExpression(switchingProviderType, switchIds.get(key));
+    }
+
+    private CodeBlock createSwitchCaseCodeBlock(SwitchCase switchCase) {
+      CodeBlock instanceCodeBlock =
+          switchCase.getReturnExpression(switchingProviderType).box(types).codeBlock();
+
+      return CodeBlock.builder()
+          // TODO(user): Is there something else more useful than the key?
+          .add("case $L: // $L \n", switchIds.get(switchCase.key()), switchCase.key())
+          .addStatement("return ($T) $L", T, instanceCodeBlock)
+          .build();
+    }
+
+    private TypeSpec build() {
+      return createSwitchingProviderType(
+          classBuilder(switchingProviderType)
+              .addTypeVariable(T)
+              .addSuperinterface(providerOf(T))
+              .addMethods(getMethods()));
+    }
+
+    private ImmutableList<MethodSpec> getMethods() {
+      ImmutableList<CodeBlock> switchCodeBlockPartitions = switchCodeBlockPartitions();
+      if (switchCodeBlockPartitions.size() == 1) {
+        // There are less than MAX_CASES_PER_SWITCH cases, so no need for extra get methods.
+        return ImmutableList.of(
+            methodBuilder("get")
+                .addModifiers(PUBLIC)
+                .addAnnotation(suppressWarnings(UNCHECKED))
+                .addAnnotation(Override.class)
+                .returns(T)
+                .addCode(getOnlyElement(switchCodeBlockPartitions))
+                .build());
+      }
+
+      // This is the main public "get" method that will route to private getter methods.
+      MethodSpec.Builder routerMethod =
+          methodBuilder("get")
+              .addModifiers(PUBLIC)
+              .addAnnotation(Override.class)
+              .returns(T)
+              .beginControlFlow("switch (id / $L)", MAX_CASES_PER_SWITCH);
+
+      ImmutableList.Builder<MethodSpec> getMethods = ImmutableList.builder();
+      for (int i = 0; i < switchCodeBlockPartitions.size(); i++) {
+        MethodSpec method =
+            methodBuilder("get" + i)
+                .addModifiers(PRIVATE)
+                .addAnnotation(suppressWarnings(UNCHECKED))
+                .returns(T)
+                .addCode(switchCodeBlockPartitions.get(i))
+                .build();
+        getMethods.add(method);
+        routerMethod.addStatement("case $L: return $N()", i, method);
+      }
+
+      routerMethod.addStatement("default: throw new $T(id)", AssertionError.class).endControlFlow();
+
+      return getMethods.add(routerMethod.build()).build();
+    }
+
+    private ImmutableList<CodeBlock> switchCodeBlockPartitions() {
+      return Lists.partition(ImmutableList.copyOf(switchCases.values()), MAX_CASES_PER_SWITCH)
+          .stream()
+          .map(
+              partitionCases ->
+                  CodeBlock.builder()
+                      .beginControlFlow("switch (id)")
+                      .add(CodeBlocks.concat(partitionCases))
+                      .addStatement("default: throw new $T(id)", AssertionError.class)
+                      .endControlFlow()
+                      .build())
+          .collect(toImmutableList());
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/SystemComponentsModule.java b/java/dagger/internal/codegen/SystemComponentsModule.java
new file mode 100644
index 0000000..3f59b24
--- /dev/null
+++ b/java/dagger/internal/codegen/SystemComponentsModule.java
@@ -0,0 +1,31 @@
+/*
+ * 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.common.base.Ticker;
+import dagger.Module;
+import dagger.Provides;
+
+/** Module to provide system-level dependencies (such as time-related objects). */
+@Module
+interface SystemComponentsModule {
+
+  @Provides
+  static Ticker ticker() {
+    return Ticker.systemTicker();
+  }
+}
diff --git a/java/dagger/internal/codegen/TopLevel.java b/java/dagger/internal/codegen/TopLevel.java
new file mode 100644
index 0000000..4f456f2
--- /dev/null
+++ b/java/dagger/internal/codegen/TopLevel.java
@@ -0,0 +1,29 @@
+/*
+ * 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 java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import javax.inject.Qualifier;
+
+/**
+ * A {@link Qualifier} for bindings that are associated with the top level component implementation.
+ */
+@Retention(RUNTIME)
+@Qualifier
+@interface TopLevel {}
diff --git a/java/dagger/internal/codegen/TopLevelImplementationComponent.java b/java/dagger/internal/codegen/TopLevelImplementationComponent.java
new file mode 100644
index 0000000..306c05d
--- /dev/null
+++ b/java/dagger/internal/codegen/TopLevelImplementationComponent.java
@@ -0,0 +1,41 @@
+/*
+ * 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 dagger.BindsInstance;
+import dagger.Module;
+import dagger.Subcomponent;
+
+/**
+ * A shared subcomponent for a top-level {@link ComponentImplementation} and any nested child
+ * implementations.
+ */
+@PerGeneratedFile
+@Subcomponent
+interface TopLevelImplementationComponent {
+  CurrentImplementationSubcomponent.Builder currentImplementationSubcomponentBuilder();
+
+  @Subcomponent.Builder
+  interface Builder {
+    @BindsInstance
+    Builder topLevelComponent(@TopLevel ComponentImplementation topLevelImplementation);
+    TopLevelImplementationComponent build();
+  }
+
+  @Module(subcomponents = TopLevelImplementationComponent.class)
+  interface InstallationModule {}
+}
diff --git a/java/dagger/internal/codegen/TypeCheckingProcessingStep.java b/java/dagger/internal/codegen/TypeCheckingProcessingStep.java
new file mode 100644
index 0000000..00769b2
--- /dev/null
+++ b/java/dagger/internal/codegen/TypeCheckingProcessingStep.java
@@ -0,0 +1,67 @@
+/*
+ * 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.common.base.Preconditions.checkNotNull;
+
+import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
+import java.lang.annotation.Annotation;
+import java.util.function.Function;
+import javax.lang.model.element.Element;
+
+/**
+ * A {@link ProcessingStep} that processes one element at a time and defers any for which {@link
+ * TypeNotPresentException} is thrown.
+ */
+// TODO(dpb): Contribute to auto-common.
+abstract class TypeCheckingProcessingStep<E extends Element> implements ProcessingStep {
+  private final Function<Element, E> downcaster;
+
+  TypeCheckingProcessingStep(Function<Element, E> downcaster) {
+    this.downcaster = checkNotNull(downcaster);
+  }
+
+  @Override
+  public ImmutableSet<Element> process(
+      SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
+    ImmutableSet.Builder<Element> deferredElements = ImmutableSet.builder();
+    ImmutableSetMultimap.copyOf(elementsByAnnotation)
+        .inverse()
+        .asMap()
+        .forEach(
+            (element, annotations) -> {
+              try {
+                process(downcaster.apply(element), ImmutableSet.copyOf(annotations));
+              } catch (TypeNotPresentException e) {
+                deferredElements.add(element);
+              }
+            });
+    return deferredElements.build();
+  }
+
+  /**
+   * Processes one element. If this method throws {@link TypeNotPresentException}, the element will
+   * be deferred until the next round of processing.
+   *
+   * @param annotations the subset of {@link ProcessingStep#annotations()} that annotate {@code
+   *     element}
+   */
+  protected abstract void process(E element, ImmutableSet<Class<? extends Annotation>> annotations);
+}
diff --git a/java/dagger/internal/codegen/TypeProtoConverter.java b/java/dagger/internal/codegen/TypeProtoConverter.java
new file mode 100644
index 0000000..c703bd8
--- /dev/null
+++ b/java/dagger/internal/codegen/TypeProtoConverter.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 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 javax.lang.model.util.ElementFilter.typesIn;
+
+import com.google.auto.common.MoreTypes;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.TypeProto;
+import dagger.internal.codegen.serialization.TypeProto.PrimitiveKind;
+import javax.inject.Inject;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.WildcardType;
+
+/** Converts {@link TypeMirror}s to {@link TypeProto}s and vice-versa. */
+final class TypeProtoConverter {
+  // TODO(ronshapiro): if DaggerTypes and DaggerElements become public, move this file to
+  // dagger.internal.codegen.serialization
+  private final DaggerTypes types;
+  private final DaggerElements elements;
+
+  @Inject
+  TypeProtoConverter(DaggerTypes types, DaggerElements elements) {
+    this.types = types;
+    this.elements = elements;
+  }
+
+  /** Translates a {@link TypeMirror} to a proto representation. */
+  static TypeProto toProto(TypeMirror type) {
+    TypeProto.Builder builder = TypeProto.newBuilder();
+    int arrayDimensions = 0;
+    while (type.getKind().equals(TypeKind.ARRAY)) {
+      type = MoreTypes.asArray(type).getComponentType();
+      arrayDimensions++;
+    }
+    builder.setArrayDimensions(arrayDimensions);
+    if (type.getKind().isPrimitive()) {
+      builder.setPrimitiveKind(PrimitiveKind.valueOf(type.getKind().name()));
+    } else if (type.getKind().equals(TypeKind.WILDCARD)) {
+      WildcardType wildcardType = MoreTypes.asWildcard(type);
+      TypeProto.Wildcard.Builder wildcardBuilder = TypeProto.Wildcard.newBuilder();
+      if (wildcardType.getExtendsBound() != null) {
+        wildcardBuilder.setExtendsBound(toProto(wildcardType.getExtendsBound()));
+      } else if (wildcardType.getSuperBound() != null) {
+        wildcardBuilder.setSuperBound(toProto(wildcardType.getSuperBound()));
+      }
+      builder.setWildcard(wildcardBuilder);
+    } else {
+      TypeElement typeElement = MoreTypes.asTypeElement(type);
+      DeclaredType declaredType = MoreTypes.asDeclared(type);
+      TypeMirror enclosingType = declaredType.getEnclosingType();
+      if (enclosingType.getKind().equals(TypeKind.NONE)) {
+        builder.setQualifiedName(typeElement.getQualifiedName().toString());
+      } else {
+        builder
+            .setEnclosingType(toProto(enclosingType))
+            .setSimpleName(typeElement.getSimpleName().toString());
+      }
+      declaredType.getTypeArguments().stream()
+          .map(TypeProtoConverter::toProto)
+          .forEachOrdered(builder::addTypeArguments);
+    }
+    return builder.build();
+  }
+
+  /** Creates an {@link TypeMirror} from its proto representation. */
+  TypeMirror fromProto(TypeProto type) {
+    if (type.hasWildcard()) {
+      return wildcardType(type.getWildcard());
+    }
+
+    TypeMirror[] typeArguments =
+        type.getTypeArgumentsList().stream().map(this::fromProto).toArray(TypeMirror[]::new);
+    TypeMirror typeMirror;
+    if (!type.getPrimitiveKind().equals(PrimitiveKind.UNKNOWN)) {
+      typeMirror = types.getPrimitiveType(TypeKind.valueOf(type.getPrimitiveKind().name()));
+    } else if (type.hasEnclosingType()) {
+      DeclaredType enclosingType = MoreTypes.asDeclared(fromProto(type.getEnclosingType()));
+      TypeElement typeElement =
+          typesIn(enclosingType.asElement().getEnclosedElements()).stream()
+              .filter(inner -> inner.getSimpleName().contentEquals(type.getSimpleName()))
+              .findFirst()
+              .get();
+      typeMirror = types.getDeclaredType(enclosingType, typeElement, typeArguments);
+    } else {
+      typeMirror =
+          types.getDeclaredType(elements.getTypeElement(type.getQualifiedName()), typeArguments);
+    }
+    for (int i = 0; i < type.getArrayDimensions(); i++) {
+      typeMirror = types.getArrayType(typeMirror);
+    }
+    return typeMirror;
+  }
+
+  private TypeMirror wildcardType(TypeProto.Wildcard wildcard) {
+    if (wildcard.hasExtendsBound()) {
+      return types.getWildcardType(fromProto(wildcard.getExtendsBound()), null);
+    } else if (wildcard.hasSuperBound()) {
+      return types.getWildcardType(null, fromProto(wildcard.getSuperBound()));
+    } else {
+      return types.getWildcardType(null, null);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/UniqueNameSet.java b/java/dagger/internal/codegen/UniqueNameSet.java
new file mode 100644
index 0000000..11c48b3
--- /dev/null
+++ b/java/dagger/internal/codegen/UniqueNameSet.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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 java.util.HashSet;
+import java.util.Set;
+
+/** A collector for names to be used in the same namespace that should not conflict. */
+final class UniqueNameSet {
+  private final Set<String> uniqueNames = new HashSet<>();
+
+  /**
+   * Generates a unique name using {@code base}. If {@code base} has not yet been added, it will be
+   * returned as-is. If your {@code base} is healthy, this will always return {@code base}.
+   */
+  String getUniqueName(CharSequence base) {
+    String name = base.toString();
+    for (int differentiator = 2; !uniqueNames.add(name); differentiator++) {
+      name = base.toString() + differentiator;
+    }
+    return name;
+  }
+
+  /**
+   * Adds {@code name} without any modification to the name set. Has no effect if {@code name} is
+   * already present in the set.
+   */
+  void claim(CharSequence name) {
+    uniqueNames.add(name.toString());
+  }
+}
diff --git a/java/dagger/internal/codegen/UnwrappedMapKeyGenerator.java b/java/dagger/internal/codegen/UnwrappedMapKeyGenerator.java
new file mode 100644
index 0000000..2b7b02c
--- /dev/null
+++ b/java/dagger/internal/codegen/UnwrappedMapKeyGenerator.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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 dagger.MapKey;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import java.util.Set;
+import javax.annotation.processing.Filer;
+import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Generates classes that create annotation instances for an unwrapped {@link MapKey} annotation
+ * type whose nested value is an annotation. The generated class will have a private empty
+ * constructor and a static method that creates each annotation type that is nested in the top-level
+ * annotation type.
+ *
+ * <p>So for an example {@link MapKey} annotation:
+ *
+ * <pre>
+ *   {@literal @MapKey}(unwrapValue = true)
+ *   {@literal @interface} Foo {
+ *     Bar bar();
+ *   }
+ *
+ *   {@literal @interface} Bar {
+ *     {@literal Class<?> baz();}
+ *   }
+ * </pre>
+ *
+ * the generated class will look like:
+ *
+ * <pre>
+ *   public final class FooCreator {
+ *     private FooCreator() {}
+ *
+ *     public static Bar createBar({@literal Class<?> baz}) { … }
+ *   }
+ * </pre>
+ */
+final class UnwrappedMapKeyGenerator extends AnnotationCreatorGenerator {
+
+  @Inject
+  UnwrappedMapKeyGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
+    super(filer, elements, sourceVersion);
+  }
+
+  @Override
+  protected Set<TypeElement> annotationsToCreate(TypeElement annotationElement) {
+    Set<TypeElement> nestedAnnotationElements = super.annotationsToCreate(annotationElement);
+    nestedAnnotationElements.remove(annotationElement);
+    return nestedAnnotationElements;
+  }
+}
diff --git a/java/dagger/internal/codegen/Util.java b/java/dagger/internal/codegen/Util.java
new file mode 100644
index 0000000..1869b7c
--- /dev/null
+++ b/java/dagger/internal/codegen/Util.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 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 javax.lang.model.element.ElementKind.CONSTRUCTOR;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import java.util.Map;
+import java.util.function.Function;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Utilities for handling types in annotation processors
+ */
+final class Util {
+  /**
+   * Returns true if and only if a component can instantiate new instances (typically of a module)
+   * rather than requiring that they be passed.
+   */
+  static boolean componentCanMakeNewInstances(TypeElement typeElement) {
+    switch (typeElement.getKind()) {
+      case CLASS:
+        break;
+      case ENUM:
+      case ANNOTATION_TYPE:
+      case INTERFACE:
+        return false;
+      default:
+        throw new AssertionError("TypeElement cannot have kind: " + typeElement.getKind());
+    }
+
+    if (typeElement.getModifiers().contains(ABSTRACT)) {
+      return false;
+    }
+
+    if (requiresEnclosingInstance(typeElement)) {
+      return false;
+    }
+
+    for (Element enclosed : typeElement.getEnclosedElements()) {
+      if (enclosed.getKind().equals(CONSTRUCTOR)
+          && ((ExecutableElement) enclosed).getParameters().isEmpty()
+          && !enclosed.getModifiers().contains(PRIVATE)) {
+        return true;
+      }
+    }
+
+    // TODO(gak): still need checks for visibility
+
+    return false;
+  }
+
+  private static boolean requiresEnclosingInstance(TypeElement typeElement) {
+    switch (typeElement.getNestingKind()) {
+      case TOP_LEVEL:
+        return false;
+      case MEMBER:
+        return !typeElement.getModifiers().contains(STATIC);
+      case ANONYMOUS:
+      case LOCAL:
+        return true;
+    }
+    throw new AssertionError(
+        "TypeElement cannot have nesting kind: " + typeElement.getNestingKind());
+  }
+
+  /**
+   * A version of {@link Map#computeIfAbsent(Object, Function)} that allows {@code mappingFunction}
+   * to update {@code map}.
+   */
+  static <K, V> V reentrantComputeIfAbsent(
+      Map<K, V> map, K key, Function<? super K, ? extends V> mappingFunction) {
+    V value = map.get(key);
+    if (value == null) {
+      value = mappingFunction.apply(key);
+      if (value != null) {
+        map.put(key, value);
+      }
+    }
+    return value;
+  }
+
+  private Util() {}
+}
diff --git a/java/dagger/internal/codegen/Validation.java b/java/dagger/internal/codegen/Validation.java
new file mode 100644
index 0000000..f6a4b3f
--- /dev/null
+++ b/java/dagger/internal/codegen/Validation.java
@@ -0,0 +1,31 @@
+/*
+ * 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 java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier annotation for the {@link dagger.spi.BindingGraphPlugin}s that are used to implement
+ * core Dagger validation.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+@interface Validation {}
diff --git a/java/dagger/internal/codegen/ValidationReport.java b/java/dagger/internal/codegen/ValidationReport.java
new file mode 100644
index 0000000..d7c3252
--- /dev/null
+++ b/java/dagger/internal/codegen/ValidationReport.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2014 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 dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.ElementFormatter.elementToString;
+import static javax.tools.Diagnostic.Kind.ERROR;
+import static javax.tools.Diagnostic.Kind.NOTE;
+import static javax.tools.Diagnostic.Kind.WARNING;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.graph.Traverser;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.errorprone.annotations.CheckReturnValue;
+import java.util.Optional;
+import javax.annotation.processing.Messager;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.tools.Diagnostic;
+import javax.tools.Diagnostic.Kind;
+
+/** A collection of issues to report for source code. */
+@AutoValue
+abstract class ValidationReport<T extends Element> {
+
+  /**
+   * The subject of the report. Should be an element within a compilation unit being processed by
+   * this compilation task.
+   */
+  abstract T subject();
+
+  /** The items to report for the {@linkplain #subject() subject}. */
+  abstract ImmutableSet<Item> items();
+
+  /** Returns the {@link #items()} from this report and all transitive subreports. */
+  ImmutableSet<Item> allItems() {
+    return allReports()
+        .stream()
+        .flatMap(report -> report.items().stream())
+        .collect(toImmutableSet());
+  }
+
+  /** Other reports associated with this one. */
+  abstract ImmutableSet<ValidationReport<?>> subreports();
+
+  private static final Traverser<ValidationReport<?>> SUBREPORTS =
+      Traverser.forTree(ValidationReport::subreports);
+
+  /** Returns this report and all transitive subreports. */
+  ImmutableSet<ValidationReport<?>> allReports() {
+    return ImmutableSet.copyOf(SUBREPORTS.depthFirstPreOrder(this));
+  }
+
+  /**
+   * {@code true} if {@link #isClean()} should return {@code false} even if there are no error items
+   * in this report.
+   */
+  abstract boolean markedDirty();
+
+  /**
+   * Returns {@code true} if there are no errors in this report or any subreports and {@link
+   * #markedDirty()} is {@code false}.
+   */
+  boolean isClean() {
+    if (markedDirty()) {
+      return false;
+    }
+    for (Item item : items()) {
+      switch (item.kind()) {
+        case ERROR:
+          return false;
+        default:
+          break;
+      }
+    }
+    for (ValidationReport<?> subreport : subreports()) {
+      if (!subreport.isClean()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Prints all {@linkplain #items() messages} to {@code messager} (and recurs for subreports). If a
+   * message's {@linkplain Item#element() element} is contained within the report's {@linkplain
+   * #subject() subject}, associates the message with the message's element. Otherwise, since
+   * {@link Diagnostic} reporting is expected to be associated with elements that are currently
+   * being compiled, associates the message with the subject itself and prepends a reference to the
+   * item's element.
+   */
+  void printMessagesTo(Messager messager) {
+    for (Item item : items()) {
+      if (isEnclosedIn(subject(), item.element())) {
+        if (item.annotation().isPresent()) {
+          if (item.annotationValue().isPresent()) {
+            messager.printMessage(
+                item.kind(),
+                item.message(),
+                item.element(),
+                item.annotation().get(),
+                item.annotationValue().get());
+          } else {
+            messager.printMessage(
+                item.kind(), item.message(), item.element(), item.annotation().get());
+          }
+        } else {
+          messager.printMessage(item.kind(), item.message(), item.element());
+        }
+      } else {
+        String message = String.format("[%s] %s", elementToString(item.element()), item.message());
+        messager.printMessage(item.kind(), message, subject());
+      }
+    }
+    for (ValidationReport<?> subreport : subreports()) {
+      subreport.printMessagesTo(messager);
+    }
+  }
+
+  private static boolean isEnclosedIn(Element parent, Element child) {
+    Element current = child;
+    while (current != null) {
+      if (current.equals(parent)) {
+        return true;
+      }
+      current = current.getEnclosingElement();
+    }
+    return false;
+  }
+
+  @AutoValue
+  static abstract class Item {
+    abstract String message();
+    abstract Kind kind();
+    abstract Element element();
+    abstract Optional<AnnotationMirror> annotation();
+    abstract Optional<AnnotationValue> annotationValue();
+  }
+
+  static <T extends Element> Builder<T> about(T subject) {
+    return new Builder<>(subject);
+  }
+
+  @CanIgnoreReturnValue
+  static final class Builder<T extends Element> {
+    private final T subject;
+    private final ImmutableSet.Builder<Item> items = ImmutableSet.builder();
+    private final ImmutableSet.Builder<ValidationReport<?>> subreports = ImmutableSet.builder();
+    private boolean markedDirty;
+
+    private Builder(T subject) {
+      this.subject = subject;
+    }
+
+    @CheckReturnValue
+    T getSubject() {
+      return subject;
+    }
+
+    Builder<T> addItems(Iterable<Item> newItems) {
+      items.addAll(newItems);
+      return this;
+    }
+
+    Builder<T> addError(String message) {
+      return addError(message, subject);
+    }
+
+    Builder<T> addError(String message, Element element) {
+      return addItem(message, ERROR, element);
+    }
+
+    Builder<T> addError(String message, Element element, AnnotationMirror annotation) {
+      return addItem(message, ERROR, element, annotation);
+    }
+
+    Builder<T> addError(
+        String message,
+        Element element,
+        AnnotationMirror annotation,
+        AnnotationValue annotationValue) {
+      return addItem(message, ERROR, element, annotation, annotationValue);
+    }
+
+    Builder<T> addWarning(String message) {
+      return addWarning(message, subject);
+    }
+
+    Builder<T> addWarning(String message, Element element) {
+      return addItem(message, WARNING, element);
+    }
+
+    Builder<T> addWarning(String message, Element element, AnnotationMirror annotation) {
+      return addItem(message, WARNING, element, annotation);
+    }
+
+    Builder<T> addWarning(
+        String message,
+        Element element,
+        AnnotationMirror annotation,
+        AnnotationValue annotationValue) {
+      return addItem(message, WARNING, element, annotation, annotationValue);
+    }
+
+    Builder<T> addNote(String message) {
+      return addNote(message, subject);
+    }
+
+    Builder<T> addNote(String message, Element element) {
+      return addItem(message, NOTE, element);
+    }
+
+    Builder<T> addNote(String message, Element element, AnnotationMirror annotation) {
+      return addItem(message, NOTE, element, annotation);
+    }
+
+    Builder<T> addNote(
+        String message,
+        Element element,
+        AnnotationMirror annotation,
+        AnnotationValue annotationValue) {
+      return addItem(message, NOTE, element, annotation, annotationValue);
+    }
+
+    Builder<T> addItem(String message, Kind kind, Element element) {
+      return addItem(message, kind, element, Optional.empty(), Optional.empty());
+    }
+
+    Builder<T> addItem(String message, Kind kind, Element element, AnnotationMirror annotation) {
+      return addItem(message, kind, element, Optional.of(annotation), Optional.empty());
+    }
+
+    Builder<T> addItem(
+        String message,
+        Kind kind,
+        Element element,
+        AnnotationMirror annotation,
+        AnnotationValue annotationValue) {
+      return addItem(message, kind, element, Optional.of(annotation), Optional.of(annotationValue));
+    }
+
+    private Builder<T> addItem(
+        String message,
+        Kind kind,
+        Element element,
+        Optional<AnnotationMirror> annotation,
+        Optional<AnnotationValue> annotationValue) {
+      items.add(
+          new AutoValue_ValidationReport_Item(message, kind, element, annotation, annotationValue));
+      return this;
+    }
+
+    /**
+     * If called, then {@link #isClean()} will return {@code false} even if there are no error items
+     * in the report.
+     */
+    void markDirty() {
+      this.markedDirty = true;
+    }
+
+    Builder<T> addSubreport(ValidationReport<?> subreport) {
+      subreports.add(subreport);
+      return this;
+    }
+
+    @CheckReturnValue
+    ValidationReport<T> build() {
+      return new AutoValue_ValidationReport<>(
+          subject, items.build(), subreports.build(), markedDirty);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/ValidationType.java b/java/dagger/internal/codegen/ValidationType.java
new file mode 100644
index 0000000..5d19dc1
--- /dev/null
+++ b/java/dagger/internal/codegen/ValidationType.java
@@ -0,0 +1,41 @@
+/*
+ * 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 java.util.Optional;
+import javax.tools.Diagnostic;
+
+/**
+ * Allows options to control how component process validates things such as scope cycles
+ * or nullability.
+ */
+enum ValidationType {
+  ERROR,
+  WARNING,
+  NONE;
+
+  Optional<Diagnostic.Kind> diagnosticKind() {
+    switch (this) {
+      case ERROR:
+        return Optional.of(Diagnostic.Kind.ERROR);
+      case WARNING:
+        return Optional.of(Diagnostic.Kind.WARNING);
+      default:
+        return Optional.empty();
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/base/BUILD b/java/dagger/internal/codegen/base/BUILD
deleted file mode 100644
index 0bcbb12..0000000
--- a/java/dagger/internal/codegen/base/BUILD
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Sources related to compiler options.
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-SHARED_SOURCES = [
-    "ClearableCache.java",
-    "MoreAnnotationMirrors.java",
-    "MoreAnnotationValues.java",
-]
-
-java_library(
-    name = "base",
-    srcs = glob(
-        ["*.java"],
-        exclude = SHARED_SOURCES,
-    ),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    tags = ["maven:merged"],
-    exports = [":shared"],
-    deps = [
-        ":shared",
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-# TODO(bcorso): Remove this target but first remove spi and producers from :base
-java_library(
-    name = "shared",
-    srcs = SHARED_SOURCES,
-    tags = ["maven:merged"],
-    deps = [
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
diff --git a/java/dagger/internal/codegen/base/ClearableCache.java b/java/dagger/internal/codegen/base/ClearableCache.java
deleted file mode 100644
index 61e9482..0000000
--- a/java/dagger/internal/codegen/base/ClearableCache.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 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.base;
-
-/** A cache of objects that can be cleared. */
-public interface ClearableCache {
-  /** Releases cached references. */
-  void clearCache();
-}
diff --git a/java/dagger/internal/codegen/base/ComponentAnnotation.java b/java/dagger/internal/codegen/base/ComponentAnnotation.java
deleted file mode 100644
index c9b3580..0000000
--- a/java/dagger/internal/codegen/base/ComponentAnnotation.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2019 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.base;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreTypes.asTypeElements;
-import static com.google.auto.common.MoreTypes.isTypeOf;
-import static dagger.internal.codegen.base.MoreAnnotationValues.asAnnotationValues;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER_MODULE;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import dagger.Component;
-import dagger.Subcomponent;
-import dagger.producers.ProductionComponent;
-import dagger.producers.ProductionSubcomponent;
-import java.lang.annotation.Annotation;
-import java.util.Collection;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A {@code @Component}, {@code @Subcomponent}, {@code @ProductionComponent}, or
- * {@code @ProductionSubcomponent} annotation, or a {@code @Module} or {@code @ProducerModule}
- * annotation that is being treated as a component annotation when validating full binding graphs
- * for modules.
- */
-public abstract class ComponentAnnotation {
-  /** The root component annotation types. */
-  private static final ImmutableSet<Class<? extends Annotation>> ROOT_COMPONENT_ANNOTATIONS =
-     ImmutableSet.of(Component.class, ProductionComponent.class);
-
-  /** The subcomponent annotation types. */
-  private static final ImmutableSet<Class<? extends Annotation>> SUBCOMPONENT_ANNOTATIONS =
-     ImmutableSet.of(Subcomponent.class, ProductionSubcomponent.class);
-
-  /** All component annotation types. */
-  private static final ImmutableSet<Class<? extends Annotation>> ALL_COMPONENT_ANNOTATIONS =
-     ImmutableSet.<Class<? extends Annotation>>builder()
-         .addAll(ROOT_COMPONENT_ANNOTATIONS)
-         .addAll(SUBCOMPONENT_ANNOTATIONS)
-         .build();
-
-  /** The annotation itself. */
-  public abstract AnnotationMirror annotation();
-
-  /** The simple name of the annotation type. */
-  public String simpleName() {
-    return MoreAnnotationMirrors.simpleName(annotation()).toString();
-  }
-
-  /**
-   * Returns {@code true} if the annotation is a {@code @Subcomponent} or
-   * {@code @ProductionSubcomponent}.
-   */
-  public abstract boolean isSubcomponent();
-
-  /**
-   * Returns {@code true} if the annotation is a {@code @ProductionComponent},
-   * {@code @ProductionSubcomponent}, or {@code @ProducerModule}.
-   */
-  public abstract boolean isProduction();
-
-  /**
-   * Returns {@code true} if the annotation is a real component annotation and not a module
-   * annotation.
-   */
-  public abstract boolean isRealComponent();
-
-  /** The values listed as {@code dependencies}. */
-  public abstract ImmutableList<AnnotationValue> dependencyValues();
-
-  /** The types listed as {@code dependencies}. */
-  public ImmutableList<TypeMirror> dependencyTypes() {
-    return dependencyValues().stream().map(MoreAnnotationValues::asType).collect(toImmutableList());
-  }
-
-  /**
-   * The types listed as {@code dependencies}.
-   *
-   * @throws IllegalArgumentException if any of {@link #dependencyTypes()} are error types
-   */
-  public ImmutableList<TypeElement> dependencies() {
-    return asTypeElements(dependencyTypes()).asList();
-  }
-
-  /** The values listed as {@code modules}. */
-  public abstract ImmutableList<AnnotationValue> moduleValues();
-
-  /** The types listed as {@code modules}. */
-  public ImmutableList<TypeMirror> moduleTypes() {
-    return moduleValues().stream().map(MoreAnnotationValues::asType).collect(toImmutableList());
-  }
-
-  /**
-   * The types listed as {@code modules}.
-   *
-   * @throws IllegalArgumentException if any of {@link #moduleTypes()} are error types
-   */
-  public ImmutableSet<TypeElement> modules() {
-    return asTypeElements(moduleTypes());
-  }
-
-  protected final ImmutableList<AnnotationValue> getAnnotationValues(String parameterName) {
-    return asAnnotationValues(getAnnotationValue(annotation(), parameterName));
-  }
-
-  /**
-   * Returns an object representing a root component annotation, not a subcomponent annotation, if
-   * one is present on {@code typeElement}.
-   */
-  public static Optional<ComponentAnnotation> rootComponentAnnotation(TypeElement typeElement) {
-    return anyComponentAnnotation(typeElement, ROOT_COMPONENT_ANNOTATIONS);
-  }
-
-  /**
-   * Returns an object representing a subcomponent annotation, if one is present on {@code
-   * typeElement}.
-   */
-  public static Optional<ComponentAnnotation> subcomponentAnnotation(TypeElement typeElement) {
-    return anyComponentAnnotation(typeElement, SUBCOMPONENT_ANNOTATIONS);
-  }
-
-  /**
-   * Returns an object representing a root component or subcomponent annotation, if one is present
-   * on {@code typeElement}.
-   */
-  public static Optional<ComponentAnnotation> anyComponentAnnotation(TypeElement typeElement) {
-    return anyComponentAnnotation(typeElement, ALL_COMPONENT_ANNOTATIONS);
-  }
-
-  private static Optional<ComponentAnnotation> anyComponentAnnotation(
-      TypeElement typeElement, Collection<Class<? extends Annotation>> annotations) {
-    return getAnyAnnotation(typeElement, annotations).map(ComponentAnnotation::componentAnnotation);
-  }
-
-  /** Returns {@code true} if the argument is a component annotation. */
-  public static boolean isComponentAnnotation(AnnotationMirror annotation) {
-    return ALL_COMPONENT_ANNOTATIONS.stream()
-        .anyMatch(annotationClass -> isTypeOf(annotationClass, annotation.getAnnotationType()));
-  }
-
-  /** Creates an object representing a component or subcomponent annotation. */
-  public static ComponentAnnotation componentAnnotation(AnnotationMirror annotation) {
-    RealComponentAnnotation.Builder annotationBuilder =
-        RealComponentAnnotation.builder().annotation(annotation);
-
-    if (isTypeOf(Component.class, annotation.getAnnotationType())) {
-      return annotationBuilder.isProduction(false).isSubcomponent(false).build();
-    }
-    if (isTypeOf(Subcomponent.class, annotation.getAnnotationType())) {
-      return annotationBuilder.isProduction(false).isSubcomponent(true).build();
-    }
-    if (isTypeOf(ProductionComponent.class, annotation.getAnnotationType())) {
-      return annotationBuilder.isProduction(true).isSubcomponent(false).build();
-    }
-    if (isTypeOf(ProductionSubcomponent.class, annotation.getAnnotationType())) {
-      return annotationBuilder.isProduction(true).isSubcomponent(true).build();
-    }
-    throw new IllegalArgumentException(
-        annotation
-            + " must be a Component, Subcomponent, ProductionComponent, "
-            + "or ProductionSubcomponent annotation");
-  }
-
-  /** Creates a fictional component annotation representing a module. */
-  public static ComponentAnnotation fromModuleAnnotation(ModuleAnnotation moduleAnnotation) {
-    return new AutoValue_ComponentAnnotation_FictionalComponentAnnotation(moduleAnnotation);
-  }
-
-  /** The root component annotation types. */
-  public static ImmutableSet<Class<? extends Annotation>> rootComponentAnnotations() {
-    return ROOT_COMPONENT_ANNOTATIONS;
-  }
-
-  /** The subcomponent annotation types. */
-  public static ImmutableSet<Class<? extends Annotation>> subcomponentAnnotations() {
-    return SUBCOMPONENT_ANNOTATIONS;
-  }
-
-  /** All component annotation types. */
-  public static ImmutableSet<Class<? extends Annotation>> allComponentAnnotations() {
-    return ALL_COMPONENT_ANNOTATIONS;
-  }
-
-  /**
-   * An actual component annotation.
-   *
-   * @see FictionalComponentAnnotation
-   */
-  @AutoValue
-  abstract static class RealComponentAnnotation extends ComponentAnnotation {
-
-    @Override
-    @Memoized
-    public ImmutableList<AnnotationValue> dependencyValues() {
-      return isSubcomponent() ? ImmutableList.of() : getAnnotationValues("dependencies");
-    }
-
-    @Override
-    @Memoized
-    public ImmutableList<TypeMirror> dependencyTypes() {
-      return super.dependencyTypes();
-    }
-
-    @Override
-    @Memoized
-    public ImmutableList<TypeElement> dependencies() {
-      return super.dependencies();
-    }
-
-    @Override
-    public boolean isRealComponent() {
-      return true;
-    }
-
-    @Override
-    @Memoized
-    public ImmutableList<AnnotationValue> moduleValues() {
-      return getAnnotationValues("modules");
-    }
-
-    @Override
-    @Memoized
-    public ImmutableList<TypeMirror> moduleTypes() {
-      return super.moduleTypes();
-    }
-
-    @Override
-    @Memoized
-    public ImmutableSet<TypeElement> modules() {
-      return super.modules();
-    }
-
-    static Builder builder() {
-      return new AutoValue_ComponentAnnotation_RealComponentAnnotation.Builder();
-    }
-
-    @AutoValue.Builder
-    interface Builder {
-      Builder annotation(AnnotationMirror annotation);
-
-      Builder isSubcomponent(boolean isSubcomponent);
-
-      Builder isProduction(boolean isProduction);
-
-      RealComponentAnnotation build();
-    }
-  }
-
-  /**
-   * A fictional component annotation used to represent modules or other collections of bindings as
-   * a component.
-   */
-  @AutoValue
-  abstract static class FictionalComponentAnnotation extends ComponentAnnotation {
-
-    @Override
-    public AnnotationMirror annotation() {
-      return moduleAnnotation().annotation();
-    }
-
-    @Override
-    public boolean isSubcomponent() {
-      return false;
-    }
-
-    @Override
-    public boolean isProduction() {
-      return ClassName.get(asType(moduleAnnotation().annotation().getAnnotationType().asElement()))
-          .equals(PRODUCER_MODULE);
-    }
-
-    @Override
-    public boolean isRealComponent() {
-      return false;
-    }
-
-    @Override
-    public ImmutableList<AnnotationValue> dependencyValues() {
-      return ImmutableList.of();
-    }
-
-    @Override
-    public ImmutableList<AnnotationValue> moduleValues() {
-      return moduleAnnotation().includesAsAnnotationValues();
-    }
-
-    @Override
-    @Memoized
-    public ImmutableList<TypeMirror> moduleTypes() {
-      return super.moduleTypes();
-    }
-
-    @Override
-    @Memoized
-    public ImmutableSet<TypeElement> modules() {
-      return super.modules();
-    }
-
-    public abstract ModuleAnnotation moduleAnnotation();
-  }
-}
diff --git a/java/dagger/internal/codegen/base/ContributionType.java b/java/dagger/internal/codegen/base/ContributionType.java
deleted file mode 100644
index c046daa..0000000
--- a/java/dagger/internal/codegen/base/ContributionType.java
+++ /dev/null
@@ -1,68 +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.base;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-
-import dagger.multibindings.ElementsIntoSet;
-import dagger.multibindings.IntoMap;
-import dagger.multibindings.IntoSet;
-import javax.lang.model.element.Element;
-
-/** Whether a binding or declaration is for a unique contribution or a map or set multibinding. */
-public enum ContributionType {
-  /** Represents map bindings. */
-  MAP,
-  /** Represents set bindings. */
-  SET,
-  /** Represents set values bindings. */
-  SET_VALUES,
-  /** Represents a valid non-collection binding. */
-  UNIQUE,
-  ;
-
-  /** An object that is associated with a {@link ContributionType}. */
-  public interface HasContributionType {
-
-    /** The contribution type of this object. */
-    ContributionType contributionType();
-  }
-
-  /** {@code true} if this is for a multibinding. */
-  public boolean isMultibinding() {
-    return !this.equals(UNIQUE);
-  }
-
-  /**
-   * The contribution type from a binding element's annotations. Presumes a well-formed binding
-   * element (at most one of @IntoSet, @IntoMap, @ElementsIntoSet and @Provides.type). {@link
-   * dagger.internal.codegen.validation.BindingMethodValidator} and {@link
-   * dagger.internal.codegen.validation.BindsInstanceProcessingStep} validate correctness on their
-   * own.
-   */
-  public static ContributionType fromBindingElement(Element element) {
-    // TODO(bcorso): Replace these class references with ClassName.
-    if (isAnnotationPresent(element, IntoMap.class)) {
-      return ContributionType.MAP;
-    } else if (isAnnotationPresent(element, IntoSet.class)) {
-      return ContributionType.SET;
-    } else if (isAnnotationPresent(element, ElementsIntoSet.class)) {
-      return ContributionType.SET_VALUES;
-    }
-    return ContributionType.UNIQUE;
-  }
-}
diff --git a/java/dagger/internal/codegen/base/DiagnosticFormatting.java b/java/dagger/internal/codegen/base/DiagnosticFormatting.java
deleted file mode 100644
index 93e445c..0000000
--- a/java/dagger/internal/codegen/base/DiagnosticFormatting.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2017 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.base;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Utility methods for formatting diagnostics to the {@link javax.annotation.processing.Messager}.
- */
-public final class DiagnosticFormatting {
-
-  /**
-   * A regular expression to match a small list of specific packages deemed to be unhelpful to
-   * display in fully qualified types in error messages.
-   *
-   * <p>Note: This should never be applied to messages themselves.
-   */
-  private static final Pattern COMMON_PACKAGE_PATTERN =
-      Pattern.compile(
-          "(?:^|[^.a-z_])" // What we want to match on but not capture.
-              + "((?:" // Start a group with a non-capturing or part
-              + "java[.]lang"
-              + "|java[.]util"
-              + "|javax[.]inject"
-              + "|dagger"
-              + "|dagger[.]multibindings"
-              + "|com[.]google[.]common[.]base"
-              + "|com[.]google[.]common[.]collect"
-              + ")[.])" // Always end with a literal .
-              + "[A-Z]"); // What we want to match on but not capture.
-
-  /**
-   * A method to strip out common packages and a few rare type prefixes from types' string
-   * representation before being used in error messages.
-   *
-   * <p>This type assumes a String value that is a valid fully qualified (and possibly
-   * parameterized) type, and should NOT be used with arbitrary text, especially prose error
-   * messages.
-   *
-   * <p>TODO(user): Tighten these to take type representations (mirrors and elements) to avoid
-   * accidental mis-use by running errors through this method.
-   */
-  public static String stripCommonTypePrefixes(String type) {
-    // Do regex magic to remove common packages we care to shorten.
-    Matcher matcher = COMMON_PACKAGE_PATTERN.matcher(type);
-    StringBuilder result = new StringBuilder();
-    int index = 0;
-    while (matcher.find()) {
-      result.append(type.subSequence(index, matcher.start(1)));
-      index = matcher.end(1); // Skip the matched pattern content.
-    }
-    result.append(type.subSequence(index, type.length()));
-    return result.toString();
-  }
-
-  private DiagnosticFormatting() {}
-}
diff --git a/java/dagger/internal/codegen/base/ElementFormatter.java b/java/dagger/internal/codegen/base/ElementFormatter.java
deleted file mode 100644
index f85fbfd..0000000
--- a/java/dagger/internal/codegen/base/ElementFormatter.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2013 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.base;
-
-import static com.google.auto.common.MoreElements.asExecutable;
-import static java.util.stream.Collectors.joining;
-
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementVisitor;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.util.ElementKindVisitor8;
-
-/**
- * Formats elements into a useful string representation.
- *
- * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
- *
- * <p>Parameters are given with their enclosing executable, with other parameters elided.
- */
-public final class ElementFormatter extends Formatter<Element> {
-  @Inject
-  ElementFormatter() {}
-
-  @Override
-  public String format(Element element) {
-    return elementToString(element);
-  }
-
-  /**
-   * Returns a useful string form for an element.
-   *
-   * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
-   *
-   * <p>Parameters are given with their enclosing executable, with other parameters elided.
-   */
-  public static String elementToString(Element element) {
-    return element.accept(ELEMENT_TO_STRING, null);
-  }
-
-  private static final ElementVisitor<String, Void> ELEMENT_TO_STRING =
-      new ElementKindVisitor8<String, Void>() {
-        @Override
-        public String visitExecutable(ExecutableElement executableElement, Void aVoid) {
-          return enclosingTypeAndMemberName(executableElement)
-              .append(
-                  executableElement.getParameters().stream()
-                      .map(parameter -> parameter.asType().toString())
-                      .collect(joining(", ", "(", ")")))
-              .toString();
-        }
-
-        @Override
-        public String visitVariableAsParameter(VariableElement parameter, Void aVoid) {
-          ExecutableElement methodOrConstructor = asExecutable(parameter.getEnclosingElement());
-          return enclosingTypeAndMemberName(methodOrConstructor)
-              .append('(')
-              .append(
-                  formatArgumentInList(
-                      methodOrConstructor.getParameters().indexOf(parameter),
-                      methodOrConstructor.getParameters().size(),
-                      parameter.getSimpleName()))
-              .append(')')
-              .toString();
-        }
-
-        @Override
-        public String visitVariableAsField(VariableElement field, Void aVoid) {
-          return enclosingTypeAndMemberName(field).toString();
-        }
-
-        @Override
-        public String visitType(TypeElement type, Void aVoid) {
-          return type.getQualifiedName().toString();
-        }
-
-        @Override
-        protected String defaultAction(Element element, Void aVoid) {
-          throw new UnsupportedOperationException(
-              "Can't determine string for " + element.getKind() + " element " + element);
-        }
-
-        private StringBuilder enclosingTypeAndMemberName(Element element) {
-          StringBuilder name = new StringBuilder(element.getEnclosingElement().accept(this, null));
-          if (!element.getSimpleName().contentEquals("<init>")) {
-            name.append('.').append(element.getSimpleName());
-          }
-          return name;
-        }
-      };
-}
diff --git a/java/dagger/internal/codegen/base/Formatter.java b/java/dagger/internal/codegen/base/Formatter.java
deleted file mode 100644
index c5e2357..0000000
--- a/java/dagger/internal/codegen/base/Formatter.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2014 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.base;
-
-import static com.google.common.base.Preconditions.checkElementIndex;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-
-/**
- * A formatter which transforms an instance of a particular type into a string
- * representation.
- *
- * @param <T> the type of the object to be transformed.
- */
-public abstract class Formatter<T> implements Function<T, String> {
-
-  public static final String INDENT = "    ";
-  public static final String DOUBLE_INDENT = INDENT + INDENT;
-  private static final int LIST_LIMIT = 10;
-
-  /**
-   * Performs the transformation of an object into a string representation.
-   */
-  public abstract String format(T object);
-
-  /**
-   * Performs the transformation of an object into a string representation in conformity with the
-   * {@link Function}{@code <T, String>} contract, delegating to {@link #format(Object)}.
-   *
-   * @deprecated Call {@link #format(Object)} instead. This method exists to make formatters easy to
-   *     use when functions are required, but shouldn't be called directly.
-   */
-  @SuppressWarnings("javadoc")
-  @Deprecated
-  @Override
-  public final String apply(T object) {
-    return format(object);
-  }
-
-  /** Formats {@code items}, one per line. Stops after {@value #LIST_LIMIT} items. */
-  public void formatIndentedList(
-      StringBuilder builder, Iterable<? extends T> items, int indentLevel) {
-    for (T item : Iterables.limit(items, LIST_LIMIT)) {
-      String formatted = format(item);
-      if (formatted.isEmpty()) {
-        continue;
-      }
-      builder.append('\n');
-      appendIndent(builder, indentLevel);
-      builder.append(formatted);
-    }
-    int numberOfOtherItems = Iterables.size(items) - LIST_LIMIT;
-    if (numberOfOtherItems > 0) {
-      builder.append('\n');
-      appendIndent(builder, indentLevel);
-      builder.append("and ").append(numberOfOtherItems).append(" other");
-    }
-    if (numberOfOtherItems > 1) {
-      builder.append('s');
-    }
-  }
-
-  private void appendIndent(StringBuilder builder, int indentLevel) {
-    for (int i = 0; i < indentLevel; i++) {
-      builder.append(INDENT);
-    }
-  }
-
-  public static String formatArgumentInList(int index, int size, CharSequence name) {
-    checkElementIndex(index, size);
-    StringBuilder builder = new StringBuilder();
-    if (index > 0) {
-      builder.append("…, ");
-    }
-    builder.append(name);
-    if (index < size - 1) {
-      builder.append(", …");
-    }
-    return builder.toString();
-  }
-}
diff --git a/java/dagger/internal/codegen/base/FrameworkTypes.java b/java/dagger/internal/codegen/base/FrameworkTypes.java
deleted file mode 100644
index 4cd54a3..0000000
--- a/java/dagger/internal/codegen/base/FrameworkTypes.java
+++ /dev/null
@@ -1,66 +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.base;
-
-import static com.google.auto.common.MoreTypes.isType;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSet;
-import dagger.Lazy;
-import dagger.MembersInjector;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import java.util.Set;
-import javax.inject.Provider;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A collection of utility methods for dealing with Dagger framework types. A framework type is any
- * type that the framework itself defines.
- */
-public final class FrameworkTypes {
-  private static final ImmutableSet<Class<?>> PROVISION_TYPES =
-      ImmutableSet.of(Provider.class, Lazy.class, MembersInjector.class);
-
-  // NOTE(beder): ListenableFuture is not considered a producer framework type because it is not
-  // defined by the framework, so we can't treat it specially in ordinary Dagger.
-  private static final ImmutableSet<Class<?>> PRODUCTION_TYPES =
-      ImmutableSet.of(Produced.class, Producer.class);
-
-  /** Returns true if the type represents a producer-related framework type. */
-  public static boolean isProducerType(TypeMirror type) {
-    return isType(type) && typeIsOneOf(PRODUCTION_TYPES, type);
-  }
-
-  /** Returns true if the type represents a framework type. */
-  public static boolean isFrameworkType(TypeMirror type) {
-    return isType(type)
-        && (typeIsOneOf(PROVISION_TYPES, type)
-            || typeIsOneOf(PRODUCTION_TYPES, type));
-  }
-
-  private static boolean typeIsOneOf(Set<Class<?>> classes, TypeMirror type) {
-    for (Class<?> clazz : classes) {
-      if (MoreTypes.isTypeOf(clazz, type)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private FrameworkTypes() {}
-}
diff --git a/java/dagger/internal/codegen/base/Keys.java b/java/dagger/internal/codegen/base/Keys.java
deleted file mode 100644
index a25f996..0000000
--- a/java/dagger/internal/codegen/base/Keys.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2017 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.base;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleTypeVisitor6;
-
-/** Utility methods related to {@link Key}s. */
-public final class Keys {
-  public static boolean isValidMembersInjectionKey(Key key) {
-    return !key.qualifier().isPresent()
-        && !key.multibindingContributionIdentifier().isPresent()
-        && key.type().getKind().equals(TypeKind.DECLARED);
-  }
-
-  /**
-   * Returns {@code true} if this is valid as an implicit key (that is, if it's valid for a
-   * just-in-time binding by discovering an {@code @Inject} constructor).
-   */
-  public static boolean isValidImplicitProvisionKey(Key key, DaggerTypes types) {
-    return isValidImplicitProvisionKey(key.qualifier(), key.type(), types);
-  }
-
-  /**
-   * Returns {@code true} if a key with {@code qualifier} and {@code type} is valid as an implicit
-   * key (that is, if it's valid for a just-in-time binding by discovering an {@code @Inject}
-   * constructor).
-   */
-  public static boolean isValidImplicitProvisionKey(
-      Optional<? extends AnnotationMirror> qualifier, TypeMirror type, final DaggerTypes types) {
-    // Qualifiers disqualify implicit provisioning.
-    if (qualifier.isPresent()) {
-      return false;
-    }
-
-    return type.accept(
-        new SimpleTypeVisitor6<Boolean, Void>(false) {
-          @Override
-          public Boolean visitDeclared(DeclaredType type, Void ignored) {
-            // Non-classes or abstract classes aren't allowed.
-            TypeElement element = MoreElements.asType(type.asElement());
-            if (!element.getKind().equals(ElementKind.CLASS)
-                || element.getModifiers().contains(Modifier.ABSTRACT)) {
-              return false;
-            }
-
-            // If the key has type arguments, validate that each type argument is declared.
-            // Otherwise the type argument may be a wildcard (or other type), and we can't
-            // resolve that to actual types.
-            for (TypeMirror arg : type.getTypeArguments()) {
-              if (arg.getKind() != TypeKind.DECLARED) {
-                return false;
-              }
-            }
-
-            // Also validate that the key is not the erasure of a generic type.
-            // If it is, that means the user referred to Foo<T> as just 'Foo',
-            // which we don't allow.  (This is a judgement call -- we *could*
-            // allow it and instantiate the type bounds... but we don't.)
-            return MoreTypes.asDeclared(element.asType()).getTypeArguments().isEmpty()
-                || !types.isSameType(types.erasure(element.asType()), type);
-          }
-        },
-        null);
-  }
-}
diff --git a/java/dagger/internal/codegen/base/MapKeyAccessibility.java b/java/dagger/internal/codegen/base/MapKeyAccessibility.java
deleted file mode 100644
index 93c265a..0000000
--- a/java/dagger/internal/codegen/base/MapKeyAccessibility.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 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.base;
-
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-
-import dagger.internal.codegen.langmodel.Accessibility;
-import java.util.Collection;
-import java.util.List;
-import java.util.function.Predicate;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleAnnotationValueVisitor8;
-
-/** Utility class for checking the visibility of an annotation.  */
-public final class MapKeyAccessibility extends SimpleAnnotationValueVisitor8<Boolean, Void> {
-  private final Predicate<TypeMirror> accessibilityChecker;
-
-  private MapKeyAccessibility(Predicate<TypeMirror> accessibilityChecker) {
-    this.accessibilityChecker = accessibilityChecker;
-  }
-
-  @Override
-  public Boolean visitAnnotation(AnnotationMirror annotation, Void aVoid) {
-    // The annotation type is not checked, as the generated code will refer to the @AutoAnnotation
-    // generated type which is always public
-    return visitValues(annotation.getElementValues().values());
-  }
-
-  @Override
-  public Boolean visitArray(List<? extends AnnotationValue> values, Void aVoid) {
-    return visitValues(values);
-  }
-
-  private boolean visitValues(Collection<? extends AnnotationValue> values) {
-    return values.stream().allMatch(value -> value.accept(this, null));
-  }
-
-  @Override
-  public Boolean visitEnumConstant(VariableElement enumConstant, Void aVoid) {
-    return accessibilityChecker.test(enumConstant.getEnclosingElement().asType());
-  }
-
-  @Override
-  public Boolean visitType(TypeMirror type, Void aVoid) {
-    return accessibilityChecker.test(type);
-  }
-
-  @Override
-  protected Boolean defaultAction(Object o, Void aVoid) {
-    return true;
-  }
-
-  public static boolean isMapKeyAccessibleFrom(
-      AnnotationMirror annotation, String accessingPackage) {
-    return new MapKeyAccessibility(type -> isTypeAccessibleFrom(type, accessingPackage))
-        .visitAnnotation(annotation, null);
-  }
-
-  public static boolean isMapKeyPubliclyAccessible(AnnotationMirror annotation) {
-    return new MapKeyAccessibility(Accessibility::isTypePubliclyAccessible)
-        .visitAnnotation(annotation, null);
-  }
-}
diff --git a/java/dagger/internal/codegen/base/MapType.java b/java/dagger/internal/codegen/base/MapType.java
deleted file mode 100644
index 4e2307a..0000000
--- a/java/dagger/internal/codegen/base/MapType.java
+++ /dev/null
@@ -1,158 +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.base;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Equivalence;
-import dagger.model.Key;
-import java.util.Map;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * Information about a {@link Map} {@link TypeMirror}.
- */
-@AutoValue
-public abstract class MapType {
-  /**
-   * The map type itself, wrapped using {@link MoreTypes#equivalence()}. Use
-   * {@link #declaredMapType()} instead.
-   */
-  protected abstract Equivalence.Wrapper<DeclaredType> wrappedDeclaredMapType();
-
-  /**
-   * The map type itself.
-   */
-  private DeclaredType declaredMapType() {
-    return wrappedDeclaredMapType().get();
-  }
-
-  /**
-   * {@code true} if the map type is the raw {@link Map} type.
-   */
-  public boolean isRawType() {
-    return declaredMapType().getTypeArguments().isEmpty();
-  }
-
-  /**
-   * The map key type.
-   *
-   * @throws IllegalStateException if {@link #isRawType()} is true.
-   */
-  public TypeMirror keyType() {
-    checkState(!isRawType());
-    return declaredMapType().getTypeArguments().get(0);
-  }
-
-  /**
-   * The map value type.
-   *
-   * @throws IllegalStateException if {@link #isRawType()} is true.
-   */
-  public TypeMirror valueType() {
-    checkState(!isRawType());
-    return declaredMapType().getTypeArguments().get(1);
-  }
-
-  /**
-   * {@code true} if {@link #valueType()} is a {@code clazz}.
-   *
-   * @throws IllegalStateException if {@link #isRawType()} is true.
-   */
-  public boolean valuesAreTypeOf(Class<?> clazz) {
-    return MoreTypes.isType(valueType()) && MoreTypes.isTypeOf(clazz, valueType());
-  }
-
-  /**
-   * Returns {@code true} if the {@linkplain #valueType() value type} of the {@link Map} is a
-   * {@linkplain FrameworkTypes#isFrameworkType(TypeMirror) framework type}.
-   */
-  public boolean valuesAreFrameworkType() {
-    return FrameworkTypes.isFrameworkType(valueType());
-  }
-
-  /**
-   * {@code V} if {@link #valueType()} is a framework type like {@code Provider<V>} or {@code
-   * Producer<V>}.
-   *
-   * @throws IllegalStateException if {@link #isRawType()} is true or {@link #valueType()} is not a
-   *     framework type
-   */
-  public TypeMirror unwrappedFrameworkValueType() {
-    checkState(
-        valuesAreFrameworkType(), "called unwrappedFrameworkValueType() on %s", declaredMapType());
-    return uncheckedUnwrappedValueType();
-  }
-
-  /**
-   * {@code V} if {@link #valueType()} is a {@code WrappingClass<V>}.
-   *
-   * @throws IllegalStateException if {@link #isRawType()} is true or {@link #valueType()} is not a
-   *     {@code WrappingClass<V>}
-   * @throws IllegalArgumentException if {@code wrappingClass} does not have exactly one type
-   *     parameter
-   */
-  public TypeMirror unwrappedValueType(Class<?> wrappingClass) {
-    checkArgument(
-        wrappingClass.getTypeParameters().length == 1,
-        "%s must have exactly one type parameter",
-        wrappingClass);
-    checkState(valuesAreTypeOf(wrappingClass), "expected values to be %s: %s", wrappingClass, this);
-    return uncheckedUnwrappedValueType();
-  }
-
-  private TypeMirror uncheckedUnwrappedValueType() {
-    return MoreTypes.asDeclared(valueType()).getTypeArguments().get(0);
-  }
-
-  /**
-   * {@code true} if {@code type} is a {@link Map} type.
-   */
-  public static boolean isMap(TypeMirror type) {
-    return MoreTypes.isType(type) && MoreTypes.isTypeOf(Map.class, type);
-  }
-
-  /**
-   * {@code true} if {@code key.type()} is a {@link Map} type.
-   */
-  public static boolean isMap(Key key) {
-    return isMap(key.type());
-  }
-
-  /**
-   * Returns a {@link MapType} for {@code type}.
-   *
-   * @throws IllegalArgumentException if {@code type} is not a {@link Map} type
-   */
-  public static MapType from(TypeMirror type) {
-    checkArgument(isMap(type), "%s is not a Map", type);
-    return new AutoValue_MapType(MoreTypes.equivalence().wrap(MoreTypes.asDeclared(type)));
-  }
-
-  /**
-   * Returns a {@link MapType} for {@code key}'s {@link Key#type() type}.
-   *
-   * @throws IllegalArgumentException if {@code key.type()} is not a {@link Map} type
-   */
-  public static MapType from(Key key) {
-    return from(key.type());
-  }
-}
diff --git a/java/dagger/internal/codegen/base/ModuleAnnotation.java b/java/dagger/internal/codegen/base/ModuleAnnotation.java
deleted file mode 100644
index 1688736..0000000
--- a/java/dagger/internal/codegen/base/ModuleAnnotation.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2019 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.base;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.base.MoreAnnotationValues.asAnnotationValues;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
-
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import dagger.Module;
-import dagger.producers.ProducerModule;
-import java.lang.annotation.Annotation;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.TypeElement;
-
-/** A {@code @Module} or {@code @ProducerModule} annotation. */
-@AutoValue
-public abstract class ModuleAnnotation {
-  private static final ImmutableSet<Class<? extends Annotation>> MODULE_ANNOTATIONS =
-      ImmutableSet.of(Module.class, ProducerModule.class);
-
-  /** The annotation itself. */
-  // This does not use AnnotationMirrors.equivalence() because we want the actual annotation
-  // instance.
-  public abstract AnnotationMirror annotation();
-
-  /** The simple name of the annotation. */
-  public String annotationName() {
-    return annotation().getAnnotationType().asElement().getSimpleName().toString();
-  }
-
-  /**
-   * The types specified in the {@code includes} attribute.
-   *
-   * @throws IllegalArgumentException if any of the values are error types
-   */
-  @Memoized
-  public ImmutableList<TypeElement> includes() {
-    return includesAsAnnotationValues().stream()
-        .map(MoreAnnotationValues::asType)
-        .map(MoreTypes::asTypeElement)
-        .collect(toImmutableList());
-  }
-
-  /** The values specified in the {@code includes} attribute. */
-  @Memoized
-  public ImmutableList<AnnotationValue> includesAsAnnotationValues() {
-    return asAnnotationValues(getAnnotationValue(annotation(), "includes"));
-  }
-
-  /**
-   * The types specified in the {@code subcomponents} attribute.
-   *
-   * @throws IllegalArgumentException if any of the values are error types
-   */
-  @Memoized
-  public ImmutableList<TypeElement> subcomponents() {
-    return subcomponentsAsAnnotationValues().stream()
-        .map(MoreAnnotationValues::asType)
-        .map(MoreTypes::asTypeElement)
-        .collect(toImmutableList());
-  }
-
-  /** The values specified in the {@code subcomponents} attribute. */
-  @Memoized
-  public ImmutableList<AnnotationValue> subcomponentsAsAnnotationValues() {
-    return asAnnotationValues(getAnnotationValue(annotation(), "subcomponents"));
-  }
-
-  /** Returns {@code true} if the argument is a {@code @Module} or {@code @ProducerModule}. */
-  public static boolean isModuleAnnotation(AnnotationMirror annotation) {
-    return MODULE_ANNOTATIONS.stream()
-        .map(Class::getCanonicalName)
-        .anyMatch(asTypeElement(annotation.getAnnotationType()).getQualifiedName()::contentEquals);
-  }
-
-  /** The module annotation types. */
-  public static ImmutableSet<Class<? extends Annotation>> moduleAnnotations() {
-    return MODULE_ANNOTATIONS;
-  }
-
-  /**
-   * Creates an object that represents a {@code @Module} or {@code @ProducerModule}.
-   *
-   * @throws IllegalArgumentException if {@link #isModuleAnnotation(AnnotationMirror)} returns
-   *     {@code false}
-   */
-  public static ModuleAnnotation moduleAnnotation(AnnotationMirror annotation) {
-    checkArgument(
-        isModuleAnnotation(annotation),
-        "%s is not a Module or ProducerModule annotation",
-        annotation);
-    return new AutoValue_ModuleAnnotation(annotation);
-  }
-
-  /**
-   * Returns an object representing the {@code @Module} or {@code @ProducerModule} annotation if one
-   * annotates {@code typeElement}.
-   */
-  public static Optional<ModuleAnnotation> moduleAnnotation(TypeElement typeElement) {
-    return getAnyAnnotation(typeElement, Module.class, ProducerModule.class)
-        .map(ModuleAnnotation::moduleAnnotation);
-  }
-}
diff --git a/java/dagger/internal/codegen/base/MoreAnnotationMirrors.java b/java/dagger/internal/codegen/base/MoreAnnotationMirrors.java
deleted file mode 100644
index 234ecc1..0000000
--- a/java/dagger/internal/codegen/base/MoreAnnotationMirrors.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2016 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.base;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
-import static dagger.internal.codegen.base.MoreAnnotationValues.asAnnotationValues;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-
-import com.google.auto.common.AnnotationMirrors;
-import com.google.common.base.Equivalence;
-import com.google.common.collect.ImmutableList;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Name;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A utility class for working with {@link AnnotationMirror} instances, similar to {@link
- * AnnotationMirrors}.
- */
-public final class MoreAnnotationMirrors {
-
-  private MoreAnnotationMirrors() {}
-
-  /**
-   * Wraps an {@link Optional} of a type in an {@code Optional} of a {@link Equivalence.Wrapper} for
-   * that type.
-   */
-  public static Optional<Equivalence.Wrapper<AnnotationMirror>> wrapOptionalInEquivalence(
-      Optional<AnnotationMirror> optional) {
-    return optional.map(AnnotationMirrors.equivalence()::wrap);
-  }
-
-  /**
-   * Unwraps an {@link Optional} of a {@link Equivalence.Wrapper} into an {@code Optional} of the
-   * underlying type.
-   */
-  public static Optional<AnnotationMirror> unwrapOptionalEquivalence(
-      Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedOptional) {
-    return wrappedOptional.map(Equivalence.Wrapper::get);
-  }
-
-  public static Name simpleName(AnnotationMirror annotationMirror) {
-    return annotationMirror.getAnnotationType().asElement().getSimpleName();
-  }
-
-  /**
-   * Returns the list of types that is the value named {@code name} from {@code annotationMirror}.
-   *
-   * @throws IllegalArgumentException unless that member represents an array of types
-   */
-  public static ImmutableList<TypeMirror> getTypeListValue(
-      AnnotationMirror annotationMirror, String name) {
-    return asAnnotationValues(getAnnotationValue(annotationMirror, name))
-        .stream()
-        .map(MoreAnnotationValues::asType)
-        .collect(toImmutableList());
-  }
-}
diff --git a/java/dagger/internal/codegen/base/MoreAnnotationValues.java b/java/dagger/internal/codegen/base/MoreAnnotationValues.java
deleted file mode 100644
index 1ee50da..0000000
--- a/java/dagger/internal/codegen/base/MoreAnnotationValues.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2013 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.base;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
-
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.AnnotationValueVisitor;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleAnnotationValueVisitor8;
-
-/** Utility methods for working with {@link AnnotationValue} instances. */
-public final class MoreAnnotationValues {
-  /**
-   * Returns the list of values represented by an array annotation value.
-   *
-   * @throws IllegalArgumentException unless {@code annotationValue} represents an array
-   */
-  public static ImmutableList<AnnotationValue> asAnnotationValues(AnnotationValue annotationValue) {
-    return annotationValue.accept(AS_ANNOTATION_VALUES, null);
-  }
-
-  private static final AnnotationValueVisitor<ImmutableList<AnnotationValue>, String>
-      AS_ANNOTATION_VALUES =
-          new SimpleAnnotationValueVisitor8<ImmutableList<AnnotationValue>, String>() {
-            @Override
-            public ImmutableList<AnnotationValue> visitArray(
-                List<? extends AnnotationValue> vals, String elementName) {
-              return ImmutableList.copyOf(vals);
-            }
-
-            @Override
-            protected ImmutableList<AnnotationValue> defaultAction(Object o, String elementName) {
-              throw new IllegalArgumentException(elementName + " is not an array: " + o);
-            }
-          };
-
-  /**
-   * Returns the type represented by an annotation value.
-   *
-   * @throws IllegalArgumentException unless {@code annotationValue} represents a single type
-   */
-  public static TypeMirror asType(AnnotationValue annotationValue) {
-    return AS_TYPE.visit(annotationValue);
-  }
-
-  private static final AnnotationValueVisitor<TypeMirror, Void> AS_TYPE =
-      new SimpleAnnotationValueVisitor8<TypeMirror, Void>() {
-        @Override
-        public TypeMirror visitType(TypeMirror t, Void p) {
-          return t;
-        }
-
-        @Override
-        protected TypeMirror defaultAction(Object o, Void p) {
-          throw new TypeNotPresentException(o.toString(), null);
-        }
-      };
-
-  /** Returns the int value of an annotation */
-  public static int getIntValue(AnnotationMirror annotation, String valueName) {
-    return (int) getAnnotationValue(annotation, valueName).getValue();
-  }
-
-  /** Returns an optional int value of an annotation if the value name is present */
-  public static Optional<Integer> getOptionalIntValue(
-      AnnotationMirror annotation, String valueName) {
-    return isValuePresent(annotation, valueName)
-        ? Optional.of(getIntValue(annotation, valueName))
-        : Optional.empty();
-  }
-
-  /** Returns the String value of an annotation */
-  public static String getStringValue(AnnotationMirror annotation, String valueName) {
-    return (String) getAnnotationValue(annotation, valueName).getValue();
-  }
-
-  /** Returns an optional String value of an annotation if the value name is present */
-  public static Optional<String> getOptionalStringValue(
-      AnnotationMirror annotation, String valueName) {
-    return isValuePresent(annotation, valueName)
-        ? Optional.of(getStringValue(annotation, valueName))
-        : Optional.empty();
-  }
-
-  /** Returns the int array value of an annotation */
-  public static int[] getIntArrayValue(AnnotationMirror annotation, String valueName) {
-    return asAnnotationValues(getAnnotationValue(annotation, valueName)).stream()
-        .mapToInt(it -> (int) it.getValue())
-        .toArray();
-  }
-
-  /** Returns the String array value of an annotation */
-  public static String[] getStringArrayValue(AnnotationMirror annotation, String valueName) {
-    return asAnnotationValues(getAnnotationValue(annotation, valueName)).stream()
-        .map(it -> (String) it.getValue())
-        .toArray(String[]::new);
-  }
-
-  private static boolean isValuePresent(AnnotationMirror annotation, String valueName) {
-    return getAnnotationValuesWithDefaults(annotation).keySet().stream()
-        .anyMatch(member -> member.getSimpleName().contentEquals(valueName));
-  }
-
-  private MoreAnnotationValues() {}
-}
diff --git a/java/dagger/internal/codegen/base/MultibindingAnnotations.java b/java/dagger/internal/codegen/base/MultibindingAnnotations.java
deleted file mode 100644
index 424f92a..0000000
--- a/java/dagger/internal/codegen/base/MultibindingAnnotations.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 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.base;
-
-import static dagger.internal.codegen.langmodel.DaggerElements.getAllAnnotations;
-
-import com.google.common.collect.ImmutableSet;
-import dagger.multibindings.ElementsIntoSet;
-import dagger.multibindings.IntoMap;
-import dagger.multibindings.IntoSet;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-
-/**
- * Utility methods related to processing {@link IntoSet}, {@link ElementsIntoSet}, and {@link
- * IntoMap}.
- */
-public final class MultibindingAnnotations {
-  public static ImmutableSet<AnnotationMirror> forElement(Element method) {
-    return getAllAnnotations(method, IntoSet.class, ElementsIntoSet.class, IntoMap.class);
-  }
-}
diff --git a/java/dagger/internal/codegen/base/OptionalType.java b/java/dagger/internal/codegen/base/OptionalType.java
deleted file mode 100644
index 1505682..0000000
--- a/java/dagger/internal/codegen/base/OptionalType.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2016 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.base;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Equivalence;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import dagger.model.Key;
-import java.util.Optional;
-import javax.lang.model.element.Name;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVisitor;
-import javax.lang.model.util.SimpleTypeVisitor8;
-
-/**
- * Information about an {@code Optional} {@link TypeMirror}.
- *
- * <p>{@link com.google.common.base.Optional} and {@link java.util.Optional} are supported.
- */
-@AutoValue
-public abstract class OptionalType {
-
-  /** A variant of {@code Optional}. */
-  public enum OptionalKind {
-    /** {@link com.google.common.base.Optional}. */
-    GUAVA_OPTIONAL(com.google.common.base.Optional.class, "absent"),
-
-    /** {@link java.util.Optional}. */
-    JDK_OPTIONAL(java.util.Optional.class, "empty"),
-    ;
-
-    private final Class<?> clazz;
-    private final String absentFactoryMethodName;
-
-    OptionalKind(Class<?> clazz, String absentFactoryMethodName) {
-      this.clazz = clazz;
-      this.absentFactoryMethodName = absentFactoryMethodName;
-    }
-
-    /** Returns {@code valueType} wrapped in the correct class. */
-    public ParameterizedTypeName of(TypeName valueType) {
-      return ParameterizedTypeName.get(ClassName.get(clazz), valueType);
-    }
-
-    /** Returns an expression for the absent/empty value. */
-    public CodeBlock absentValueExpression() {
-      return CodeBlock.of("$T.$L()", clazz, absentFactoryMethodName);
-    }
-
-    /**
-     * Returns an expression for the absent/empty value, parameterized with {@link #valueType()}.
-     */
-    public CodeBlock parameterizedAbsentValueExpression(OptionalType optionalType) {
-      return CodeBlock.of("$T.<$T>$L()", clazz, optionalType.valueType(), absentFactoryMethodName);
-    }
-
-    /** Returns an expression for the present {@code value}. */
-    public CodeBlock presentExpression(CodeBlock value) {
-      return CodeBlock.of("$T.of($L)", clazz, value);
-    }
-
-    /**
-     * Returns an expression for the present {@code value}, returning {@code Optional<Object>} no
-     * matter what type the value is.
-     */
-    public CodeBlock presentObjectExpression(CodeBlock value) {
-      return CodeBlock.of("$T.<$T>of($L)", clazz, Object.class, value);
-    }
-  }
-
-  private static final TypeVisitor<Optional<OptionalKind>, Void> OPTIONAL_KIND =
-      new SimpleTypeVisitor8<Optional<OptionalKind>, Void>(Optional.empty()) {
-        @Override
-        public Optional<OptionalKind> visitDeclared(DeclaredType t, Void p) {
-          for (OptionalKind optionalKind : OptionalKind.values()) {
-            Name qualifiedName = MoreElements.asType(t.asElement()).getQualifiedName();
-            if (qualifiedName.contentEquals(optionalKind.clazz.getCanonicalName())) {
-              return Optional.of(optionalKind);
-            }
-          }
-          return Optional.empty();
-        }
-      };
-
-  /**
-   * The optional type itself, wrapped using {@link MoreTypes#equivalence()}.
-   *
-   * @deprecated Use {@link #declaredOptionalType()} instead.
-   */
-  @Deprecated
-  protected abstract Equivalence.Wrapper<DeclaredType> wrappedDeclaredOptionalType();
-
-  /** The optional type itself. */
-  @SuppressWarnings("deprecation")
-  private DeclaredType declaredOptionalType() {
-    return wrappedDeclaredOptionalType().get();
-  }
-
-  /** Which {@code Optional} type is used. */
-  public OptionalKind kind() {
-    return declaredOptionalType().accept(OPTIONAL_KIND, null).get();
-  }
-
-  /** The value type. */
-  public TypeMirror valueType() {
-    return declaredOptionalType().getTypeArguments().get(0);
-  }
-
-  /** Returns {@code true} if {@code type} is an {@code Optional} type. */
-  private static boolean isOptional(TypeMirror type) {
-    return type.accept(OPTIONAL_KIND, null).isPresent();
-  }
-
-  /** Returns {@code true} if {@code key.type()} is an {@code Optional} type. */
-  public static boolean isOptional(Key key) {
-    return isOptional(key.type());
-  }
-
-  /**
-   * Returns a {@link OptionalType} for {@code type}.
-   *
-   * @throws IllegalArgumentException if {@code type} is not an {@code Optional} type
-   */
-  public static OptionalType from(TypeMirror type) {
-    checkArgument(isOptional(type), "%s must be an Optional", type);
-    return new AutoValue_OptionalType(MoreTypes.equivalence().wrap(MoreTypes.asDeclared(type)));
-  }
-
-  /**
-   * Returns a {@link OptionalType} for {@code key}'s {@link Key#type() type}.
-   *
-   * @throws IllegalArgumentException if {@code key.type()} is not an {@code Optional} type
-   */
-  public static OptionalType from(Key key) {
-    return from(key.type());
-  }
-}
diff --git a/java/dagger/internal/codegen/base/RequestKinds.java b/java/dagger/internal/codegen/base/RequestKinds.java
deleted file mode 100644
index 95d5ef4..0000000
--- a/java/dagger/internal/codegen/base/RequestKinds.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2014 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.base;
-
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.auto.common.MoreTypes.isType;
-import static com.google.auto.common.MoreTypes.isTypeOf;
-import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.javapoet.TypeNames.lazyOf;
-import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.javapoet.TypeNames.producedOf;
-import static dagger.internal.codegen.javapoet.TypeNames.producerOf;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
-import static dagger.internal.codegen.langmodel.DaggerTypes.checkTypePresent;
-import static dagger.model.RequestKind.LAZY;
-import static dagger.model.RequestKind.PRODUCED;
-import static dagger.model.RequestKind.PRODUCER;
-import static dagger.model.RequestKind.PROVIDER;
-import static dagger.model.RequestKind.PROVIDER_OF_LAZY;
-import static javax.lang.model.type.TypeKind.DECLARED;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.squareup.javapoet.TypeName;
-import dagger.Lazy;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.RequestKind;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import javax.inject.Provider;
-import javax.lang.model.type.TypeMirror;
-
-/** Utility methods for {@link RequestKind}s. */
-public final class RequestKinds {
-
-  /** Returns the type of a request of this kind for a key with a given type. */
-  public static TypeMirror requestType(
-      RequestKind requestKind, TypeMirror type, DaggerTypes types) {
-    switch (requestKind) {
-      case INSTANCE:
-        return type;
-
-      case PROVIDER_OF_LAZY:
-        return types.wrapType(requestType(LAZY, type, types), Provider.class);
-
-      case FUTURE:
-        return types.wrapType(type, ListenableFuture.class);
-
-      default:
-        return types.wrapType(type, frameworkClass(requestKind));
-    }
-  }
-
-  /** Returns the type of a request of this kind for a key with a given type. */
-  public static TypeName requestTypeName(RequestKind requestKind, TypeName keyType) {
-    switch (requestKind) {
-      case INSTANCE:
-        return keyType;
-
-      case PROVIDER:
-        return providerOf(keyType);
-
-      case LAZY:
-        return lazyOf(keyType);
-
-      case PROVIDER_OF_LAZY:
-        return providerOf(lazyOf(keyType));
-
-      case PRODUCER:
-        return producerOf(keyType);
-
-      case PRODUCED:
-        return producedOf(keyType);
-
-      case FUTURE:
-        return listenableFutureOf(keyType);
-
-      default:
-        throw new AssertionError(requestKind);
-    }
-  }
-
-  private static final ImmutableMap<RequestKind, Class<?>> FRAMEWORK_CLASSES =
-      ImmutableMap.of(
-          PROVIDER, Provider.class,
-          LAZY, Lazy.class,
-          PRODUCER, Producer.class,
-          PRODUCED, Produced.class);
-
-  /** Returns the {@link RequestKind} that matches the wrapping types (if any) of {@code type}. */
-  public static RequestKind getRequestKind(TypeMirror type) {
-    checkTypePresent(type);
-    if (!isType(type) // TODO(b/147320669): isType check can be removed once this bug is fixed.
-            || !type.getKind().equals(DECLARED)
-            || asDeclared(type).getTypeArguments().isEmpty()) {
-      // If the type is not a declared type (i.e. class or interface) with type arguments, then we
-      // know it can't be a parameterized type of one of the framework classes, so return INSTANCE.
-      return RequestKind.INSTANCE;
-    }
-    for (RequestKind kind : FRAMEWORK_CLASSES.keySet()) {
-      if (isTypeOf(frameworkClass(kind), type)) {
-        if (kind.equals(PROVIDER) && getRequestKind(DaggerTypes.unwrapType(type)).equals(LAZY)) {
-          return PROVIDER_OF_LAZY;
-        }
-        return kind;
-      }
-    }
-    return RequestKind.INSTANCE;
-  }
-
-  /**
-   * Unwraps the framework class(es) of {@code requestKind} from {@code type}. If {@code
-   * requestKind} is {@link RequestKind#INSTANCE}, this acts as an identity function.
-   *
-   * @throws TypeNotPresentException if {@code type} is an {@link javax.lang.model.type.ErrorType},
-   *     which may mean that the type will be generated in a later round of processing
-   * @throws IllegalArgumentException if {@code type} is not wrapped with {@code requestKind}'s
-   *     framework class(es).
-   */
-  public static TypeMirror extractKeyType(TypeMirror type) {
-    return extractKeyType(getRequestKind(type), type);
-  }
-
-  private static TypeMirror extractKeyType(RequestKind requestKind, TypeMirror type) {
-    switch (requestKind) {
-      case INSTANCE:
-        return type;
-      case PROVIDER_OF_LAZY:
-        return extractKeyType(LAZY, extractKeyType(PROVIDER, type));
-      default:
-        checkArgument(isType(type));
-        return DaggerTypes.unwrapType(type);
-    }
-  }
-
-  /**
-   * A dagger- or {@code javax.inject}-defined class for {@code requestKind} that that can wrap
-   * another type but share the same {@link dagger.model.Key}.
-   *
-   * <p>For example, {@code Provider<String>} and {@code Lazy<String>} can both be requested if a
-   * key exists for {@code String}; they all share the same key.
-   *
-   * <p>This concept is not well defined and should probably be removed and inlined into the cases
-   * that need it. For example, {@link RequestKind#PROVIDER_OF_LAZY} has <em>2</em> wrapping
-   * classes, and {@link RequestKind#FUTURE} is wrapped with a {@link ListenableFuture}, but for
-   * historical/implementation reasons has not had an associated framework class.
-   */
-  public static Class<?> frameworkClass(RequestKind requestKind) {
-    Class<?> result = FRAMEWORK_CLASSES.get(requestKind);
-    checkArgument(result != null, "no framework class for %s", requestKind);
-    return result;
-  }
-
-  /**
-   * Returns {@code true} if requests for {@code requestKind} can be satisfied by a production
-   * binding.
-   */
-  public static boolean canBeSatisfiedByProductionBinding(RequestKind requestKind) {
-    switch (requestKind) {
-      case INSTANCE:
-      case PROVIDER:
-      case LAZY:
-      case PROVIDER_OF_LAZY:
-      case MEMBERS_INJECTION:
-        return false;
-      case PRODUCER:
-      case PRODUCED:
-      case FUTURE:
-        return true;
-    }
-    throw new AssertionError();
-  }
-
-  private RequestKinds() {}
-}
diff --git a/java/dagger/internal/codegen/base/Scopes.java b/java/dagger/internal/codegen/base/Scopes.java
deleted file mode 100644
index f2c39ce..0000000
--- a/java/dagger/internal/codegen/base/Scopes.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 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.base;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.DiagnosticFormatting.stripCommonTypePrefixes;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.common.AnnotationMirrors;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.model.Scope;
-import dagger.producers.ProductionScope;
-import java.lang.annotation.Annotation;
-import java.util.Optional;
-import javax.inject.Singleton;
-import javax.lang.model.element.Element;
-
-/** Common names and convenience methods for {@link Scope}s. */
-public final class Scopes {
-
-  /** Returns a representation for {@link ProductionScope @ProductionScope} scope. */
-  public static Scope productionScope(DaggerElements elements) {
-    return scope(elements, ProductionScope.class);
-  }
-
-  /** Returns a representation for {@link Singleton @Singleton} scope. */
-  public static Scope singletonScope(DaggerElements elements) {
-    return scope(elements, Singleton.class);
-  }
-
-  /**
-   * Creates a {@link Scope} object from the {@link javax.inject.Scope}-annotated annotation type.
-   */
-  private static Scope scope(
-      DaggerElements elements, Class<? extends Annotation> scopeAnnotationClass) {
-    return Scope.scope(SimpleAnnotationMirror.of(elements.getTypeElement(scopeAnnotationClass)));
-  }
-
-  /**
-   * Returns at most one associated scoped annotation from the source code element, throwing an
-   * exception if there are more than one.
-   */
-  public static Optional<Scope> uniqueScopeOf(Element element) {
-    // TODO(ronshapiro): Use MoreCollectors.toOptional() once we can use guava-jre
-    return Optional.ofNullable(getOnlyElement(scopesOf(element), null));
-  }
-
-  /**
-   * Returns the readable source representation (name with @ prefix) of the scope's annotation type.
-   *
-   * <p>It's readable source because it has had common package prefixes removed, e.g.
-   * {@code @javax.inject.Singleton} is returned as {@code @Singleton}.
-   */
-  public static String getReadableSource(Scope scope) {
-    return stripCommonTypePrefixes(scope.toString());
-  }
-
-  /** Returns all of the associated scopes for a source code element. */
-  public static ImmutableSet<Scope> scopesOf(Element element) {
-    return AnnotationMirrors.getAnnotatedAnnotations(element, javax.inject.Scope.class)
-        .stream()
-        .map(Scope::scope)
-        .collect(toImmutableSet());
-  }
-}
diff --git a/java/dagger/internal/codegen/base/SetType.java b/java/dagger/internal/codegen/base/SetType.java
deleted file mode 100644
index a75a6d3..0000000
--- a/java/dagger/internal/codegen/base/SetType.java
+++ /dev/null
@@ -1,120 +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.base;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Equivalence;
-import dagger.model.Key;
-import java.util.Set;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * Information about a {@link Set} {@link TypeMirror}.
- */
-@AutoValue
-public abstract class SetType {
-  /**
-   * The set type itself, wrapped using {@link MoreTypes#equivalence()}. Use
-   * {@link #declaredSetType()} instead.
-   */
-  protected abstract Equivalence.Wrapper<DeclaredType> wrappedDeclaredSetType();
-
-  /**
-   * The set type itself.
-   */
-  private DeclaredType declaredSetType() {
-    return wrappedDeclaredSetType().get();
-  }
-
-  /**
-   * {@code true} if the set type is the raw {@link Set} type.
-   */
-  public boolean isRawType() {
-    return declaredSetType().getTypeArguments().isEmpty();
-  }
-
-  /**
-   * The element type.
-   */
-  public TypeMirror elementType() {
-    return declaredSetType().getTypeArguments().get(0);
-  }
-
-  /**
-   * {@code true} if {@link #elementType()} is a {@code clazz}.
-   */
-  public boolean elementsAreTypeOf(Class<?> clazz) {
-    return MoreTypes.isType(elementType()) && MoreTypes.isTypeOf(clazz, elementType());
-  }
-
-  /**
-   * {@code T} if {@link #elementType()} is a {@code WrappingClass<T>}.
-   *
-   * @throws IllegalStateException if {@link #elementType()} is not a {@code WrappingClass<T>}
-   * @throws IllegalArgumentException if {@code wrappingClass} does not have exactly one type
-   *     parameter
-   */
-  public TypeMirror unwrappedElementType(Class<?> wrappingClass) {
-    checkArgument(
-        wrappingClass.getTypeParameters().length == 1,
-        "%s must have exactly one type parameter",
-        wrappingClass);
-    checkArgument(
-        elementsAreTypeOf(wrappingClass),
-        "expected elements to be %s, but this type is %s",
-        wrappingClass,
-        declaredSetType());
-    return MoreTypes.asDeclared(elementType()).getTypeArguments().get(0);
-  }
-
-  /**
-   * {@code true} if {@code type} is a {@link Set} type.
-   */
-  public static boolean isSet(TypeMirror type) {
-    return MoreTypes.isType(type) && MoreTypes.isTypeOf(Set.class, type);
-  }
-
-  /**
-   * {@code true} if {@code key.type()} is a {@link Set} type.
-   */
-  public static boolean isSet(Key key) {
-    return isSet(key.type());
-  }
-
-  /**
-   * Returns a {@link SetType} for {@code type}.
-   *
-   * @throws IllegalArgumentException if {@code type} is not a {@link Set} type
-   */
-  public static SetType from(TypeMirror type) {
-    checkArgument(isSet(type), "%s must be a Set", type);
-    return new AutoValue_SetType(MoreTypes.equivalence().wrap(MoreTypes.asDeclared(type)));
-  }
-
-  /**
-   * Returns a {@link SetType} for {@code key}'s {@link Key#type() type}.
-   *
-   * @throws IllegalArgumentException if {@code key.type()} is not a {@link Set} type
-   */
-  public static SetType from(Key key) {
-    return from (key.type());
-  }
-}
diff --git a/java/dagger/internal/codegen/base/SimpleAnnotationMirror.java b/java/dagger/internal/codegen/base/SimpleAnnotationMirror.java
deleted file mode 100644
index 9690691..0000000
--- a/java/dagger/internal/codegen/base/SimpleAnnotationMirror.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2016 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.base;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.base.Functions;
-import com.google.common.base.Joiner;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import java.util.Map;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-
-/** A representation of an annotation. */
-public final class SimpleAnnotationMirror implements AnnotationMirror {
-  private final TypeElement annotationType;
-  private final ImmutableMap<String, ? extends AnnotationValue> namedValues;
-  private final ImmutableMap<ExecutableElement, ? extends AnnotationValue> elementValues;
-
-  private SimpleAnnotationMirror(
-      TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
-    checkArgument(
-        annotationType.getKind().equals(ElementKind.ANNOTATION_TYPE),
-        "annotationType must be an annotation: %s",
-        annotationType);
-    checkArgument(
-        FluentIterable.from(methodsIn(annotationType.getEnclosedElements()))
-            .transform(element -> element.getSimpleName().toString())
-            .toSet()
-            .equals(namedValues.keySet()),
-        "namedValues must have values for exactly the members in %s: %s",
-        annotationType,
-        namedValues);
-    this.annotationType = annotationType;
-    this.namedValues = ImmutableMap.copyOf(namedValues);
-    this.elementValues =
-        Maps.toMap(
-            methodsIn(annotationType.getEnclosedElements()),
-            Functions.compose(
-                Functions.forMap(namedValues), element -> element.getSimpleName().toString()));
-  }
-
-  @Override
-  public DeclaredType getAnnotationType() {
-    return MoreTypes.asDeclared(annotationType.asType());
-  }
-
-  @Override
-  public Map<ExecutableElement, ? extends AnnotationValue> getElementValues() {
-    return elementValues;
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder("@").append(annotationType.getQualifiedName());
-    if (!namedValues.isEmpty()) {
-      builder
-          .append('(')
-          .append(Joiner.on(", ").withKeyValueSeparator(" = ").join(namedValues))
-          .append(')');
-    }
-    return builder.toString();
-  }
-
-  /**
-   * An object representing an annotation instance.
-   *
-   * @param annotationType must be an annotation type with no members
-   */
-  public static AnnotationMirror of(TypeElement annotationType) {
-    return of(annotationType, ImmutableMap.<String, AnnotationValue>of());
-  }
-
-  /**
-   * An object representing an annotation instance.
-   *
-   * @param annotationType must be an annotation type
-   * @param namedValues a value for every annotation member, including those with defaults, indexed
-   *     by simple name
-   */
-  private static AnnotationMirror of(
-      TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
-    return new SimpleAnnotationMirror(annotationType, namedValues);
-  }
-}
diff --git a/java/dagger/internal/codegen/base/SimpleTypeAnnotationValue.java b/java/dagger/internal/codegen/base/SimpleTypeAnnotationValue.java
deleted file mode 100644
index d595bcb..0000000
--- a/java/dagger/internal/codegen/base/SimpleTypeAnnotationValue.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2016 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.base;
-
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.AnnotationValueVisitor;
-import javax.lang.model.type.TypeMirror;
-
-/** An {@link AnnotationValue} that contains a {@link TypeMirror}. */
-final class SimpleTypeAnnotationValue implements AnnotationValue {
-  private final TypeMirror value;
-
-  SimpleTypeAnnotationValue(TypeMirror value) {
-    this.value = value;
-  }
-
-  @Override
-  public TypeMirror getValue() {
-    return value;
-  }
-
-  @Override
-  public String toString() {
-    return value + ".class";
-  }
-
-  @Override
-  public <R, P> R accept(AnnotationValueVisitor<R, P> visitor, P parameter) {
-    return visitor.visitType(getValue(), parameter);
-  }
-}
diff --git a/java/dagger/internal/codegen/base/SourceFileGenerationException.java b/java/dagger/internal/codegen/base/SourceFileGenerationException.java
deleted file mode 100644
index 5553dd8..0000000
--- a/java/dagger/internal/codegen/base/SourceFileGenerationException.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2014 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.base;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.squareup.javapoet.ClassName;
-import java.util.Optional;
-import javax.annotation.processing.Messager;
-import javax.lang.model.element.Element;
-
-/**
- * An exception thrown to indicate that a source file could not be generated.
- *
- * <p>This exception <b>should not</b> be used to report detectable, logical errors as it may mask
- * other errors that might have been caught upon further processing. Use a {@link ValidationReport}
- * for that.
- */
-public final class SourceFileGenerationException extends Exception {
-  private final Element associatedElement;
-
-  SourceFileGenerationException(
-      Optional<ClassName> generatedClassName, Throwable cause, Element associatedElement) {
-    super(createMessage(generatedClassName, cause.getMessage()), cause);
-    this.associatedElement = checkNotNull(associatedElement);
-  }
-
-  private static String createMessage(Optional<ClassName> generatedClassName, String message) {
-    return String.format("Could not generate %s: %s.",
-        generatedClassName.isPresent()
-            ? generatedClassName.get()
-            : "unknown file",
-        message);
-  }
-
-  public void printMessageTo(Messager messager) {
-    messager.printMessage(ERROR, getMessage(), associatedElement);
-  }
-}
diff --git a/java/dagger/internal/codegen/base/SourceFileGenerator.java b/java/dagger/internal/codegen/base/SourceFileGenerator.java
deleted file mode 100644
index 02348a4..0000000
--- a/java/dagger/internal/codegen/base/SourceFileGenerator.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2014 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.base;
-
-import static com.google.auto.common.GeneratedAnnotations.generatedAnnotation;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.javapoet.AnnotationSpecs;
-import dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.Optional;
-import javax.annotation.processing.Filer;
-import javax.annotation.processing.Messager;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-
-/**
- * A template class that provides a framework for properly handling IO while generating source files
- * from an annotation processor. Particularly, it makes a best effort to ensure that files that fail
- * to write successfully are deleted.
- *
- * @param <T> The input type from which source is to be generated.
- */
-public abstract class SourceFileGenerator<T> {
-  private static final String GENERATED_COMMENTS = "https://dagger.dev";
-
-  private final Filer filer;
-  private final DaggerElements elements;
-  private final SourceVersion sourceVersion;
-
-  public SourceFileGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
-    this.filer = checkNotNull(filer);
-    this.elements = checkNotNull(elements);
-    this.sourceVersion = checkNotNull(sourceVersion);
-  }
-
-  public SourceFileGenerator(SourceFileGenerator<T> delegate) {
-    this(delegate.filer, delegate.elements, delegate.sourceVersion);
-  }
-
-  /**
-   * Generates a source file to be compiled for {@code T}. Writes any generation exception to {@code
-   * messager} and does not throw.
-   */
-  public void generate(T input, Messager messager) {
-    try {
-      generate(input);
-    } catch (SourceFileGenerationException e) {
-      e.printMessageTo(messager);
-    }
-  }
-
-  /** Generates a source file to be compiled for {@code T}. */
-  public void generate(T input) throws SourceFileGenerationException {
-    Optional<TypeSpec.Builder> type = write(input);
-    if (!type.isPresent()) {
-      return;
-    }
-    try {
-      buildJavaFile(input, type.get()).writeTo(filer);
-    } catch (Exception e) {
-      // if the code above threw a SFGE, use that
-      Throwables.propagateIfPossible(e, SourceFileGenerationException.class);
-      // otherwise, throw a new one
-      throw new SourceFileGenerationException(Optional.empty(), e, originatingElement(input));
-    }
-  }
-
-  private JavaFile buildJavaFile(T input, TypeSpec.Builder typeSpecBuilder) {
-    typeSpecBuilder.addOriginatingElement(originatingElement(input));
-    Optional<AnnotationSpec> generatedAnnotation =
-        generatedAnnotation(elements, sourceVersion)
-            .map(
-                annotation ->
-                    AnnotationSpec.builder(ClassName.get(annotation))
-                        .addMember("value", "$S", "dagger.internal.codegen.ComponentProcessor")
-                        .addMember("comments", "$S", GENERATED_COMMENTS)
-                        .build());
-    generatedAnnotation.ifPresent(typeSpecBuilder::addAnnotation);
-
-    // TODO(b/134590785): remove this and only suppress annotations locally, if necessary
-    typeSpecBuilder.addAnnotation(
-        AnnotationSpecs.suppressWarnings(
-            ImmutableSet.<Suppression>builder()
-                .addAll(warningSuppressions())
-                .add(UNCHECKED, RAWTYPES)
-                .build()));
-
-    JavaFile.Builder javaFileBuilder =
-        JavaFile.builder(nameGeneratedType(input).packageName(), typeSpecBuilder.build())
-            .skipJavaLangImports(true);
-    if (!generatedAnnotation.isPresent()) {
-      javaFileBuilder.addFileComment("Generated by Dagger ($L).", GENERATED_COMMENTS);
-    }
-    return javaFileBuilder.build();
-  }
-
-  /** Implementations should return the {@link ClassName} for the top-level type to be generated. */
-  public abstract ClassName nameGeneratedType(T input);
-
-  /** Returns the originating element of the generating type. */
-  public abstract Element originatingElement(T input);
-
-  /**
-   * Returns a {@link TypeSpec.Builder type} to be generated for {@code T}, or {@link
-   * Optional#empty()} if no file should be generated.
-   */
-  // TODO(ronshapiro): write() makes more sense in JavaWriter where all writers are mutable.
-  // consider renaming to something like typeBuilder() which conveys the mutability of the result
-  public abstract Optional<TypeSpec.Builder> write(T input);
-
-  /** Returns {@link Suppression}s that are applied to files generated by this generator. */
-  // TODO(b/134590785): When suppressions are removed locally, remove this and inline the usages
-  protected ImmutableSet<Suppression> warningSuppressions() {
-    return ImmutableSet.of();
-  }
-}
diff --git a/java/dagger/internal/codegen/base/UniqueNameSet.java b/java/dagger/internal/codegen/base/UniqueNameSet.java
deleted file mode 100644
index c1ffe47..0000000
--- a/java/dagger/internal/codegen/base/UniqueNameSet.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2016 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.base;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/** A collector for names to be used in the same namespace that should not conflict. */
-public final class UniqueNameSet {
-  private final Set<String> uniqueNames = new HashSet<>();
-
-  /**
-   * Generates a unique name using {@code base}. If {@code base} has not yet been added, it will be
-   * returned as-is. If your {@code base} is healthy, this will always return {@code base}.
-   */
-  public String getUniqueName(CharSequence base) {
-    String name = base.toString();
-    for (int differentiator = 2; !uniqueNames.add(name); differentiator++) {
-      name = base.toString() + differentiator;
-    }
-    return name;
-  }
-
-  /**
-   * Adds {@code name} without any modification to the name set. Has no effect if {@code name} is
-   * already present in the set.
-   */
-  public void claim(CharSequence name) {
-    uniqueNames.add(name.toString());
-  }
-}
diff --git a/java/dagger/internal/codegen/base/Util.java b/java/dagger/internal/codegen/base/Util.java
deleted file mode 100644
index e92b8ab..0000000
--- a/java/dagger/internal/codegen/base/Util.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2013 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.base;
-
-import java.util.Map;
-import java.util.function.Function;
-
-/** General utilities for the annotation processor. */
-public final class Util {
-
-  /**
-   * A version of {@link Map#computeIfAbsent(Object, Function)} that allows {@code mappingFunction}
-   * to update {@code map}.
-   */
-  public static <K, V> V reentrantComputeIfAbsent(
-      Map<K, V> map, K key, Function<? super K, ? extends V> mappingFunction) {
-    V value = map.get(key);
-    if (value == null) {
-      value = mappingFunction.apply(key);
-      if (value != null) {
-        map.put(key, value);
-      }
-    }
-    return value;
-  }
-
-  private Util() {}
-}
diff --git a/java/dagger/internal/codegen/binding/AnnotationExpression.java b/java/dagger/internal/codegen/binding/AnnotationExpression.java
deleted file mode 100644
index de0aea5..0000000
--- a/java/dagger/internal/codegen/binding/AnnotationExpression.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2016 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.binding;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
-import static dagger.internal.codegen.binding.SourceFiles.classFileName;
-import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
-import static java.util.stream.Collectors.toList;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.TypeName;
-import java.util.List;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleAnnotationValueVisitor6;
-import javax.lang.model.util.SimpleTypeVisitor6;
-
-/**
- * Returns an expression creating an instance of the visited annotation type. Its parameter must be
- * a class as generated by {@link dagger.internal.codegen.writing.AnnotationCreatorGenerator}.
- *
- * <p>Note that {@link AnnotationValue#toString()} is the source-code representation of the value
- * <em>when used in an annotation</em>, which is not always the same as the representation needed
- * when creating the value in a method body.
- *
- * <p>For example, inside an annotation, a nested array of {@code int}s is simply {@code {1, 2, 3}},
- * but in code it would have to be {@code new int[] {1, 2, 3}}.
- */
-public class AnnotationExpression
-    extends SimpleAnnotationValueVisitor6<CodeBlock, AnnotationValue> {
-
-  private final AnnotationMirror annotation;
-  private final ClassName creatorClass;
-
-  AnnotationExpression(AnnotationMirror annotation) {
-    this.annotation = annotation;
-    this.creatorClass =
-        getAnnotationCreatorClassName(
-            MoreTypes.asTypeElement(annotation.getAnnotationType()));
-  }
-
-  /**
-   * Returns an expression that calls static methods on the annotation's creator class to create an
-   * annotation instance equivalent the annotation passed to the constructor.
-   */
-  CodeBlock getAnnotationInstanceExpression() {
-    return getAnnotationInstanceExpression(annotation);
-  }
-
-  private CodeBlock getAnnotationInstanceExpression(AnnotationMirror annotation) {
-    return CodeBlock.of(
-        "$T.$L($L)",
-        creatorClass,
-        createMethodName(
-            MoreElements.asType(annotation.getAnnotationType().asElement())),
-        makeParametersCodeBlock(
-            getAnnotationValuesWithDefaults(annotation)
-                .entrySet()
-                .stream()
-                .map(entry -> getValueExpression(entry.getKey().getReturnType(), entry.getValue()))
-                .collect(toList())));
-  }
-
-  /**
-   * Returns the name of the generated class that contains the static {@code create} methods for an
-   * annotation type.
-   */
-  public static ClassName getAnnotationCreatorClassName(TypeElement annotationType) {
-    ClassName annotationTypeName = ClassName.get(annotationType);
-    return annotationTypeName
-        .topLevelClassName()
-        .peerClass(classFileName(annotationTypeName) + "Creator");
-  }
-
-  public static String createMethodName(TypeElement annotationType) {
-    return "create" + annotationType.getSimpleName();
-  }
-
-  /**
-   * Returns an expression that evaluates to a {@code value} of a given type on an {@code
-   * annotation}.
-   */
-  CodeBlock getValueExpression(TypeMirror valueType, AnnotationValue value) {
-    return ARRAY_LITERAL_PREFIX.visit(valueType, this.visit(value, value));
-  }
-
-  @Override
-  public CodeBlock visitEnumConstant(VariableElement c, AnnotationValue p) {
-    return CodeBlock.of("$T.$L", c.getEnclosingElement(), c.getSimpleName());
-  }
-
-  @Override
-  public CodeBlock visitAnnotation(AnnotationMirror a, AnnotationValue p) {
-    return getAnnotationInstanceExpression(a);
-  }
-
-  @Override
-  public CodeBlock visitType(TypeMirror t, AnnotationValue p) {
-    return CodeBlock.of("$T.class", t);
-  }
-
-  @Override
-  public CodeBlock visitString(String s, AnnotationValue p) {
-    return CodeBlock.of("$S", s);
-  }
-
-  @Override
-  public CodeBlock visitByte(byte b, AnnotationValue p) {
-    return CodeBlock.of("(byte) $L", b);
-  }
-
-  @Override
-  public CodeBlock visitChar(char c, AnnotationValue p) {
-    return CodeBlock.of("$L", p);
-  }
-
-  @Override
-  public CodeBlock visitDouble(double d, AnnotationValue p) {
-    return CodeBlock.of("$LD", d);
-  }
-
-  @Override
-  public CodeBlock visitFloat(float f, AnnotationValue p) {
-    return CodeBlock.of("$LF", f);
-  }
-
-  @Override
-  public CodeBlock visitLong(long i, AnnotationValue p) {
-    return CodeBlock.of("$LL", i);
-  }
-
-  @Override
-  public CodeBlock visitShort(short s, AnnotationValue p) {
-    return CodeBlock.of("(short) $L", s);
-  }
-
-  @Override
-  protected CodeBlock defaultAction(Object o, AnnotationValue p) {
-    return CodeBlock.of("$L", o);
-  }
-
-  @Override
-  public CodeBlock visitArray(List<? extends AnnotationValue> values, AnnotationValue p) {
-    ImmutableList.Builder<CodeBlock> codeBlocks = ImmutableList.builder();
-    for (AnnotationValue value : values) {
-      codeBlocks.add(this.visit(value, p));
-    }
-    return CodeBlock.of("{$L}", makeParametersCodeBlock(codeBlocks.build()));
-  }
-
-  /**
-   * If the visited type is an array, prefixes the parameter code block with {@code new T[]}, where
-   * {@code T} is the raw array component type.
-   */
-  private static final SimpleTypeVisitor6<CodeBlock, CodeBlock> ARRAY_LITERAL_PREFIX =
-      new SimpleTypeVisitor6<CodeBlock, CodeBlock>() {
-
-        @Override
-        public CodeBlock visitArray(ArrayType t, CodeBlock p) {
-          return CodeBlock.of("new $T[] $L", RAW_TYPE_NAME.visit(t.getComponentType()), p);
-        }
-
-        @Override
-        protected CodeBlock defaultAction(TypeMirror e, CodeBlock p) {
-          return p;
-        }
-      };
-
-  /**
-   * If the visited type is an array, returns the name of its raw component type; otherwise returns
-   * the name of the type itself.
-   */
-  private static final SimpleTypeVisitor6<TypeName, Void> RAW_TYPE_NAME =
-      new SimpleTypeVisitor6<TypeName, Void>() {
-        @Override
-        public TypeName visitDeclared(DeclaredType t, Void p) {
-          return ClassName.get(MoreTypes.asTypeElement(t));
-        }
-
-        @Override
-        protected TypeName defaultAction(TypeMirror e, Void p) {
-          return TypeName.get(e);
-        }
-      };
-}
diff --git a/java/dagger/internal/codegen/binding/AssistedInjectionAnnotations.java b/java/dagger/internal/codegen/binding/AssistedInjectionAnnotations.java
deleted file mode 100644
index 8d6ee5d..0000000
--- a/java/dagger/internal/codegen/binding/AssistedInjectionAnnotations.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2020 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.binding;
-
-import static com.google.auto.common.MoreElements.asExecutable;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.auto.common.MoreTypes.asExecutable;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.MoreAnnotationValues.getStringValue;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.util.ElementFilter.constructorsIn;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.base.Equivalence;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingKind;
-import java.util.List;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-
-/** Assisted injection utility methods. */
-public final class AssistedInjectionAnnotations {
-  /** Returns the factory method for the given factory {@link TypeElement}. */
-  public static ExecutableElement assistedFactoryMethod(
-      TypeElement factory, DaggerElements elements, DaggerTypes types) {
-    return getOnlyElement(assistedFactoryMethods(factory, elements, types));
-  }
-
-  /** Returns the list of abstract factory methods for the given factory {@link TypeElement}. */
-  public static ImmutableSet<ExecutableElement> assistedFactoryMethods(
-      TypeElement factory, DaggerElements elements, DaggerTypes types) {
-    return MoreElements.getLocalAndInheritedMethods(factory, types, elements).stream()
-        .filter(method -> method.getModifiers().contains(ABSTRACT))
-        .filter(method -> !method.isDefault())
-        .collect(toImmutableSet());
-  }
-
-  /** Returns {@code true} if the element uses assisted injection. */
-  public static boolean isAssistedInjectionType(TypeElement typeElement) {
-    ImmutableSet<ExecutableElement> injectConstructors = assistedInjectedConstructors(typeElement);
-    return !injectConstructors.isEmpty()
-        && isAnnotationPresent(getOnlyElement(injectConstructors), AssistedInject.class);
-  }
-
-  /** Returns {@code true} if this binding is an assisted factory. */
-  public static boolean isAssistedFactoryType(Element element) {
-    return isAnnotationPresent(element, AssistedFactory.class);
-  }
-
-  /**
-   * Returns the list of assisted parameters as {@link ParameterSpec}s.
-   *
-   * <p>The type of each parameter will be the resolved type given by the binding key, and the name
-   * of each parameter will be the name given in the {@link
-   * dagger.assisted.AssistedInject}-annotated constructor.
-   */
-  public static ImmutableList<ParameterSpec> assistedParameterSpecs(
-      Binding binding, DaggerTypes types) {
-    checkArgument(binding.kind() == BindingKind.ASSISTED_INJECTION);
-    ExecutableElement constructor = asExecutable(binding.bindingElement().get());
-    ExecutableType constructorType =
-        asExecutable(types.asMemberOf(asDeclared(binding.key().type()), constructor));
-    return assistedParameterSpecs(constructor.getParameters(), constructorType.getParameterTypes());
-  }
-
-  private static ImmutableList<ParameterSpec> assistedParameterSpecs(
-      List<? extends VariableElement> paramElements, List<? extends TypeMirror> paramTypes) {
-    ImmutableList.Builder<ParameterSpec> assistedParameterSpecs = ImmutableList.builder();
-    for (int i = 0; i < paramElements.size(); i++) {
-      VariableElement paramElement = paramElements.get(i);
-      TypeMirror paramType = paramTypes.get(i);
-      if (isAssistedParameter(paramElement)) {
-        assistedParameterSpecs.add(
-            ParameterSpec.builder(TypeName.get(paramType), paramElement.getSimpleName().toString())
-                .build());
-      }
-    }
-    return assistedParameterSpecs.build();
-  }
-
-  /**
-   * Returns the list of assisted factory parameters as {@link ParameterSpec}s.
-   *
-   * <p>The type of each parameter will be the resolved type given by the binding key, and the name
-   * of each parameter will be the name given in the {@link
-   * dagger.assisted.AssistedInject}-annotated constructor.
-   */
-  public static ImmutableList<ParameterSpec> assistedFactoryParameterSpecs(
-      Binding binding, DaggerElements elements, DaggerTypes types) {
-    checkArgument(binding.kind() == BindingKind.ASSISTED_FACTORY);
-
-    AssistedFactoryMetadata metadata =
-        AssistedFactoryMetadata.create(binding.bindingElement().get().asType(), elements, types);
-    ExecutableType factoryMethodType =
-        asExecutable(types.asMemberOf(asDeclared(binding.key().type()), metadata.factoryMethod()));
-    return assistedParameterSpecs(
-        // Use the order of the parameters from the @AssistedFactory method but use the parameter
-        // names of the @AssistedInject constructor.
-        metadata.assistedFactoryAssistedParameters().stream()
-            .map(metadata.assistedInjectAssistedParametersMap()::get)
-            .collect(toImmutableList()),
-        factoryMethodType.getParameterTypes());
-  }
-
-  /** Returns the constructors in {@code type} that are annotated with {@link AssistedInject}. */
-  public static ImmutableSet<ExecutableElement> assistedInjectedConstructors(TypeElement type) {
-    return constructorsIn(type.getEnclosedElements()).stream()
-        .filter(constructor -> isAnnotationPresent(constructor, AssistedInject.class))
-        .collect(toImmutableSet());
-  }
-
-  public static ImmutableList<VariableElement> assistedParameters(Binding binding) {
-    return binding.kind() == BindingKind.ASSISTED_INJECTION
-        ? assistedParameters(asExecutable(binding.bindingElement().get()))
-        : ImmutableList.of();
-  }
-
-  private static ImmutableList<VariableElement> assistedParameters(ExecutableElement constructor) {
-    return constructor.getParameters().stream()
-        .filter(AssistedInjectionAnnotations::isAssistedParameter)
-        .collect(toImmutableList());
-  }
-
-  /** Returns {@code true} if this binding is uses assisted injection. */
-  public static boolean isAssistedParameter(VariableElement param) {
-    return isAnnotationPresent(MoreElements.asVariable(param), Assisted.class);
-  }
-
-  /** Metadata about an {@link dagger.assisted.AssistedFactory} annotated type. */
-  @AutoValue
-  public abstract static class AssistedFactoryMetadata {
-    public static AssistedFactoryMetadata create(
-        TypeMirror factory, DaggerElements elements, DaggerTypes types) {
-      DeclaredType factoryType = asDeclared(factory);
-      TypeElement factoryElement = asTypeElement(factoryType);
-      ExecutableElement factoryMethod = assistedFactoryMethod(factoryElement, elements, types);
-      ExecutableType factoryMethodType = asExecutable(types.asMemberOf(factoryType, factoryMethod));
-      DeclaredType assistedInjectType = asDeclared(factoryMethodType.getReturnType());
-      return new AutoValue_AssistedInjectionAnnotations_AssistedFactoryMetadata(
-          factoryElement,
-          factoryType,
-          factoryMethod,
-          factoryMethodType,
-          asTypeElement(assistedInjectType),
-          assistedInjectType,
-          AssistedInjectionAnnotations.assistedInjectAssistedParameters(assistedInjectType, types),
-          AssistedInjectionAnnotations.assistedFactoryAssistedParameters(
-              factoryMethod, factoryMethodType));
-    }
-
-    public abstract TypeElement factory();
-
-    public abstract DeclaredType factoryType();
-
-    public abstract ExecutableElement factoryMethod();
-
-    public abstract ExecutableType factoryMethodType();
-
-    public abstract TypeElement assistedInjectElement();
-
-    public abstract DeclaredType assistedInjectType();
-
-    public abstract ImmutableList<AssistedParameter> assistedInjectAssistedParameters();
-
-    public abstract ImmutableList<AssistedParameter> assistedFactoryAssistedParameters();
-
-    @Memoized
-    public ImmutableMap<AssistedParameter, VariableElement> assistedInjectAssistedParametersMap() {
-      ImmutableMap.Builder<AssistedParameter, VariableElement> builder = ImmutableMap.builder();
-      for (AssistedParameter assistedParameter : assistedInjectAssistedParameters()) {
-        builder.put(assistedParameter, assistedParameter.variableElement);
-      }
-      return builder.build();
-    }
-
-    @Memoized
-    public ImmutableMap<AssistedParameter, VariableElement> assistedFactoryAssistedParametersMap() {
-      ImmutableMap.Builder<AssistedParameter, VariableElement> builder = ImmutableMap.builder();
-      for (AssistedParameter assistedParameter : assistedFactoryAssistedParameters()) {
-        builder.put(assistedParameter, assistedParameter.variableElement);
-      }
-      return builder.build();
-    }
-  }
-
-  /**
-   * Metadata about an {@link Assisted} annotated parameter.
-   *
-   * <p>This parameter can represent an {@link Assisted} annotated parameter from an {@link
-   * AssistedInject} constructor or an {@link AssistedFactory} method.
-   */
-  @AutoValue
-  public abstract static class AssistedParameter {
-    public static AssistedParameter create(VariableElement parameter, TypeMirror parameterType) {
-      AssistedParameter assistedParameter =
-          new AutoValue_AssistedInjectionAnnotations_AssistedParameter(
-              getAnnotationMirror(parameter, Assisted.class)
-                  .map(assisted -> getStringValue(assisted, "value"))
-                  .orElse(""),
-              MoreTypes.equivalence().wrap(parameterType));
-      assistedParameter.variableElement = parameter;
-      return assistedParameter;
-    }
-
-    private VariableElement variableElement;
-
-    /** Returns the string qualifier from the {@link Assisted#value()}. */
-    public abstract String qualifier();
-
-    /** Returns the wrapper for the type annotated with {@link Assisted}. */
-    public abstract Equivalence.Wrapper<TypeMirror> wrappedType();
-
-    /** Returns the type annotated with {@link Assisted}. */
-    public final TypeMirror type() {
-      return wrappedType().get();
-    }
-
-    public final VariableElement variableElement() {
-      return variableElement;
-    }
-
-    @Override
-    public final String toString() {
-      return qualifier().isEmpty()
-          ? String.format("@Assisted %s", type())
-          : String.format("@Assisted(\"%s\") %s", qualifier(), type());
-    }
-  }
-
-  public static ImmutableList<AssistedParameter> assistedInjectAssistedParameters(
-      DeclaredType assistedInjectType, DaggerTypes types) {
-    // We keep track of the constructor both as an ExecutableElement to access @Assisted
-    // parameters and as an ExecutableType to access the resolved parameter types.
-    ExecutableElement assistedInjectConstructor =
-        getOnlyElement(assistedInjectedConstructors(asTypeElement(assistedInjectType)));
-    ExecutableType assistedInjectConstructorType =
-        asExecutable(types.asMemberOf(assistedInjectType, assistedInjectConstructor));
-
-    ImmutableList.Builder<AssistedParameter> builder = ImmutableList.builder();
-    for (int i = 0; i < assistedInjectConstructor.getParameters().size(); i++) {
-      VariableElement parameter = assistedInjectConstructor.getParameters().get(i);
-      TypeMirror parameterType = assistedInjectConstructorType.getParameterTypes().get(i);
-      if (isAnnotationPresent(parameter, Assisted.class)) {
-        builder.add(AssistedParameter.create(parameter, parameterType));
-      }
-    }
-    return builder.build();
-  }
-
-  public static ImmutableList<AssistedParameter> assistedFactoryAssistedParameters(
-      ExecutableElement factoryMethod, ExecutableType factoryMethodType) {
-    ImmutableList.Builder<AssistedParameter> builder = ImmutableList.builder();
-    for (int i = 0; i < factoryMethod.getParameters().size(); i++) {
-      VariableElement parameter = factoryMethod.getParameters().get(i);
-      TypeMirror parameterType = factoryMethodType.getParameterTypes().get(i);
-      builder.add(AssistedParameter.create(parameter, parameterType));
-    }
-    return builder.build();
-  }
-
-  private AssistedInjectionAnnotations() {}
-}
diff --git a/java/dagger/internal/codegen/binding/BUILD b/java/dagger/internal/codegen/binding/BUILD
deleted file mode 100644
index ff8db8f..0000000
--- a/java/dagger/internal/codegen/binding/BUILD
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2017 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.
-
-# Description:
-#   JavaPoet extensions for use in Dagger
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "binding",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    tags = ["maven:merged"],
-    deps = [
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
-        "//java/dagger/internal/guava:graph",
-        "//java/dagger/model:internal-proxies",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
diff --git a/java/dagger/internal/codegen/binding/Binding.java b/java/dagger/internal/codegen/binding/Binding.java
deleted file mode 100644
index 0d4eef6..0000000
--- a/java/dagger/internal/codegen/binding/Binding.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.common.base.Suppliers.memoize;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingKind;
-import dagger.model.DependencyRequest;
-import dagger.model.Scope;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.TypeParameterElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleTypeVisitor6;
-
-/**
- * An abstract type for classes representing a Dagger binding. Particularly, contains the {@link
- * Element} that generated the binding and the {@link DependencyRequest} instances that are required
- * to satisfy the binding, but leaves the specifics of the <i>mechanism</i> of the binding to the
- * subtypes.
- */
-public abstract class Binding extends BindingDeclaration {
-
-  /**
-   * Returns {@code true} if using this binding requires an instance of the {@link
-   * #contributingModule()}.
-   */
-  public boolean requiresModuleInstance() {
-    if (!bindingElement().isPresent() || !contributingModule().isPresent()) {
-      return false;
-    }
-    Set<Modifier> modifiers = bindingElement().get().getModifiers();
-    return !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC);
-  }
-
-  /**
-   * Returns {@code true} if this binding may provide {@code null} instead of an instance of {@link
-   * #key()}. Nullable bindings cannot be requested from {@linkplain DependencyRequest#isNullable()
-   * non-nullable dependency requests}.
-   */
-  public abstract boolean isNullable();
-
-  /** The kind of binding this instance represents. */
-  public abstract BindingKind kind();
-
-  /** The {@link BindingType} of this binding. */
-  public abstract BindingType bindingType();
-
-  /** The {@link FrameworkType} of this binding. */
-  public final FrameworkType frameworkType() {
-    return FrameworkType.forBindingType(bindingType());
-  }
-
-  /**
-   * The explicit set of {@link DependencyRequest dependencies} required to satisfy this binding as
-   * defined by the user-defined injection sites.
-   */
-  public abstract ImmutableSet<DependencyRequest> explicitDependencies();
-
-  /**
-   * The set of {@link DependencyRequest dependencies} that are added by the framework rather than a
-   * user-defined injection site. This returns an unmodifiable set.
-   */
-  public ImmutableSet<DependencyRequest> implicitDependencies() {
-    return ImmutableSet.of();
-  }
-
-  private final Supplier<ImmutableSet<DependencyRequest>> dependencies =
-      memoize(
-          () -> {
-            ImmutableSet<DependencyRequest> implicitDependencies = implicitDependencies();
-            return ImmutableSet.copyOf(
-                implicitDependencies.isEmpty()
-                    ? explicitDependencies()
-                    : Sets.union(implicitDependencies, explicitDependencies()));
-          });
-
-  /**
-   * The set of {@link DependencyRequest dependencies} required to satisfy this binding. This is the
-   * union of {@link #explicitDependencies()} and {@link #implicitDependencies()}. This returns an
-   * unmodifiable set.
-   */
-  public final ImmutableSet<DependencyRequest> dependencies() {
-    return dependencies.get();
-  }
-
-  /**
-   * If this binding's key's type parameters are different from those of the {@link
-   * #bindingTypeElement()}, this is the binding for the {@link #bindingTypeElement()}'s unresolved
-   * type.
-   */
-  public abstract Optional<? extends Binding> unresolved();
-
-  public Optional<Scope> scope() {
-    return Optional.empty();
-  }
-
-  // TODO(sameb): Remove the TypeElement parameter and pull it from the TypeMirror.
-  static boolean hasNonDefaultTypeParameters(
-      TypeElement element, TypeMirror type, DaggerTypes types) {
-    // If the element has no type parameters, nothing can be wrong.
-    if (element.getTypeParameters().isEmpty()) {
-      return false;
-    }
-
-    List<TypeMirror> defaultTypes = Lists.newArrayList();
-    for (TypeParameterElement parameter : element.getTypeParameters()) {
-      defaultTypes.add(parameter.asType());
-    }
-
-    List<TypeMirror> actualTypes =
-        type.accept(
-            new SimpleTypeVisitor6<List<TypeMirror>, Void>() {
-              @Override
-              protected List<TypeMirror> defaultAction(TypeMirror e, Void p) {
-                return ImmutableList.of();
-              }
-
-              @Override
-              public List<TypeMirror> visitDeclared(DeclaredType t, Void p) {
-                return ImmutableList.<TypeMirror>copyOf(t.getTypeArguments());
-              }
-            },
-            null);
-
-    // The actual type parameter size can be different if the user is using a raw type.
-    if (defaultTypes.size() != actualTypes.size()) {
-      return true;
-    }
-
-    for (int i = 0; i < defaultTypes.size(); i++) {
-      if (!types.isSameType(defaultTypes.get(i), actualTypes.get(i))) {
-        return true;
-      }
-    }
-    return false;
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/BindingDeclaration.java b/java/dagger/internal/codegen/binding/BindingDeclaration.java
deleted file mode 100644
index 712260f..0000000
--- a/java/dagger/internal/codegen/binding/BindingDeclaration.java
+++ /dev/null
@@ -1,87 +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.binding;
-
-import static dagger.internal.codegen.extension.Optionals.emptiesLast;
-import static java.util.Comparator.comparing;
-
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.model.BindingKind;
-import dagger.model.Key;
-import java.util.Comparator;
-import java.util.Optional;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-/** An object that declares or specifies a binding. */
-public abstract class BindingDeclaration {
-  /**
-   * A comparator that compares binding declarations with elements.
-   *
-   * <p>Compares, in order:
-   *
-   * <ol>
-   *   <li>Contributing module or enclosing type name
-   *   <li>Binding element's simple name
-   *   <li>Binding element's type
-   * </ol>
-   *
-   * Any binding declarations without elements are last.
-   */
-  public static final Comparator<BindingDeclaration> COMPARATOR =
-      comparing(
-              (BindingDeclaration declaration) ->
-                  declaration.contributingModule().isPresent()
-                      ? declaration.contributingModule()
-                      : declaration.bindingTypeElement(),
-              emptiesLast(comparing((TypeElement type) -> type.getQualifiedName().toString())))
-          .thenComparing(
-              (BindingDeclaration declaration) -> declaration.bindingElement(),
-              emptiesLast(
-                  comparing((Element element) -> element.getSimpleName().toString())
-                      .thenComparing((Element element) -> element.asType().toString())));
-
-  /** The {@link Key} of this declaration. */
-  public abstract Key key();
-
-  /**
-   * The {@link Element} that declares this binding. Absent for {@linkplain BindingKind binding
-   * kinds} that are not always declared by exactly one element.
-   *
-   * <p>For example, consider {@link BindingKind#MULTIBOUND_SET}. A component with many
-   * {@code @IntoSet} bindings for the same key will have a synthetic binding that depends on all
-   * contributions, but with no identifiying binding element. A {@code @Multibinds} method will also
-   * contribute a synthetic binding, but since multiple {@code @Multibinds} methods can coexist in
-   * the same component (and contribute to one single binding), it has no binding element.
-   */
-  public abstract Optional<Element> bindingElement();
-
-  /**
-   * The type enclosing the {@link #bindingElement()}, or {@link Optional#empty()} if {@link
-   * #bindingElement()} is empty.
-   */
-  public final Optional<TypeElement> bindingTypeElement() {
-    return bindingElement().map(DaggerElements::closestEnclosingTypeElement);
-  }
-
-  /**
-   * The installed module class that contributed the {@link #bindingElement()}. May be a subclass of
-   * the class that contains {@link #bindingElement()}. Absent if {@link #bindingElement()} is
-   * empty.
-   */
-  public abstract Optional<TypeElement> contributingModule();
-}
diff --git a/java/dagger/internal/codegen/binding/BindingDeclarationFormatter.java b/java/dagger/internal/codegen/binding/BindingDeclarationFormatter.java
deleted file mode 100644
index 8476497..0000000
--- a/java/dagger/internal/codegen/binding/BindingDeclarationFormatter.java
+++ /dev/null
@@ -1,125 +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.binding;
-
-import static com.google.common.collect.Sets.immutableEnumSet;
-import static dagger.internal.codegen.base.DiagnosticFormatting.stripCommonTypePrefixes;
-import static dagger.internal.codegen.base.ElementFormatter.elementToString;
-import static javax.lang.model.element.ElementKind.PARAMETER;
-import static javax.lang.model.type.TypeKind.DECLARED;
-import static javax.lang.model.type.TypeKind.EXECUTABLE;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.base.Formatter;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeKind;
-
-/**
- * Formats a {@link BindingDeclaration} into a {@link String} suitable for use in error messages.
- */
-public final class BindingDeclarationFormatter extends Formatter<BindingDeclaration> {
-  private static final ImmutableSet<TypeKind> FORMATTABLE_ELEMENT_TYPE_KINDS =
-      immutableEnumSet(EXECUTABLE, DECLARED);
-
-  private final MethodSignatureFormatter methodSignatureFormatter;
-
-  @Inject
-  BindingDeclarationFormatter(MethodSignatureFormatter methodSignatureFormatter) {
-    this.methodSignatureFormatter = methodSignatureFormatter;
-  }
-
-  /**
-   * Returns {@code true} for declarations that this formatter can format. Specifically bindings
-   * from subcomponent declarations or those with {@linkplain BindingDeclaration#bindingElement()
-   * binding elements} that are methods, constructors, or types.
-   */
-  public boolean canFormat(BindingDeclaration bindingDeclaration) {
-    if (bindingDeclaration instanceof SubcomponentDeclaration) {
-      return true;
-    }
-    if (bindingDeclaration.bindingElement().isPresent()) {
-      Element bindingElement = bindingDeclaration.bindingElement().get();
-      return bindingElement.getKind().equals(PARAMETER)
-          || FORMATTABLE_ELEMENT_TYPE_KINDS.contains(bindingElement.asType().getKind());
-    }
-    // TODO(dpb): validate whether what this is doing is correct
-    return false;
-  }
-
-  @Override
-  public String format(BindingDeclaration bindingDeclaration) {
-    if (bindingDeclaration instanceof SubcomponentDeclaration) {
-      return formatSubcomponentDeclaration((SubcomponentDeclaration) bindingDeclaration);
-    }
-
-    if (bindingDeclaration.bindingElement().isPresent()) {
-      Element bindingElement = bindingDeclaration.bindingElement().get();
-      if (bindingElement.getKind().equals(PARAMETER)) {
-        return elementToString(bindingElement);
-      }
-
-      switch (bindingElement.asType().getKind()) {
-        case EXECUTABLE:
-          return methodSignatureFormatter.format(
-              MoreElements.asExecutable(bindingElement),
-              bindingDeclaration
-                  .contributingModule()
-                  .map(module -> MoreTypes.asDeclared(module.asType())));
-
-        case DECLARED:
-          return stripCommonTypePrefixes(bindingElement.asType().toString());
-
-        default:
-          throw new IllegalArgumentException(
-              "Formatting unsupported for element: " + bindingElement);
-      }
-    }
-
-    return String.format(
-        "Dagger-generated binding for %s",
-        stripCommonTypePrefixes(bindingDeclaration.key().toString()));
-  }
-
-  private String formatSubcomponentDeclaration(SubcomponentDeclaration subcomponentDeclaration) {
-    ImmutableList<TypeElement> moduleSubcomponents =
-        subcomponentDeclaration.moduleAnnotation().subcomponents();
-    int index = moduleSubcomponents.indexOf(subcomponentDeclaration.subcomponentType());
-    StringBuilder annotationValue = new StringBuilder();
-    if (moduleSubcomponents.size() != 1) {
-      annotationValue.append("{");
-    }
-    annotationValue.append(
-        formatArgumentInList(
-            index,
-            moduleSubcomponents.size(),
-            subcomponentDeclaration.subcomponentType().getQualifiedName() + ".class"));
-    if (moduleSubcomponents.size() != 1) {
-      annotationValue.append("}");
-    }
-
-    return String.format(
-        "@%s(subcomponents = %s) for %s",
-        subcomponentDeclaration.moduleAnnotation().annotationName(),
-        annotationValue,
-        subcomponentDeclaration.contributingModule().get());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/BindingFactory.java b/java/dagger/internal/codegen/binding/BindingFactory.java
deleted file mode 100644
index 6f2fc80..0000000
--- a/java/dagger/internal/codegen/binding/BindingFactory.java
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * Copyright (C) 2017 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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.MoreAnnotationMirrors.wrapOptionalInEquivalence;
-import static dagger.internal.codegen.base.Scopes.uniqueScopeOf;
-import static dagger.internal.codegen.binding.Binding.hasNonDefaultTypeParameters;
-import static dagger.internal.codegen.binding.ComponentDescriptor.isComponentProductionMethod;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.getNullableType;
-import static dagger.internal.codegen.binding.ContributionBinding.bindingKindForMultibindingKey;
-import static dagger.internal.codegen.binding.MapKeys.getMapKey;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.model.BindingKind.ASSISTED_FACTORY;
-import static dagger.model.BindingKind.ASSISTED_INJECTION;
-import static dagger.model.BindingKind.BOUND_INSTANCE;
-import static dagger.model.BindingKind.COMPONENT;
-import static dagger.model.BindingKind.COMPONENT_DEPENDENCY;
-import static dagger.model.BindingKind.COMPONENT_PRODUCTION;
-import static dagger.model.BindingKind.COMPONENT_PROVISION;
-import static dagger.model.BindingKind.DELEGATE;
-import static dagger.model.BindingKind.INJECTION;
-import static dagger.model.BindingKind.MEMBERS_INJECTOR;
-import static dagger.model.BindingKind.OPTIONAL;
-import static dagger.model.BindingKind.PRODUCTION;
-import static dagger.model.BindingKind.PROVISION;
-import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
-import static javax.lang.model.element.ElementKind.CONSTRUCTOR;
-import static javax.lang.model.element.ElementKind.METHOD;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Iterables;
-import dagger.Module;
-import dagger.assisted.AssistedInject;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.binding.MembersInjectionBinding.InjectionSite;
-import dagger.internal.codegen.binding.ProductionBinding.ProductionKind;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import java.util.Optional;
-import java.util.function.BiFunction;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-
-/** A factory for {@link Binding} objects. */
-public final class BindingFactory {
-  private final DaggerTypes types;
-  private final KeyFactory keyFactory;
-  private final DependencyRequestFactory dependencyRequestFactory;
-  private final InjectionSiteFactory injectionSiteFactory;
-  private final DaggerElements elements;
-  private final InjectionAnnotations injectionAnnotations;
-  private final KotlinMetadataUtil metadataUtil;
-
-  @Inject
-  BindingFactory(
-      DaggerTypes types,
-      DaggerElements elements,
-      KeyFactory keyFactory,
-      DependencyRequestFactory dependencyRequestFactory,
-      InjectionSiteFactory injectionSiteFactory,
-      InjectionAnnotations injectionAnnotations,
-      KotlinMetadataUtil metadataUtil) {
-    this.types = types;
-    this.elements = elements;
-    this.keyFactory = keyFactory;
-    this.dependencyRequestFactory = dependencyRequestFactory;
-    this.injectionSiteFactory = injectionSiteFactory;
-    this.injectionAnnotations = injectionAnnotations;
-    this.metadataUtil = metadataUtil;
-  }
-
-  /**
-   * Returns an {@link dagger.model.BindingKind#INJECTION} binding.
-   *
-   * @param constructorElement the {@code @Inject}-annotated constructor
-   * @param resolvedType the parameterized type if the constructor is for a generic class and the
-   *     binding should be for the parameterized type
-   */
-  // TODO(dpb): See if we can just pass the parameterized type and not also the constructor.
-  public ProvisionBinding injectionBinding(
-      ExecutableElement constructorElement, Optional<TypeMirror> resolvedType) {
-    checkArgument(constructorElement.getKind().equals(CONSTRUCTOR));
-    checkArgument(
-        isAnnotationPresent(constructorElement, Inject.class)
-            || isAnnotationPresent(constructorElement, AssistedInject.class));
-    checkArgument(!injectionAnnotations.getQualifier(constructorElement).isPresent());
-
-    ExecutableType constructorType = MoreTypes.asExecutable(constructorElement.asType());
-    DeclaredType constructedType =
-        MoreTypes.asDeclared(constructorElement.getEnclosingElement().asType());
-    // If the class this is constructing has some type arguments, resolve everything.
-    if (!constructedType.getTypeArguments().isEmpty() && resolvedType.isPresent()) {
-      DeclaredType resolved = MoreTypes.asDeclared(resolvedType.get());
-      // Validate that we're resolving from the correct type.
-      checkState(
-          types.isSameType(types.erasure(resolved), types.erasure(constructedType)),
-          "erased expected type: %s, erased actual type: %s",
-          types.erasure(resolved),
-          types.erasure(constructedType));
-      constructorType = MoreTypes.asExecutable(types.asMemberOf(resolved, constructorElement));
-      constructedType = resolved;
-    }
-
-    // Collect all dependency requests within the provision method.
-    // Note: we filter out @Assisted parameters since these aren't considered dependency requests.
-    ImmutableSet.Builder<DependencyRequest> provisionDependencies = ImmutableSet.builder();
-    for (int i = 0; i < constructorElement.getParameters().size(); i++) {
-      VariableElement parameter = constructorElement.getParameters().get(i);
-      TypeMirror parameterType = constructorType.getParameterTypes().get(i);
-      if (!AssistedInjectionAnnotations.isAssistedParameter(parameter)) {
-        provisionDependencies.add(
-            dependencyRequestFactory.forRequiredResolvedVariable(parameter, parameterType));
-      }
-    }
-
-    Key key = keyFactory.forInjectConstructorWithResolvedType(constructedType);
-    ProvisionBinding.Builder builder =
-        ProvisionBinding.builder()
-            .contributionType(ContributionType.UNIQUE)
-            .bindingElement(constructorElement)
-            .key(key)
-            .provisionDependencies(provisionDependencies.build())
-            .injectionSites(injectionSiteFactory.getInjectionSites(constructedType))
-            .kind(
-                isAnnotationPresent(constructorElement, AssistedInject.class)
-                    ? ASSISTED_INJECTION
-                    : INJECTION)
-            .scope(uniqueScopeOf(constructorElement.getEnclosingElement()));
-
-    TypeElement bindingTypeElement = MoreElements.asType(constructorElement.getEnclosingElement());
-    if (hasNonDefaultTypeParameters(bindingTypeElement, key.type(), types)) {
-      builder.unresolved(injectionBinding(constructorElement, Optional.empty()));
-    }
-    return builder.build();
-  }
-
-  public ProvisionBinding assistedFactoryBinding(
-      TypeElement factory, Optional<TypeMirror> resolvedType) {
-
-    // If the class this is constructing has some type arguments, resolve everything.
-    DeclaredType factoryType = MoreTypes.asDeclared(factory.asType());
-    if (!factoryType.getTypeArguments().isEmpty() && resolvedType.isPresent()) {
-      DeclaredType resolved = MoreTypes.asDeclared(resolvedType.get());
-      // Validate that we're resolving from the correct type by checking that the erasure of the
-      // resolvedType is the same as the erasure of the factoryType.
-      checkState(
-          types.isSameType(types.erasure(resolved), types.erasure(factoryType)),
-          "erased expected type: %s, erased actual type: %s",
-          types.erasure(resolved),
-          types.erasure(factoryType));
-      factoryType = resolved;
-    }
-
-    ExecutableElement factoryMethod =
-        AssistedInjectionAnnotations.assistedFactoryMethod(factory, elements, types);
-    ExecutableType factoryMethodType =
-        MoreTypes.asExecutable(types.asMemberOf(factoryType, factoryMethod));
-    return ProvisionBinding.builder()
-        .contributionType(ContributionType.UNIQUE)
-        .key(Key.builder(factoryType).build())
-        .bindingElement(factory)
-        .provisionDependencies(
-            ImmutableSet.of(
-                DependencyRequest.builder()
-                    .key(Key.builder(factoryMethodType.getReturnType()).build())
-                    .kind(RequestKind.PROVIDER)
-                    .build()))
-        .kind(ASSISTED_FACTORY)
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#PROVISION} binding for a {@code @Provides}-annotated
-   * method.
-   *
-   * @param contributedBy the installed module that declares or inherits the method
-   */
-  public ProvisionBinding providesMethodBinding(
-      ExecutableElement providesMethod, TypeElement contributedBy) {
-    return setMethodBindingProperties(
-            ProvisionBinding.builder(),
-            providesMethod,
-            contributedBy,
-            keyFactory.forProvidesMethod(providesMethod, contributedBy),
-            this::providesMethodBinding)
-        .kind(PROVISION)
-        .scope(uniqueScopeOf(providesMethod))
-        .nullableType(getNullableType(providesMethod))
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#PRODUCTION} binding for a {@code @Produces}-annotated
-   * method.
-   *
-   * @param contributedBy the installed module that declares or inherits the method
-   */
-  public ProductionBinding producesMethodBinding(
-      ExecutableElement producesMethod, TypeElement contributedBy) {
-    // TODO(beder): Add nullability checking with Java 8.
-    ProductionBinding.Builder builder =
-        setMethodBindingProperties(
-                ProductionBinding.builder(),
-                producesMethod,
-                contributedBy,
-                keyFactory.forProducesMethod(producesMethod, contributedBy),
-                this::producesMethodBinding)
-            .kind(PRODUCTION)
-            .productionKind(ProductionKind.fromProducesMethod(producesMethod))
-            .thrownTypes(producesMethod.getThrownTypes())
-            .executorRequest(dependencyRequestFactory.forProductionImplementationExecutor())
-            .monitorRequest(dependencyRequestFactory.forProductionComponentMonitor());
-    return builder.build();
-  }
-
-  private <C extends ContributionBinding, B extends ContributionBinding.Builder<C, B>>
-      B setMethodBindingProperties(
-          B builder,
-          ExecutableElement method,
-          TypeElement contributedBy,
-          Key key,
-          BiFunction<ExecutableElement, TypeElement, C> create) {
-    checkArgument(method.getKind().equals(METHOD));
-    ExecutableType methodType =
-        MoreTypes.asExecutable(
-            types.asMemberOf(MoreTypes.asDeclared(contributedBy.asType()), method));
-    if (!types.isSameType(methodType, method.asType())) {
-      builder.unresolved(create.apply(method, MoreElements.asType(method.getEnclosingElement())));
-    }
-    boolean isKotlinObject =
-        metadataUtil.isObjectClass(contributedBy)
-            || metadataUtil.isCompanionObjectClass(contributedBy);
-    return builder
-        .contributionType(ContributionType.fromBindingElement(method))
-        .bindingElement(method)
-        .contributingModule(contributedBy)
-        .isContributingModuleKotlinObject(isKotlinObject)
-        .key(key)
-        .dependencies(
-            dependencyRequestFactory.forRequiredResolvedVariables(
-                method.getParameters(), methodType.getParameterTypes()))
-        .wrappedMapKeyAnnotation(wrapOptionalInEquivalence(getMapKey(method)));
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#MULTIBOUND_MAP} or {@link
-   * dagger.model.BindingKind#MULTIBOUND_SET} binding given a set of multibinding contribution
-   * bindings.
-   *
-   * @param key a key that may be satisfied by a multibinding
-   */
-  public ContributionBinding syntheticMultibinding(
-      Key key, Iterable<ContributionBinding> multibindingContributions) {
-    ContributionBinding.Builder<?, ?> builder =
-        multibindingRequiresProduction(key, multibindingContributions)
-            ? ProductionBinding.builder()
-            : ProvisionBinding.builder();
-    return builder
-        .contributionType(ContributionType.UNIQUE)
-        .key(key)
-        .dependencies(
-            dependencyRequestFactory.forMultibindingContributions(key, multibindingContributions))
-        .kind(bindingKindForMultibindingKey(key))
-        .build();
-  }
-
-  private boolean multibindingRequiresProduction(
-      Key key, Iterable<ContributionBinding> multibindingContributions) {
-    if (MapType.isMap(key)) {
-      MapType mapType = MapType.from(key);
-      if (mapType.valuesAreTypeOf(Producer.class) || mapType.valuesAreTypeOf(Produced.class)) {
-        return true;
-      }
-    } else if (SetType.isSet(key) && SetType.from(key).elementsAreTypeOf(Produced.class)) {
-      return true;
-    }
-    return Iterables.any(
-        multibindingContributions, binding -> binding.bindingType().equals(BindingType.PRODUCTION));
-  }
-
-  /** Returns a {@link dagger.model.BindingKind#COMPONENT} binding for the component. */
-  public ProvisionBinding componentBinding(TypeElement componentDefinitionType) {
-    checkNotNull(componentDefinitionType);
-    return ProvisionBinding.builder()
-        .contributionType(ContributionType.UNIQUE)
-        .bindingElement(componentDefinitionType)
-        .key(keyFactory.forType(componentDefinitionType.asType()))
-        .kind(COMPONENT)
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#COMPONENT_DEPENDENCY} binding for a component's
-   * dependency.
-   */
-  public ProvisionBinding componentDependencyBinding(ComponentRequirement dependency) {
-    checkNotNull(dependency);
-    return ProvisionBinding.builder()
-        .contributionType(ContributionType.UNIQUE)
-        .bindingElement(dependency.typeElement())
-        .key(keyFactory.forType(dependency.type()))
-        .kind(COMPONENT_DEPENDENCY)
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#COMPONENT_PROVISION} or {@link
-   * dagger.model.BindingKind#COMPONENT_PRODUCTION} binding for a method on a component's
-   * dependency.
-   *
-   * @param componentDescriptor the component with the dependency, not the dependency that has the
-   *     method
-   */
-  public ContributionBinding componentDependencyMethodBinding(
-      ComponentDescriptor componentDescriptor, ExecutableElement dependencyMethod) {
-    checkArgument(dependencyMethod.getKind().equals(METHOD));
-    checkArgument(dependencyMethod.getParameters().isEmpty());
-    ContributionBinding.Builder<?, ?> builder;
-    if (componentDescriptor.isProduction()
-        && isComponentProductionMethod(elements, dependencyMethod)) {
-      builder =
-          ProductionBinding.builder()
-              .key(keyFactory.forProductionComponentMethod(dependencyMethod))
-              .kind(COMPONENT_PRODUCTION)
-              .thrownTypes(dependencyMethod.getThrownTypes());
-    } else {
-      builder =
-          ProvisionBinding.builder()
-              .key(keyFactory.forComponentMethod(dependencyMethod))
-              .nullableType(getNullableType(dependencyMethod))
-              .kind(COMPONENT_PROVISION)
-              .scope(uniqueScopeOf(dependencyMethod));
-    }
-    return builder
-        .contributionType(ContributionType.UNIQUE)
-        .bindingElement(dependencyMethod)
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#BOUND_INSTANCE} binding for a
-   * {@code @BindsInstance}-annotated builder setter method or factory method parameter.
-   */
-  ProvisionBinding boundInstanceBinding(ComponentRequirement requirement, Element element) {
-    checkArgument(element instanceof VariableElement || element instanceof ExecutableElement);
-    VariableElement parameterElement =
-        element instanceof VariableElement
-            ? MoreElements.asVariable(element)
-            : getOnlyElement(MoreElements.asExecutable(element).getParameters());
-    return ProvisionBinding.builder()
-        .contributionType(ContributionType.UNIQUE)
-        .bindingElement(element)
-        .key(requirement.key().get())
-        .nullableType(getNullableType(parameterElement))
-        .kind(BOUND_INSTANCE)
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#SUBCOMPONENT_CREATOR} binding declared by a component
-   * method that returns a subcomponent builder. Use {{@link
-   * #subcomponentCreatorBinding(ImmutableSet)}} for bindings declared using {@link
-   * Module#subcomponents()}.
-   *
-   * @param component the component that declares or inherits the method
-   */
-  ProvisionBinding subcomponentCreatorBinding(
-      ExecutableElement subcomponentCreatorMethod, TypeElement component) {
-    checkArgument(subcomponentCreatorMethod.getKind().equals(METHOD));
-    checkArgument(subcomponentCreatorMethod.getParameters().isEmpty());
-    Key key =
-        keyFactory.forSubcomponentCreatorMethod(
-            subcomponentCreatorMethod, asDeclared(component.asType()));
-    return ProvisionBinding.builder()
-        .contributionType(ContributionType.UNIQUE)
-        .bindingElement(subcomponentCreatorMethod)
-        .key(key)
-        .kind(SUBCOMPONENT_CREATOR)
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#SUBCOMPONENT_CREATOR} binding declared using {@link
-   * Module#subcomponents()}.
-   */
-  ProvisionBinding subcomponentCreatorBinding(
-      ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
-    SubcomponentDeclaration subcomponentDeclaration = subcomponentDeclarations.iterator().next();
-    return ProvisionBinding.builder()
-        .contributionType(ContributionType.UNIQUE)
-        .key(subcomponentDeclaration.key())
-        .kind(SUBCOMPONENT_CREATOR)
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#DELEGATE} binding.
-   *
-   * @param delegateDeclaration the {@code @Binds}-annotated declaration
-   * @param actualBinding the binding that satisfies the {@code @Binds} declaration
-   */
-  ContributionBinding delegateBinding(
-      DelegateDeclaration delegateDeclaration, ContributionBinding actualBinding) {
-    switch (actualBinding.bindingType()) {
-      case PRODUCTION:
-        return buildDelegateBinding(
-            ProductionBinding.builder().nullableType(actualBinding.nullableType()),
-            delegateDeclaration,
-            Producer.class);
-
-      case PROVISION:
-        return buildDelegateBinding(
-            ProvisionBinding.builder()
-                .scope(uniqueScopeOf(delegateDeclaration.bindingElement().get()))
-                .nullableType(actualBinding.nullableType()),
-            delegateDeclaration,
-            Provider.class);
-
-      case MEMBERS_INJECTION: // fall-through to throw
-    }
-    throw new AssertionError("bindingType: " + actualBinding);
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#DELEGATE} binding used when there is no binding that
-   * satisfies the {@code @Binds} declaration.
-   */
-  public ContributionBinding unresolvedDelegateBinding(DelegateDeclaration delegateDeclaration) {
-    return buildDelegateBinding(
-        ProvisionBinding.builder().scope(uniqueScopeOf(delegateDeclaration.bindingElement().get())),
-        delegateDeclaration,
-        Provider.class);
-  }
-
-  private ContributionBinding buildDelegateBinding(
-      ContributionBinding.Builder<?, ?> builder,
-      DelegateDeclaration delegateDeclaration,
-      Class<?> frameworkType) {
-    boolean isKotlinObject =
-        metadataUtil.isObjectClass(delegateDeclaration.contributingModule().get())
-            || metadataUtil.isCompanionObjectClass(delegateDeclaration.contributingModule().get());
-    return builder
-        .contributionType(delegateDeclaration.contributionType())
-        .bindingElement(delegateDeclaration.bindingElement().get())
-        .contributingModule(delegateDeclaration.contributingModule().get())
-        .isContributingModuleKotlinObject(isKotlinObject)
-        .key(keyFactory.forDelegateBinding(delegateDeclaration, frameworkType))
-        .dependencies(delegateDeclaration.delegateRequest())
-        .wrappedMapKeyAnnotation(delegateDeclaration.wrappedMapKey())
-        .kind(DELEGATE)
-        .build();
-  }
-
-  /**
-   * Returns an {@link dagger.model.BindingKind#OPTIONAL} binding for {@code key}.
-   *
-   * @param requestKind the kind of request for the optional binding
-   * @param underlyingKeyBindings the possibly empty set of bindings that exist in the component for
-   *     the underlying (non-optional) key
-   */
-  ContributionBinding syntheticOptionalBinding(
-      Key key,
-      RequestKind requestKind,
-      ImmutableCollection<? extends Binding> underlyingKeyBindings) {
-    if (underlyingKeyBindings.isEmpty()) {
-      return ProvisionBinding.builder()
-          .contributionType(ContributionType.UNIQUE)
-          .key(key)
-          .kind(OPTIONAL)
-          .build();
-    }
-
-    boolean requiresProduction =
-        underlyingKeyBindings.stream()
-                .anyMatch(binding -> binding.bindingType() == BindingType.PRODUCTION)
-            || requestKind.equals(RequestKind.PRODUCER) // handles producerFromProvider cases
-            || requestKind.equals(RequestKind.PRODUCED); // handles producerFromProvider cases
-
-    return (requiresProduction ? ProductionBinding.builder() : ProvisionBinding.builder())
-        .contributionType(ContributionType.UNIQUE)
-        .key(key)
-        .kind(OPTIONAL)
-        .dependencies(dependencyRequestFactory.forSyntheticPresentOptionalBinding(key, requestKind))
-        .build();
-  }
-
-  /** Returns a {@link dagger.model.BindingKind#MEMBERS_INJECTOR} binding. */
-  public ProvisionBinding membersInjectorBinding(
-      Key key, MembersInjectionBinding membersInjectionBinding) {
-    return ProvisionBinding.builder()
-        .key(key)
-        .contributionType(ContributionType.UNIQUE)
-        .kind(MEMBERS_INJECTOR)
-        .bindingElement(MoreTypes.asTypeElement(membersInjectionBinding.key().type()))
-        .provisionDependencies(membersInjectionBinding.dependencies())
-        .injectionSites(membersInjectionBinding.injectionSites())
-        .build();
-  }
-
-  /**
-   * Returns a {@link dagger.model.BindingKind#MEMBERS_INJECTION} binding.
-   *
-   * @param resolvedType if {@code declaredType} is a generic class and {@code resolvedType} is a
-   *     parameterization of that type, the returned binding will be for the resolved type
-   */
-  // TODO(dpb): See if we can just pass one nongeneric/parameterized type.
-  public MembersInjectionBinding membersInjectionBinding(
-      DeclaredType declaredType, Optional<TypeMirror> resolvedType) {
-    // If the class this is injecting has some type arguments, resolve everything.
-    if (!declaredType.getTypeArguments().isEmpty() && resolvedType.isPresent()) {
-      DeclaredType resolved = asDeclared(resolvedType.get());
-      // Validate that we're resolving from the correct type.
-      checkState(
-          types.isSameType(types.erasure(resolved), types.erasure(declaredType)),
-          "erased expected type: %s, erased actual type: %s",
-          types.erasure(resolved),
-          types.erasure(declaredType));
-      declaredType = resolved;
-    }
-    ImmutableSortedSet<InjectionSite> injectionSites =
-        injectionSiteFactory.getInjectionSites(declaredType);
-    ImmutableSet<DependencyRequest> dependencies =
-        injectionSites.stream()
-            .flatMap(injectionSite -> injectionSite.dependencies().stream())
-            .collect(toImmutableSet());
-
-    Key key = keyFactory.forMembersInjectedType(declaredType);
-    TypeElement typeElement = MoreElements.asType(declaredType.asElement());
-    return new AutoValue_MembersInjectionBinding(
-        key,
-        dependencies,
-        typeElement,
-        hasNonDefaultTypeParameters(typeElement, key.type(), types)
-            ? Optional.of(
-                membersInjectionBinding(asDeclared(typeElement.asType()), Optional.empty()))
-            : Optional.empty(),
-        injectionSites);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/BindingGraph.java b/java/dagger/internal/codegen/binding/BindingGraph.java
deleted file mode 100644
index 4936a05..0000000
--- a/java/dagger/internal/codegen/binding/BindingGraph.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
-import static dagger.internal.codegen.extension.DaggerStreams.presentValues;
-import static dagger.internal.codegen.extension.DaggerStreams.stream;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Sets;
-import com.google.common.graph.Graphs;
-import com.google.common.graph.ImmutableNetwork;
-import com.google.common.graph.Traverser;
-import dagger.model.BindingGraph.ChildFactoryMethodEdge;
-import dagger.model.BindingGraph.ComponentNode;
-import dagger.model.BindingGraph.Edge;
-import dagger.model.BindingGraph.Node;
-import dagger.model.ComponentPath;
-import dagger.model.Key;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-
-/**
- * A graph that represents a single component or subcomponent within a fully validated top-level
- * binding graph.
- */
-@AutoValue
-public abstract class BindingGraph {
-
-  @AutoValue
-  abstract static class TopLevelBindingGraph extends dagger.model.BindingGraph {
-    static TopLevelBindingGraph create(
-        ImmutableNetwork<Node, Edge> network, boolean isFullBindingGraph) {
-      TopLevelBindingGraph topLevelBindingGraph =
-          new AutoValue_BindingGraph_TopLevelBindingGraph(network, isFullBindingGraph);
-
-      ImmutableMap<ComponentPath, ComponentNode> componentNodes =
-          topLevelBindingGraph.componentNodes().stream()
-              .collect(
-                  toImmutableMap(ComponentNode::componentPath, componentNode -> componentNode));
-
-      ImmutableSetMultimap.Builder<ComponentNode, ComponentNode> subcomponentNodesBuilder =
-          ImmutableSetMultimap.builder();
-      topLevelBindingGraph.componentNodes().stream()
-          .filter(componentNode -> !componentNode.componentPath().atRoot())
-          .forEach(
-              componentNode ->
-                  subcomponentNodesBuilder.put(
-                      componentNodes.get(componentNode.componentPath().parent()), componentNode));
-
-      // Set these fields directly on the instance rather than passing these in as input to the
-      // AutoValue to prevent exposing this data outside of the class.
-      topLevelBindingGraph.componentNodes = componentNodes;
-      topLevelBindingGraph.subcomponentNodes = subcomponentNodesBuilder.build();
-      return topLevelBindingGraph;
-    }
-
-    private ImmutableMap<ComponentPath, ComponentNode> componentNodes;
-    private ImmutableSetMultimap<ComponentNode, ComponentNode> subcomponentNodes;
-
-    TopLevelBindingGraph() {}
-
-    // This overrides dagger.model.BindingGraph with a more efficient implementation.
-    @Override
-    public Optional<ComponentNode> componentNode(ComponentPath componentPath) {
-      return componentNodes.containsKey(componentPath)
-          ? Optional.of(componentNodes.get(componentPath))
-          : Optional.empty();
-    }
-
-    /** Returns the set of subcomponent nodes of the given component node. */
-    ImmutableSet<ComponentNode> subcomponentNodes(ComponentNode componentNode) {
-      return subcomponentNodes.get(componentNode);
-    }
-
-    @Override
-    @Memoized
-    public ImmutableSetMultimap<Class<? extends Node>, ? extends Node> nodesByClass() {
-      return super.nodesByClass();
-    }
-  }
-
-  static BindingGraph create(
-      ComponentNode componentNode, TopLevelBindingGraph topLevelBindingGraph) {
-    return create(Optional.empty(), componentNode, topLevelBindingGraph);
-  }
-
-  private static BindingGraph create(
-      Optional<BindingGraph> parent,
-      ComponentNode componentNode,
-      TopLevelBindingGraph topLevelBindingGraph) {
-    ImmutableSet<BindingNode> reachableBindingNodes =
-        Graphs.reachableNodes(topLevelBindingGraph.network().asGraph(), componentNode).stream()
-            .filter(node -> isSubpath(componentNode.componentPath(), node.componentPath()))
-            .filter(node -> node instanceof BindingNode)
-            .map(node -> (BindingNode) node)
-            .collect(toImmutableSet());
-
-    // Construct the maps of the ContributionBindings and MembersInjectionBindings.
-    Map<Key, BindingNode> contributionBindings = new HashMap<>();
-    Map<Key, BindingNode> membersInjectionBindings = new HashMap<>();
-    for (BindingNode bindingNode : reachableBindingNodes) {
-      Map<Key, BindingNode> bindingsMap;
-      if (bindingNode.delegate() instanceof ContributionBinding) {
-        bindingsMap = contributionBindings;
-      } else if (bindingNode.delegate() instanceof MembersInjectionBinding) {
-        bindingsMap = membersInjectionBindings;
-      } else {
-        throw new AssertionError("Unexpected binding node type: " + bindingNode.delegate());
-      }
-
-      // TODO(bcorso): Mapping binding nodes by key is flawed since bindings that depend on local
-      // multibindings can have multiple nodes (one in each component). In this case, we choose the
-      // node in the child-most component since this is likely the node that users of this
-      // BindingGraph will want (and to remain consisted with LegacyBindingGraph). However, ideally
-      // we would avoid this ambiguity by getting dependencies directly from the top-level network.
-      // In particular, rather than using a Binding's list of DependencyRequests (which only
-      // contains the key) we would use the top-level network to find the DependencyEdges for a
-      // particular BindingNode.
-      Key key = bindingNode.key();
-      if (!bindingsMap.containsKey(key)
-          // Always choose the child-most binding node.
-          || bindingNode.componentPath().components().size()
-              > bindingsMap.get(key).componentPath().components().size()) {
-        bindingsMap.put(key, bindingNode);
-      }
-    }
-
-    BindingGraph bindingGraph = new AutoValue_BindingGraph(componentNode, topLevelBindingGraph);
-
-    ImmutableSet<ModuleDescriptor> modules =
-        ((ComponentNodeImpl) componentNode).componentDescriptor().modules();
-
-    ImmutableSet<ModuleDescriptor> inheritedModules =
-        parent.isPresent()
-            ? Sets.union(parent.get().ownedModules, parent.get().inheritedModules).immutableCopy()
-            : ImmutableSet.of();
-
-    // Set these fields directly on the instance rather than passing these in as input to the
-    // AutoValue to prevent exposing this data outside of the class.
-    bindingGraph.inheritedModules = inheritedModules;
-    bindingGraph.ownedModules = Sets.difference(modules, inheritedModules).immutableCopy();
-    bindingGraph.contributionBindings = ImmutableMap.copyOf(contributionBindings);
-    bindingGraph.membersInjectionBindings = ImmutableMap.copyOf(membersInjectionBindings);
-    bindingGraph.bindingModules =
-        contributionBindings.values().stream()
-            .map(BindingNode::contributingModule)
-            .flatMap(presentValues())
-            .collect(toImmutableSet());
-
-    return bindingGraph;
-  }
-
-  private ImmutableMap<Key, BindingNode> contributionBindings;
-  private ImmutableMap<Key, BindingNode> membersInjectionBindings;
-  private ImmutableSet<ModuleDescriptor> inheritedModules;
-  private ImmutableSet<ModuleDescriptor> ownedModules;
-  private ImmutableSet<TypeElement> bindingModules;
-
-  BindingGraph() {}
-
-  /** Returns the {@link ComponentNode} for this graph. */
-  public abstract ComponentNode componentNode();
-
-  /** Returns the {@link ComponentPath} for this graph. */
-  public final ComponentPath componentPath() {
-    return componentNode().componentPath();
-  }
-
-  /** Returns the {@link TopLevelBindingGraph} from which this graph is contained. */
-  public abstract TopLevelBindingGraph topLevelBindingGraph();
-
-  /** Returns the {@link ComponentDescriptor} for this graph */
-  public final ComponentDescriptor componentDescriptor() {
-    return ((ComponentNodeImpl) componentNode()).componentDescriptor();
-  }
-
-  /** Returns the {@link ContributionBinding} for the given {@link Key}. */
-  public final ContributionBinding contributionBinding(Key key) {
-    return (ContributionBinding) contributionBindings.get(key).delegate();
-  }
-
-  /**
-   * Returns the {@link MembersInjectionBinding} for the given {@link Key} or {@link
-   * Optional#empty()} if one does not exist.
-   */
-  public final Optional<MembersInjectionBinding> membersInjectionBinding(Key key) {
-    return membersInjectionBindings.containsKey(key)
-        ? Optional.of((MembersInjectionBinding) membersInjectionBindings.get(key).delegate())
-        : Optional.empty();
-  }
-
-  /** Returns the {@link TypeElement} for the component this graph represents. */
-  public final TypeElement componentTypeElement() {
-    return componentPath().currentComponent();
-  }
-
-  /**
-   * Returns the set of modules that are owned by this graph regardless of whether or not any of
-   * their bindings are used in this graph. For graphs representing top-level {@link
-   * dagger.Component components}, this set will be the same as {@linkplain
-   * ComponentDescriptor#modules() the component's transitive modules}. For {@linkplain Subcomponent
-   * subcomponents}, this set will be the transitive modules that are not owned by any of their
-   * ancestors.
-   */
-  public final ImmutableSet<TypeElement> ownedModuleTypes() {
-    return ownedModules.stream().map(ModuleDescriptor::moduleElement).collect(toImmutableSet());
-  }
-
-  /**
-   * Returns the factory method for this subcomponent, if it exists.
-   *
-   * <p>This factory method is the one defined in the parent component's interface.
-   *
-   * <p>In the example below, the {@link BindingGraph#factoryMethod} for {@code ChildComponent}
-   * would return the {@link ExecutableElement}: {@code childComponent(ChildModule1)} .
-   *
-   * <pre><code>
-   *   {@literal @Component}
-   *   interface ParentComponent {
-   *     ChildComponent childComponent(ChildModule1 childModule);
-   *   }
-   * </code></pre>
-   */
-  // TODO(b/73294201): Consider returning the resolved ExecutableType for the factory method.
-  public final Optional<ExecutableElement> factoryMethod() {
-    return topLevelBindingGraph().network().inEdges(componentNode()).stream()
-        .filter(edge -> edge instanceof ChildFactoryMethodEdge)
-        .map(edge -> ((ChildFactoryMethodEdge) edge).factoryMethod())
-        .collect(toOptional());
-  }
-
-  /**
-   * Returns a map between the {@linkplain ComponentRequirement component requirement} and the
-   * corresponding {@link VariableElement} for each module parameter in the {@linkplain
-   * BindingGraph#factoryMethod factory method}.
-   */
-  // TODO(dpb): Consider disallowing modules if none of their bindings are used.
-  public final ImmutableMap<ComponentRequirement, VariableElement> factoryMethodParameters() {
-    return factoryMethod().get().getParameters().stream()
-        .collect(
-            toImmutableMap(
-                parameter -> ComponentRequirement.forModule(parameter.asType()),
-                parameter -> parameter));
-  }
-
-  /**
-   * The types for which the component needs instances.
-   *
-   * <ul>
-   *   <li>component dependencies
-   *   <li>owned modules with concrete instance bindings that are used in the graph
-   *   <li>bound instances
-   * </ul>
-   */
-  @Memoized
-  public ImmutableSet<ComponentRequirement> componentRequirements() {
-    ImmutableSet<TypeElement> requiredModules =
-        stream(Traverser.forTree(BindingGraph::subgraphs).depthFirstPostOrder(this))
-            .flatMap(graph -> graph.bindingModules.stream())
-            .filter(ownedModuleTypes()::contains)
-            .collect(toImmutableSet());
-    ImmutableSet.Builder<ComponentRequirement> requirements = ImmutableSet.builder();
-    componentDescriptor().requirements().stream()
-        .filter(
-            requirement ->
-                !requirement.kind().isModule()
-                    || requiredModules.contains(requirement.typeElement()))
-        .forEach(requirements::add);
-    if (factoryMethod().isPresent()) {
-      requirements.addAll(factoryMethodParameters().keySet());
-    }
-    return requirements.build();
-  }
-
-  /** Returns all {@link ComponentDescriptor}s in the {@link TopLevelBindingGraph}. */
-  public final ImmutableSet<ComponentDescriptor> componentDescriptors() {
-    return topLevelBindingGraph().componentNodes().stream()
-        .map(componentNode -> ((ComponentNodeImpl) componentNode).componentDescriptor())
-        .collect(toImmutableSet());
-  }
-
-  @Memoized
-  public ImmutableList<BindingGraph> subgraphs() {
-    return topLevelBindingGraph().subcomponentNodes(componentNode()).stream()
-        .map(subcomponent -> create(Optional.of(this), subcomponent, topLevelBindingGraph()))
-        .collect(toImmutableList());
-  }
-
-  public final ImmutableSet<BindingNode> bindingNodes(Key key) {
-    ImmutableSet.Builder<BindingNode> builder = ImmutableSet.builder();
-    if (contributionBindings.containsKey(key)) {
-      builder.add(contributionBindings.get(key));
-    }
-    if (membersInjectionBindings.containsKey(key)) {
-      builder.add(membersInjectionBindings.get(key));
-    }
-    return builder.build();
-  }
-
-  @Memoized
-  public ImmutableSet<BindingNode> bindingNodes() {
-    return ImmutableSet.<BindingNode>builder()
-        .addAll(contributionBindings.values())
-        .addAll(membersInjectionBindings.values())
-        .build();
-  }
-
-  // TODO(bcorso): Move this to ComponentPath
-  private static boolean isSubpath(ComponentPath path, ComponentPath subpath) {
-    if (path.components().size() < subpath.components().size()) {
-      return false;
-    }
-    for (int i = 0; i < subpath.components().size(); i++) {
-      if (!path.components().get(i).equals(subpath.components().get(i))) {
-        return false;
-      }
-    }
-    return true;
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/BindingGraphConverter.java b/java/dagger/internal/codegen/binding/BindingGraphConverter.java
deleted file mode 100644
index b882b37..0000000
--- a/java/dagger/internal/codegen/binding/BindingGraphConverter.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * 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.binding;
-
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.common.base.Verify.verify;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.extension.DaggerGraphs.unreachableNodes;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Iterators;
-import com.google.common.graph.ImmutableNetwork;
-import com.google.common.graph.MutableNetwork;
-import com.google.common.graph.Network;
-import com.google.common.graph.NetworkBuilder;
-import dagger.internal.codegen.binding.BindingGraph.TopLevelBindingGraph;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.model.BindingGraph.ComponentNode;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.BindingGraph.Edge;
-import dagger.model.BindingGraph.MissingBinding;
-import dagger.model.BindingGraph.Node;
-import dagger.model.ComponentPath;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-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.TypeMirror;
-
-/** Converts {@link BindingGraph}s to {@link dagger.model.BindingGraph}s. */
-final class BindingGraphConverter {
-  private final BindingDeclarationFormatter bindingDeclarationFormatter;
-
-  @Inject
-  BindingGraphConverter(BindingDeclarationFormatter bindingDeclarationFormatter) {
-    this.bindingDeclarationFormatter = bindingDeclarationFormatter;
-  }
-
-  /**
-   * Creates the external {@link dagger.model.BindingGraph} representing the given internal {@link
-   * BindingGraph}.
-   */
-  BindingGraph convert(LegacyBindingGraph legacyBindingGraph, boolean isFullBindingGraph) {
-    MutableNetwork<Node, Edge> network = asNetwork(legacyBindingGraph);
-    ComponentNode rootNode = rootComponentNode(network);
-
-    // When bindings are copied down into child graphs because they transitively depend on local
-    // multibindings or optional bindings, the parent-owned binding is still there. If that
-    // parent-owned binding is not reachable from its component, it doesn't need to be in the graph
-    // because it will never be used. So remove all nodes that are not reachable from the root
-    // component—unless we're converting a full binding graph.
-    if (!isFullBindingGraph) {
-      unreachableNodes(network.asGraph(), rootNode).forEach(network::removeNode);
-    }
-
-    TopLevelBindingGraph topLevelBindingGraph =
-        TopLevelBindingGraph.create(ImmutableNetwork.copyOf(network), isFullBindingGraph);
-    return BindingGraph.create(rootNode, topLevelBindingGraph);
-  }
-
-  private MutableNetwork<Node, Edge> asNetwork(LegacyBindingGraph graph) {
-    Converter converter = new Converter(bindingDeclarationFormatter);
-    converter.visitRootComponent(graph);
-    return converter.network;
-  }
-
-  // TODO(dpb): Example of BindingGraph logic applied to derived networks.
-  private ComponentNode rootComponentNode(Network<Node, Edge> network) {
-    return (ComponentNode)
-        Iterables.find(
-            network.nodes(),
-            node -> node instanceof ComponentNode && node.componentPath().atRoot());
-  }
-
-  /**
-   * Used as a cache key to make sure resolved bindings are cached per component path.
-   * This is required so that binding nodes are not reused across different branches of the
-   * graph since the ResolvedBindings class only contains the component and not the path.
-   */
-  @AutoValue
-  abstract static class ResolvedBindingsWithPath {
-    abstract ResolvedBindings resolvedBindings();
-    abstract ComponentPath componentPath();
-
-    static ResolvedBindingsWithPath create(
-        ResolvedBindings resolvedBindings, ComponentPath componentPath) {
-      return new AutoValue_BindingGraphConverter_ResolvedBindingsWithPath(
-          resolvedBindings, componentPath);
-    }
-  }
-
-  private static final class Converter {
-    /** The path from the root graph to the currently visited graph. */
-    private final Deque<LegacyBindingGraph> bindingGraphPath = new ArrayDeque<>();
-
-    /** The {@link ComponentPath} for each component in {@link #bindingGraphPath}. */
-    private final Deque<ComponentPath> componentPaths = new ArrayDeque<>();
-
-    private final BindingDeclarationFormatter bindingDeclarationFormatter;
-    private final MutableNetwork<Node, Edge> network =
-        NetworkBuilder.directed().allowsParallelEdges(true).allowsSelfLoops(true).build();
-    private final Set<BindingNode> bindings = new HashSet<>();
-
-    private final Map<ResolvedBindingsWithPath, ImmutableSet<BindingNode>> resolvedBindingsMap =
-        new HashMap<>();
-
-    /** Constructs a converter for a root (component, not subcomponent) binding graph. */
-    private Converter(BindingDeclarationFormatter bindingDeclarationFormatter) {
-      this.bindingDeclarationFormatter = bindingDeclarationFormatter;
-    }
-
-    private void visitRootComponent(LegacyBindingGraph graph) {
-      visitComponent(graph, null);
-    }
-
-    /**
-     * Called once for each component in a component hierarchy.
-     *
-     * <p>This implementation does the following:
-     *
-     * <ol>
-     *   <li>If this component is installed in its parent by a subcomponent factory method, calls
-     *       {@link #visitSubcomponentFactoryMethod(ComponentNode, ComponentNode,
-     *       ExecutableElement)}.
-     *   <li>For each entry point in the component, calls {@link #visitEntryPoint(ComponentNode,
-     *       DependencyRequest)}.
-     *   <li>For each child component, calls {@link #visitComponent(LegacyBindingGraph,
-     *       ComponentNode)}, updating the traversal state.
-     * </ol>
-     *
-     * @param graph the currently visited graph
-     */
-    private void visitComponent(LegacyBindingGraph graph, ComponentNode parentComponent) {
-      bindingGraphPath.addLast(graph);
-      ComponentPath graphPath =
-          ComponentPath.create(
-              bindingGraphPath.stream()
-                  .map(LegacyBindingGraph::componentDescriptor)
-                  .map(ComponentDescriptor::typeElement)
-                  .collect(toImmutableList()));
-      componentPaths.addLast(graphPath);
-      ComponentNode currentComponent =
-          ComponentNodeImpl.create(componentPath(), graph.componentDescriptor());
-
-      network.addNode(currentComponent);
-
-      for (ComponentMethodDescriptor entryPointMethod :
-          graph.componentDescriptor().entryPointMethods()) {
-        visitEntryPoint(currentComponent, entryPointMethod.dependencyRequest().get());
-      }
-
-      for (ResolvedBindings resolvedBindings : graph.resolvedBindings()) {
-        for (BindingNode binding : bindingNodes(resolvedBindings)) {
-          if (bindings.add(binding)) {
-            network.addNode(binding);
-            for (DependencyRequest dependencyRequest : binding.dependencies()) {
-              addDependencyEdges(binding, dependencyRequest);
-            }
-          }
-          if (binding.kind().equals(SUBCOMPONENT_CREATOR)
-              && binding.componentPath().equals(currentComponent.componentPath())) {
-            network.addEdge(
-                binding,
-                subcomponentNode(binding.key().type(), graph),
-                new SubcomponentCreatorBindingEdgeImpl(
-                    resolvedBindings.subcomponentDeclarations()));
-          }
-        }
-      }
-
-      if (bindingGraphPath.size() > 1) {
-        LegacyBindingGraph parent = Iterators.get(bindingGraphPath.descendingIterator(), 1);
-        parent
-            .componentDescriptor()
-            .getFactoryMethodForChildComponent(graph.componentDescriptor())
-            .ifPresent(
-                childFactoryMethod ->
-                    visitSubcomponentFactoryMethod(
-                        parentComponent, currentComponent, childFactoryMethod.methodElement()));
-      }
-
-      for (LegacyBindingGraph child : graph.subgraphs()) {
-        visitComponent(child, currentComponent);
-      }
-
-      verify(bindingGraphPath.removeLast().equals(graph));
-      verify(componentPaths.removeLast().equals(graphPath));
-    }
-
-    /**
-     * Called once for each entry point in a component.
-     *
-     * @param componentNode the component that contains the entry point
-     * @param entryPoint the entry point to visit
-     */
-    private void visitEntryPoint(ComponentNode componentNode, DependencyRequest entryPoint) {
-      addDependencyEdges(componentNode, entryPoint);
-    }
-
-    /**
-     * Called if this component was installed in its parent by a subcomponent factory method.
-     *
-     * @param parentComponent the parent graph
-     * @param currentComponent the currently visited graph
-     * @param factoryMethod the factory method in the parent component that declares that the
-     *     current component is a child
-     */
-    private void visitSubcomponentFactoryMethod(
-        ComponentNode parentComponent,
-        ComponentNode currentComponent,
-        ExecutableElement factoryMethod) {
-      network.addEdge(
-          parentComponent,
-          currentComponent,
-          new ChildFactoryMethodEdgeImpl(factoryMethod));
-    }
-
-    /**
-     * Returns an immutable snapshot of the path from the root component to the currently visited
-     * component.
-     */
-    private ComponentPath componentPath() {
-      return componentPaths.getLast();
-    }
-
-    /**
-     * Returns the subpath from the root component to the matching {@code ancestor} of the current
-     * component.
-     */
-    private ComponentPath pathFromRootToAncestor(TypeElement ancestor) {
-      for (ComponentPath componentPath : componentPaths) {
-        if (componentPath.currentComponent().equals(ancestor)) {
-          return componentPath;
-        }
-      }
-      throw new IllegalArgumentException(
-          String.format(
-              "%s is not in the current path: %s", ancestor.getQualifiedName(), componentPath()));
-    }
-
-    /**
-     * Returns the LegacyBindingGraph for {@code ancestor}, where {@code ancestor} is in the
-     * component path of the current traversal.
-     */
-    private LegacyBindingGraph graphForAncestor(TypeElement ancestor) {
-      for (LegacyBindingGraph graph : bindingGraphPath) {
-        if (graph.componentDescriptor().typeElement().equals(ancestor)) {
-          return graph;
-        }
-      }
-      throw new IllegalArgumentException(
-          String.format(
-              "%s is not in the current path: %s", ancestor.getQualifiedName(), componentPath()));
-    }
-
-    /**
-     * Adds a {@link dagger.model.BindingGraph.DependencyEdge} from a node to the binding(s) that
-     * satisfy a dependency request.
-     */
-    private void addDependencyEdges(Node source, DependencyRequest dependencyRequest) {
-      ResolvedBindings dependencies = resolvedDependencies(source, dependencyRequest);
-      if (dependencies.isEmpty()) {
-        addDependencyEdge(source, dependencyRequest, missingBindingNode(dependencies));
-      } else {
-        for (BindingNode dependency : bindingNodes(dependencies)) {
-          addDependencyEdge(source, dependencyRequest, dependency);
-        }
-      }
-    }
-
-    private void addDependencyEdge(
-        Node source, DependencyRequest dependencyRequest, Node dependency) {
-      network.addNode(dependency);
-      if (!hasDependencyEdge(source, dependency, dependencyRequest)) {
-        network.addEdge(
-            source,
-            dependency,
-            new DependencyEdgeImpl(dependencyRequest, source instanceof ComponentNode));
-      }
-    }
-
-    private boolean hasDependencyEdge(
-        Node source, Node dependency, DependencyRequest dependencyRequest) {
-      // An iterative approach is used instead of a Stream because this method is called in a hot
-      // loop, and the Stream calculates the size of network.edgesConnecting(), which is slow. This
-      // seems to be because caculating the edges connecting two nodes in a Network that supports
-      // parallel edges is must check the equality of many nodes, and BindingNode's equality
-      // semantics drag in the equality of many other expensive objects
-      for (Edge edge : network.edgesConnecting(source, dependency)) {
-        if (edge instanceof DependencyEdge) {
-          if (((DependencyEdge) edge).dependencyRequest().equals(dependencyRequest)) {
-            return true;
-          }
-        }
-      }
-      return false;
-    }
-
-    private ResolvedBindings resolvedDependencies(
-        Node source, DependencyRequest dependencyRequest) {
-      return graphForAncestor(source.componentPath().currentComponent())
-          .resolvedBindings(bindingRequest(dependencyRequest));
-    }
-
-    private ImmutableSet<BindingNode> bindingNodes(ResolvedBindings resolvedBindings) {
-      ResolvedBindingsWithPath resolvedBindingsWithPath =
-          ResolvedBindingsWithPath.create(resolvedBindings, componentPath());
-      return resolvedBindingsMap.computeIfAbsent(
-          resolvedBindingsWithPath, this::uncachedBindingNodes);
-    }
-
-    private ImmutableSet<BindingNode> uncachedBindingNodes(
-        ResolvedBindingsWithPath resolvedBindingsWithPath) {
-      ImmutableSet.Builder<BindingNode> bindingNodes = ImmutableSet.builder();
-      resolvedBindingsWithPath.resolvedBindings()
-          .allBindings()
-          .asMap()
-          .forEach(
-              (component, bindings) -> {
-                for (Binding binding : bindings) {
-                  bindingNodes.add(
-                      bindingNode(resolvedBindingsWithPath.resolvedBindings(), binding, component));
-                }
-              });
-      return bindingNodes.build();
-    }
-
-    private BindingNode bindingNode(
-        ResolvedBindings resolvedBindings, Binding binding, TypeElement owningComponent) {
-      return BindingNode.create(
-          pathFromRootToAncestor(owningComponent),
-          binding,
-          resolvedBindings.multibindingDeclarations(),
-          resolvedBindings.optionalBindingDeclarations(),
-          resolvedBindings.subcomponentDeclarations(),
-          bindingDeclarationFormatter);
-    }
-
-    private MissingBinding missingBindingNode(ResolvedBindings dependencies) {
-      // Put all missing binding nodes in the root component. This simplifies the binding graph
-      // and produces better error messages for users since all dependents point to the same node.
-      return MissingBindingImpl.create(
-          ComponentPath.create(ImmutableList.of(componentPath().rootComponent())),
-          dependencies.key());
-    }
-
-    private ComponentNode subcomponentNode(
-        TypeMirror subcomponentBuilderType, LegacyBindingGraph graph) {
-      TypeElement subcomponentBuilderElement = asTypeElement(subcomponentBuilderType);
-      ComponentDescriptor subcomponent =
-          graph.componentDescriptor().getChildComponentWithBuilderType(subcomponentBuilderElement);
-      return ComponentNodeImpl.create(
-          componentPath().childPath(subcomponent.typeElement()), subcomponent);
-    }
-  }
-
-  @AutoValue
-  abstract static class MissingBindingImpl extends MissingBinding {
-    static MissingBinding create(ComponentPath component, Key key) {
-      return new AutoValue_BindingGraphConverter_MissingBindingImpl(component, key);
-    }
-
-    @Memoized
-    @Override
-    public abstract int hashCode();
-
-    @Override
-    public abstract boolean equals(Object o);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/BindingGraphFactory.java b/java/dagger/internal/codegen/binding/BindingGraphFactory.java
deleted file mode 100644
index 2c15e26..0000000
--- a/java/dagger/internal/codegen/binding/BindingGraphFactory.java
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.auto.common.MoreTypes.isType;
-import static com.google.auto.common.MoreTypes.isTypeOf;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.base.RequestKinds.getRequestKind;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedFactoryType;
-import static dagger.internal.codegen.binding.ComponentDescriptor.isComponentContributionMethod;
-import static dagger.internal.codegen.binding.SourceFiles.generatedMonitoringModuleName;
-import static dagger.model.BindingKind.ASSISTED_INJECTION;
-import static dagger.model.BindingKind.DELEGATE;
-import static dagger.model.BindingKind.INJECTION;
-import static dagger.model.BindingKind.OPTIONAL;
-import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
-import static dagger.model.RequestKind.MEMBERS_INJECTION;
-import static java.util.function.Predicate.isEqual;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimaps;
-import dagger.MembersInjector;
-import dagger.Reusable;
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.OptionalType;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.model.Scope;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import dagger.producers.internal.ProductionExecutorModule;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Queue;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.inject.Singleton;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeKind;
-
-/** A factory for {@link BindingGraph} objects. */
-@Singleton
-public final class BindingGraphFactory implements ClearableCache {
-
-  private final DaggerElements elements;
-  private final InjectBindingRegistry injectBindingRegistry;
-  private final KeyFactory keyFactory;
-  private final BindingFactory bindingFactory;
-  private final ModuleDescriptor.Factory moduleDescriptorFactory;
-  private final BindingGraphConverter bindingGraphConverter;
-  private final Map<Key, ImmutableSet<Key>> keysMatchingRequestCache = new HashMap<>();
-  private final CompilerOptions compilerOptions;
-
-  @Inject
-  BindingGraphFactory(
-      DaggerElements elements,
-      InjectBindingRegistry injectBindingRegistry,
-      KeyFactory keyFactory,
-      BindingFactory bindingFactory,
-      ModuleDescriptor.Factory moduleDescriptorFactory,
-      BindingGraphConverter bindingGraphConverter,
-      CompilerOptions compilerOptions) {
-    this.elements = elements;
-    this.injectBindingRegistry = injectBindingRegistry;
-    this.keyFactory = keyFactory;
-    this.bindingFactory = bindingFactory;
-    this.moduleDescriptorFactory = moduleDescriptorFactory;
-    this.bindingGraphConverter = bindingGraphConverter;
-    this.compilerOptions = compilerOptions;
-  }
-
-  /**
-   * Creates a binding graph for a component.
-   *
-   * @param createFullBindingGraph if {@code true}, the binding graph will include all bindings;
-   *     otherwise it will include only bindings reachable from at least one entry point
-   */
-  public BindingGraph create(
-      ComponentDescriptor componentDescriptor, boolean createFullBindingGraph) {
-    return bindingGraphConverter.convert(
-        createLegacyBindingGraph(Optional.empty(), componentDescriptor, createFullBindingGraph),
-        createFullBindingGraph);
-  }
-
-  private LegacyBindingGraph createLegacyBindingGraph(
-      Optional<Resolver> parentResolver,
-      ComponentDescriptor componentDescriptor,
-      boolean createFullBindingGraph) {
-    ImmutableSet.Builder<ContributionBinding> explicitBindingsBuilder = ImmutableSet.builder();
-    ImmutableSet.Builder<DelegateDeclaration> delegatesBuilder = ImmutableSet.builder();
-    ImmutableSet.Builder<OptionalBindingDeclaration> optionalsBuilder = ImmutableSet.builder();
-
-    if (componentDescriptor.isRealComponent()) {
-      // binding for the component itself
-      explicitBindingsBuilder.add(
-          bindingFactory.componentBinding(componentDescriptor.typeElement()));
-    }
-
-    // Collect Component dependencies.
-    for (ComponentRequirement dependency : componentDescriptor.dependencies()) {
-      explicitBindingsBuilder.add(bindingFactory.componentDependencyBinding(dependency));
-      List<ExecutableElement> dependencyMethods =
-          methodsIn(elements.getAllMembers(dependency.typeElement()));
-
-      // Within a component dependency, we want to allow the same method to appear multiple
-      // times assuming it is the exact same method. We do this by tracking a set of bindings
-      // we've already added with the binding element removed since that is the only thing
-      // allowed to differ.
-      HashMultimap<String, ContributionBinding> dedupeBindings = HashMultimap.create();
-      for (ExecutableElement method : dependencyMethods) {
-        // MembersInjection methods aren't "provided" explicitly, so ignore them.
-        if (isComponentContributionMethod(elements, method)) {
-          ContributionBinding binding = bindingFactory.componentDependencyMethodBinding(
-              componentDescriptor, method);
-          if (dedupeBindings.put(
-              method.getSimpleName().toString(),
-              // Remove the binding element since we know that will be different, but everything
-              // else we want to be the same to consider it a duplicate.
-              binding.toBuilder().clearBindingElement().build())) {
-            explicitBindingsBuilder.add(binding);
-          }
-        }
-      }
-    }
-
-    // Collect bindings on the creator.
-    componentDescriptor
-        .creatorDescriptor()
-        .ifPresent(
-            creatorDescriptor ->
-                creatorDescriptor.boundInstanceRequirements().stream()
-                    .map(
-                        requirement ->
-                            bindingFactory.boundInstanceBinding(
-                                requirement, creatorDescriptor.elementForRequirement(requirement)))
-                    .forEach(explicitBindingsBuilder::add));
-
-    componentDescriptor
-        .childComponentsDeclaredByBuilderEntryPoints()
-        .forEach(
-            (builderEntryPoint, childComponent) -> {
-              if (!componentDescriptor
-                  .childComponentsDeclaredByModules()
-                  .contains(childComponent)) {
-                explicitBindingsBuilder.add(
-                    bindingFactory.subcomponentCreatorBinding(
-                        builderEntryPoint.methodElement(), componentDescriptor.typeElement()));
-              }
-            });
-
-    ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations = ImmutableSet.builder();
-    ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarations = ImmutableSet.builder();
-
-    // Collect transitive module bindings and multibinding declarations.
-    for (ModuleDescriptor moduleDescriptor : modules(componentDescriptor, parentResolver)) {
-      explicitBindingsBuilder.addAll(moduleDescriptor.bindings());
-      multibindingDeclarations.addAll(moduleDescriptor.multibindingDeclarations());
-      subcomponentDeclarations.addAll(moduleDescriptor.subcomponentDeclarations());
-      delegatesBuilder.addAll(moduleDescriptor.delegateDeclarations());
-      optionalsBuilder.addAll(moduleDescriptor.optionalDeclarations());
-    }
-
-    final Resolver requestResolver =
-        new Resolver(
-            parentResolver,
-            componentDescriptor,
-            indexBindingDeclarationsByKey(explicitBindingsBuilder.build()),
-            indexBindingDeclarationsByKey(multibindingDeclarations.build()),
-            indexBindingDeclarationsByKey(subcomponentDeclarations.build()),
-            indexBindingDeclarationsByKey(delegatesBuilder.build()),
-            indexBindingDeclarationsByKey(optionalsBuilder.build()));
-
-    componentDescriptor.entryPointMethods().stream()
-        .map(method -> method.dependencyRequest().get())
-        .forEach(
-            entryPoint -> {
-              if (entryPoint.kind().equals(MEMBERS_INJECTION)) {
-                requestResolver.resolveMembersInjection(entryPoint.key());
-              } else {
-                requestResolver.resolve(entryPoint.key());
-              }
-            });
-
-    if (createFullBindingGraph) {
-      // Resolve the keys for all bindings in all modules, stripping any multibinding contribution
-      // identifier so that the multibinding itself is resolved.
-      modules(componentDescriptor, parentResolver).stream()
-          .flatMap(module -> module.allBindingKeys().stream())
-          .map(key -> key.toBuilder().multibindingContributionIdentifier(Optional.empty()).build())
-          .forEach(requestResolver::resolve);
-    }
-
-    // Resolve all bindings for subcomponents, creating subgraphs for all subcomponents that have
-    // been detected during binding resolution. If a binding for a subcomponent is never resolved,
-    // no BindingGraph will be created for it and no implementation will be generated. This is
-    // done in a queue since resolving one subcomponent might resolve a key for a subcomponent
-    // from a parent graph. This is done until no more new subcomponents are resolved.
-    Set<ComponentDescriptor> resolvedSubcomponents = new HashSet<>();
-    ImmutableList.Builder<LegacyBindingGraph> subgraphs = ImmutableList.builder();
-    for (ComponentDescriptor subcomponent :
-        Iterables.consumingIterable(requestResolver.subcomponentsToResolve)) {
-      if (resolvedSubcomponents.add(subcomponent)) {
-        subgraphs.add(
-            createLegacyBindingGraph(
-                Optional.of(requestResolver), subcomponent, createFullBindingGraph));
-      }
-    }
-
-    return new LegacyBindingGraph(
-        componentDescriptor,
-        ImmutableMap.copyOf(requestResolver.getResolvedContributionBindings()),
-        ImmutableMap.copyOf(requestResolver.getResolvedMembersInjectionBindings()),
-        ImmutableList.copyOf(subgraphs.build()));
-  }
-
-  /**
-   * Returns all the modules that should be installed in the component. For production components
-   * and production subcomponents that have a parent that is not a production component or
-   * subcomponent, also includes the production monitoring module for the component and the
-   * production executor module.
-   */
-  private ImmutableSet<ModuleDescriptor> modules(
-      ComponentDescriptor componentDescriptor, Optional<Resolver> parentResolver) {
-    return shouldIncludeImplicitProductionModules(componentDescriptor, parentResolver)
-        ? new ImmutableSet.Builder<ModuleDescriptor>()
-            .addAll(componentDescriptor.modules())
-            .add(descriptorForMonitoringModule(componentDescriptor.typeElement()))
-            .add(descriptorForProductionExecutorModule())
-            .build()
-        : componentDescriptor.modules();
-  }
-
-  private boolean shouldIncludeImplicitProductionModules(
-      ComponentDescriptor component, Optional<Resolver> parentResolver) {
-    return component.isProduction()
-        && ((!component.isSubcomponent() && component.isRealComponent())
-            || (parentResolver.isPresent()
-                && !parentResolver.get().componentDescriptor.isProduction()));
-  }
-
-  /**
-   * Returns a descriptor for a generated module that handles monitoring for production components.
-   * This module is generated in the {@link
-   * dagger.internal.codegen.validation.MonitoringModuleProcessingStep}.
-   *
-   * @throws TypeNotPresentException if the module has not been generated yet. This will cause the
-   *     processor to retry in a later processing round.
-   */
-  private ModuleDescriptor descriptorForMonitoringModule(TypeElement componentDefinitionType) {
-    return moduleDescriptorFactory.create(
-        elements.checkTypePresent(
-            generatedMonitoringModuleName(componentDefinitionType).toString()));
-  }
-
-  /** Returns a descriptor {@link ProductionExecutorModule}. */
-  private ModuleDescriptor descriptorForProductionExecutorModule() {
-    return moduleDescriptorFactory.create(elements.getTypeElement(ProductionExecutorModule.class));
-  }
-
-  /** Indexes {@code bindingDeclarations} by {@link BindingDeclaration#key()}. */
-  private static <T extends BindingDeclaration>
-      ImmutableSetMultimap<Key, T> indexBindingDeclarationsByKey(Iterable<T> declarations) {
-    return ImmutableSetMultimap.copyOf(Multimaps.index(declarations, BindingDeclaration::key));
-  }
-
-  @Override
-  public void clearCache() {
-    keysMatchingRequestCache.clear();
-  }
-
-  private final class Resolver {
-    final Optional<Resolver> parentResolver;
-    final ComponentDescriptor componentDescriptor;
-    final ImmutableSetMultimap<Key, ContributionBinding> explicitBindings;
-    final ImmutableSet<ContributionBinding> explicitBindingsSet;
-    final ImmutableSetMultimap<Key, ContributionBinding> explicitMultibindings;
-    final ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations;
-    final ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations;
-    final ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations;
-    final ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations;
-    final ImmutableSetMultimap<Key, DelegateDeclaration> delegateMultibindingDeclarations;
-    final Map<Key, ResolvedBindings> resolvedContributionBindings = new LinkedHashMap<>();
-    final Map<Key, ResolvedBindings> resolvedMembersInjectionBindings = new LinkedHashMap<>();
-    final Deque<Key> cycleStack = new ArrayDeque<>();
-    final Map<Key, Boolean> keyDependsOnLocalBindingsCache = new HashMap<>();
-    final Map<Binding, Boolean> bindingDependsOnLocalBindingsCache = new HashMap<>();
-    final Queue<ComponentDescriptor> subcomponentsToResolve = new ArrayDeque<>();
-
-    Resolver(
-        Optional<Resolver> parentResolver,
-        ComponentDescriptor componentDescriptor,
-        ImmutableSetMultimap<Key, ContributionBinding> explicitBindings,
-        ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations,
-        ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations,
-        ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations,
-        ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations) {
-      this.parentResolver = parentResolver;
-      this.componentDescriptor = checkNotNull(componentDescriptor);
-      this.explicitBindings = checkNotNull(explicitBindings);
-      this.explicitBindingsSet = ImmutableSet.copyOf(explicitBindings.values());
-      this.multibindingDeclarations = checkNotNull(multibindingDeclarations);
-      this.subcomponentDeclarations = checkNotNull(subcomponentDeclarations);
-      this.delegateDeclarations = checkNotNull(delegateDeclarations);
-      this.optionalBindingDeclarations = checkNotNull(optionalBindingDeclarations);
-      this.explicitMultibindings = multibindingContributionsByMultibindingKey(explicitBindingsSet);
-      this.delegateMultibindingDeclarations =
-          multibindingContributionsByMultibindingKey(delegateDeclarations.values());
-      subcomponentsToResolve.addAll(
-          componentDescriptor.childComponentsDeclaredByFactoryMethods().values());
-      subcomponentsToResolve.addAll(
-          componentDescriptor.childComponentsDeclaredByBuilderEntryPoints().values());
-    }
-
-    /**
-     * Returns the resolved contribution bindings for the given {@link Key}:
-     *
-     * <ul>
-     *   <li>All explicit bindings for:
-     *       <ul>
-     *         <li>the requested key
-     *         <li>{@code Set<T>} if the requested key's type is {@code Set<Produced<T>>}
-     *         <li>{@code Map<K, Provider<V>>} if the requested key's type is {@code Map<K,
-     *             Producer<V>>}.
-     *       </ul>
-     *   <li>An implicit {@link Inject @Inject}-annotated constructor binding if there is one and
-     *       there are no explicit bindings or synthetic bindings.
-     * </ul>
-     */
-    ResolvedBindings lookUpBindings(Key requestKey) {
-      Set<ContributionBinding> bindings = new LinkedHashSet<>();
-      Set<ContributionBinding> multibindingContributions = new LinkedHashSet<>();
-      Set<MultibindingDeclaration> multibindingDeclarations = new LinkedHashSet<>();
-      Set<OptionalBindingDeclaration> optionalBindingDeclarations = new LinkedHashSet<>();
-      Set<SubcomponentDeclaration> subcomponentDeclarations = new LinkedHashSet<>();
-
-      // Gather all bindings, multibindings, optional, and subcomponent declarations/contributions.
-      ImmutableSet<Key> keysMatchingRequest = keysMatchingRequest(requestKey);
-      for (Resolver resolver : getResolverLineage()) {
-        bindings.addAll(resolver.getLocalExplicitBindings(requestKey));
-
-        for (Key key : keysMatchingRequest) {
-          multibindingContributions.addAll(resolver.getLocalExplicitMultibindings(key));
-          multibindingDeclarations.addAll(resolver.multibindingDeclarations.get(key));
-          subcomponentDeclarations.addAll(resolver.subcomponentDeclarations.get(key));
-          // The optional binding declarations are keyed by the unwrapped type.
-          keyFactory.unwrapOptional(key)
-              .map(resolver.optionalBindingDeclarations::get)
-              .ifPresent(optionalBindingDeclarations::addAll);
-        }
-      }
-
-      // Add synthetic multibinding
-      if (!multibindingContributions.isEmpty() || !multibindingDeclarations.isEmpty()) {
-        bindings.add(bindingFactory.syntheticMultibinding(requestKey, multibindingContributions));
-      }
-
-      // Add synthetic optional binding
-      if (!optionalBindingDeclarations.isEmpty()) {
-        bindings.add(
-            bindingFactory.syntheticOptionalBinding(
-                requestKey,
-                getRequestKind(OptionalType.from(requestKey).valueType()),
-                lookUpBindings(keyFactory.unwrapOptional(requestKey).get()).bindings()));
-      }
-
-      // Add subcomponent creator binding
-      if (!subcomponentDeclarations.isEmpty()) {
-        ProvisionBinding binding =
-            bindingFactory.subcomponentCreatorBinding(
-                ImmutableSet.copyOf(subcomponentDeclarations));
-        bindings.add(binding);
-        addSubcomponentToOwningResolver(binding);
-      }
-
-      // Add members injector binding
-      if (isType(requestKey.type()) && isTypeOf(MembersInjector.class, requestKey.type())) {
-        injectBindingRegistry
-            .getOrFindMembersInjectorProvisionBinding(requestKey)
-            .ifPresent(bindings::add);
-      }
-
-      // Add Assisted Factory binding
-      if (isType(requestKey.type())
-          && requestKey.type().getKind() == TypeKind.DECLARED
-          && isAssistedFactoryType(asTypeElement(requestKey.type()))) {
-        bindings.add(
-            bindingFactory.assistedFactoryBinding(
-                asTypeElement(requestKey.type()), Optional.of(requestKey.type())));
-      }
-
-      // If there are no bindings, add the implicit @Inject-constructed binding if there is one.
-      if (bindings.isEmpty()) {
-        injectBindingRegistry
-            .getOrFindProvisionBinding(requestKey)
-            .filter(this::isCorrectlyScopedInSubcomponent)
-            .ifPresent(bindings::add);
-      }
-
-      return ResolvedBindings.forContributionBindings(
-          requestKey,
-          Multimaps.index(bindings, binding -> getOwningComponent(requestKey, binding)),
-          multibindingDeclarations,
-          subcomponentDeclarations,
-          optionalBindingDeclarations);
-    }
-
-    /**
-     * Returns true if this binding graph resolution is for a subcomponent and the {@code @Inject}
-     * binding's scope correctly matches one of the components in the current component ancestry.
-     * If not, it means the binding is not owned by any of the currently known components, and will
-     * be owned by a future ancestor (or, if never owned, will result in an incompatibly scoped
-     * binding error at the root component).
-     */
-    private boolean isCorrectlyScopedInSubcomponent(ProvisionBinding binding) {
-      checkArgument(binding.kind() == INJECTION || binding.kind() == ASSISTED_INJECTION);
-      if (!rootComponent().isSubcomponent()
-          || !binding.scope().isPresent()
-          || binding.scope().get().isReusable()) {
-        return true;
-      }
-
-      Resolver owningResolver = getOwningResolver(binding).orElse(this);
-      ComponentDescriptor owningComponent = owningResolver.componentDescriptor;
-      return owningComponent.scopes().contains(binding.scope().get());
-    }
-
-    private ComponentDescriptor rootComponent() {
-      return parentResolver.map(Resolver::rootComponent).orElse(componentDescriptor);
-    }
-
-    /** Returns the resolved members injection bindings for the given {@link Key}. */
-    ResolvedBindings lookUpMembersInjectionBinding(Key requestKey) {
-      // no explicit deps for members injection, so just look it up
-      Optional<MembersInjectionBinding> binding =
-          injectBindingRegistry.getOrFindMembersInjectionBinding(requestKey);
-      return binding.isPresent()
-          ? ResolvedBindings.forMembersInjectionBinding(
-              requestKey, componentDescriptor, binding.get())
-          : ResolvedBindings.noBindings(requestKey);
-    }
-
-    /**
-     * When a binding is resolved for a {@link SubcomponentDeclaration}, adds corresponding {@link
-     * ComponentDescriptor subcomponent} to a queue in the owning component's resolver. The queue
-     * will be used to detect which subcomponents need to be resolved.
-     */
-    private void addSubcomponentToOwningResolver(ProvisionBinding subcomponentCreatorBinding) {
-      checkArgument(subcomponentCreatorBinding.kind().equals(SUBCOMPONENT_CREATOR));
-      Resolver owningResolver = getOwningResolver(subcomponentCreatorBinding).get();
-
-      TypeElement builderType = MoreTypes.asTypeElement(subcomponentCreatorBinding.key().type());
-      owningResolver.subcomponentsToResolve.add(
-          owningResolver.componentDescriptor.getChildComponentWithBuilderType(builderType));
-    }
-
-    /**
-     * Profiling has determined that computing the keys matching {@code requestKey} has measurable
-     * performance impact. It is called repeatedly (at least 3 times per key resolved per {@link
-     * BindingGraph}. {@code javac}'s name-checking performance seems suboptimal (converting byte
-     * strings to Strings repeatedly), and the matching keys creations relies on that. This also
-     * ensures that the resulting keys have their hash codes cached on successive calls to this
-     * method.
-     *
-     * <p>This caching may become obsolete if:
-     *
-     * <ul>
-     *   <li>We decide to intern all {@link Key} instances
-     *   <li>We fix javac's name-checking peformance (though we may want to keep this for older
-     *       javac users)
-     * </ul>
-     */
-    private ImmutableSet<Key> keysMatchingRequest(Key requestKey) {
-      return keysMatchingRequestCache.computeIfAbsent(
-          requestKey, this::keysMatchingRequestUncached);
-    }
-
-    private ImmutableSet<Key> keysMatchingRequestUncached(Key requestKey) {
-      ImmutableSet.Builder<Key> keys = ImmutableSet.builder();
-      keys.add(requestKey);
-      keyFactory.unwrapSetKey(requestKey, Produced.class).ifPresent(keys::add);
-      keyFactory.rewrapMapKey(requestKey, Producer.class, Provider.class).ifPresent(keys::add);
-      keyFactory.rewrapMapKey(requestKey, Provider.class, Producer.class).ifPresent(keys::add);
-      keys.addAll(keyFactory.implicitFrameworkMapKeys(requestKey));
-      return keys.build();
-    }
-
-    private ImmutableSet<ContributionBinding> createDelegateBindings(
-        ImmutableSet<DelegateDeclaration> delegateDeclarations) {
-      ImmutableSet.Builder<ContributionBinding> builder = ImmutableSet.builder();
-      for (DelegateDeclaration delegateDeclaration : delegateDeclarations) {
-        builder.add(createDelegateBinding(delegateDeclaration));
-      }
-      return builder.build();
-    }
-
-    /**
-     * Creates one (and only one) delegate binding for a delegate declaration, based on the resolved
-     * bindings of the right-hand-side of a {@link dagger.Binds} method. If there are duplicate
-     * bindings for the dependency key, there should still be only one binding for the delegate key.
-     */
-    private ContributionBinding createDelegateBinding(DelegateDeclaration delegateDeclaration) {
-      Key delegateKey = delegateDeclaration.delegateRequest().key();
-      if (cycleStack.contains(delegateKey)) {
-        return bindingFactory.unresolvedDelegateBinding(delegateDeclaration);
-      }
-
-      ResolvedBindings resolvedDelegate;
-      try {
-        cycleStack.push(delegateKey);
-        resolvedDelegate = lookUpBindings(delegateKey);
-      } finally {
-        cycleStack.pop();
-      }
-      if (resolvedDelegate.contributionBindings().isEmpty()) {
-        // This is guaranteed to result in a missing binding error, so it doesn't matter if the
-        // binding is a Provision or Production, except if it is a @IntoMap method, in which
-        // case the key will be of type Map<K, Provider<V>>, which will be "upgraded" into a
-        // Map<K, Producer<V>> if it's requested in a ProductionComponent. This may result in a
-        // strange error, that the RHS needs to be provided with an @Inject or @Provides
-        // annotated method, but a user should be able to figure out if a @Produces annotation
-        // is needed.
-        // TODO(gak): revisit how we model missing delegates if/when we clean up how we model
-        // binding declarations
-        return bindingFactory.unresolvedDelegateBinding(delegateDeclaration);
-      }
-      // It doesn't matter which of these is selected, since they will later on produce a
-      // duplicate binding error.
-      ContributionBinding explicitDelegate =
-          resolvedDelegate.contributionBindings().iterator().next();
-      return bindingFactory.delegateBinding(delegateDeclaration, explicitDelegate);
-    }
-
-    /**
-     * Returns the component that should contain the framework field for {@code binding}.
-     *
-     * <p>If {@code binding} is either not bound in an ancestor component or depends transitively on
-     * bindings in this component, returns this component.
-     *
-     * <p>Otherwise, resolves {@code request} in this component's parent in order to resolve any
-     * multibinding contributions in the parent, and returns the parent-resolved {@link
-     * ResolvedBindings#owningComponent(ContributionBinding)}.
-     */
-    private TypeElement getOwningComponent(Key requestKey, ContributionBinding binding) {
-      if (isResolvedInParent(requestKey, binding)
-          && !new LocalDependencyChecker().dependsOnLocalBindings(binding)) {
-        ResolvedBindings parentResolvedBindings =
-            parentResolver.get().resolvedContributionBindings.get(requestKey);
-        return parentResolvedBindings.owningComponent(binding);
-      } else {
-        return componentDescriptor.typeElement();
-      }
-    }
-
-    /**
-     * Returns {@code true} if {@code binding} is owned by an ancestor. If so, {@linkplain #resolve
-     * resolves} the {@link Key} in this component's parent. Don't resolve directly in the owning
-     * component in case it depends on multibindings in any of its descendants.
-     */
-    private boolean isResolvedInParent(Key requestKey, ContributionBinding binding) {
-      Optional<Resolver> owningResolver = getOwningResolver(binding);
-      if (owningResolver.isPresent() && !owningResolver.get().equals(this)) {
-        parentResolver.get().resolve(requestKey);
-        return true;
-      } else {
-        return false;
-      }
-    }
-
-    private Optional<Resolver> getOwningResolver(ContributionBinding binding) {
-      // TODO(ronshapiro): extract the different pieces of this method into their own methods
-      if ((binding.scope().isPresent() && binding.scope().get().isProductionScope())
-          || binding.bindingType().equals(BindingType.PRODUCTION)) {
-        for (Resolver requestResolver : getResolverLineage()) {
-          // Resolve @Inject @ProductionScope bindings at the highest production component.
-          if (binding.kind().equals(INJECTION)
-              && requestResolver.componentDescriptor.isProduction()) {
-            return Optional.of(requestResolver);
-          }
-
-          // Resolve explicit @Produces and @ProductionScope bindings at the highest component that
-          // installs the binding.
-          if (requestResolver.containsExplicitBinding(binding)) {
-            return Optional.of(requestResolver);
-          }
-        }
-      }
-
-      if (binding.scope().isPresent() && binding.scope().get().isReusable()) {
-        for (Resolver requestResolver : getResolverLineage().reverse()) {
-          // If a @Reusable binding was resolved in an ancestor, use that component.
-          ResolvedBindings resolvedBindings =
-              requestResolver.resolvedContributionBindings.get(binding.key());
-          if (resolvedBindings != null
-              && resolvedBindings.contributionBindings().contains(binding)) {
-            return Optional.of(requestResolver);
-          }
-        }
-        // If a @Reusable binding was not resolved in any ancestor, resolve it here.
-        return Optional.empty();
-      }
-
-      for (Resolver requestResolver : getResolverLineage().reverse()) {
-        if (requestResolver.containsExplicitBinding(binding)) {
-          return Optional.of(requestResolver);
-        }
-      }
-
-      // look for scope separately.  we do this for the case where @Singleton can appear twice
-      // in the † compatibility mode
-      Optional<Scope> bindingScope = binding.scope();
-      if (bindingScope.isPresent()) {
-        for (Resolver requestResolver : getResolverLineage().reverse()) {
-          if (requestResolver.componentDescriptor.scopes().contains(bindingScope.get())) {
-            return Optional.of(requestResolver);
-          }
-        }
-      }
-      return Optional.empty();
-    }
-
-    private boolean containsExplicitBinding(ContributionBinding binding) {
-      return explicitBindingsSet.contains(binding)
-          || resolverContainsDelegateDeclarationForBinding(binding)
-          || subcomponentDeclarations.containsKey(binding.key());
-    }
-
-    /** Returns true if {@code binding} was installed in a module in this resolver's component. */
-    private boolean resolverContainsDelegateDeclarationForBinding(ContributionBinding binding) {
-      if (!binding.kind().equals(DELEGATE)) {
-        return false;
-      }
-
-      // Map multibinding key values are wrapped with a framework type. This needs to be undone
-      // to look it up in the delegate declarations map.
-      // TODO(erichang): See if we can standardize the way map keys are used in these data
-      // structures, either always wrapped or unwrapped to be consistent and less errorprone.
-      Key bindingKey = binding.key();
-      if (compilerOptions.strictMultibindingValidation()
-          && binding.contributionType().equals(ContributionType.MAP)) {
-        bindingKey = keyFactory.unwrapMapValueType(bindingKey);
-      }
-
-      return delegateDeclarations.get(bindingKey).stream()
-          .anyMatch(
-              declaration ->
-                  declaration.contributingModule().equals(binding.contributingModule())
-                  && declaration.bindingElement().equals(binding.bindingElement()));
-    }
-
-    /** Returns the resolver lineage from parent to child. */
-    private ImmutableList<Resolver> getResolverLineage() {
-      ImmutableList.Builder<Resolver> resolverList = ImmutableList.builder();
-      for (Optional<Resolver> currentResolver = Optional.of(this);
-          currentResolver.isPresent();
-          currentResolver = currentResolver.get().parentResolver) {
-        resolverList.add(currentResolver.get());
-      }
-      return resolverList.build().reverse();
-    }
-
-    /**
-     * Returns the explicit {@link ContributionBinding}s that match the {@code key} from this
-     * resolver.
-     */
-    private ImmutableSet<ContributionBinding> getLocalExplicitBindings(Key key) {
-      return new ImmutableSet.Builder<ContributionBinding>()
-          .addAll(explicitBindings.get(key))
-          // @Binds @IntoMap declarations have key Map<K, V>, unlike @Provides @IntoMap or @Produces
-          // @IntoMap, which have Map<K, Provider/Producer<V>> keys. So unwrap the key's type's
-          // value type if it's a Map<K, Provider/Producer<V>> before looking in
-          // delegateDeclarations. createDelegateBindings() will create bindings with the properly
-          // wrapped key type.
-          .addAll(
-              createDelegateBindings(delegateDeclarations.get(keyFactory.unwrapMapValueType(key))))
-          .build();
-    }
-
-    /**
-     * Returns the explicit multibinding contributions that contribute to the map or set requested
-     * by {@code key} from this resolver.
-     */
-    private ImmutableSet<ContributionBinding> getLocalExplicitMultibindings(Key key) {
-      ImmutableSet.Builder<ContributionBinding> multibindings = ImmutableSet.builder();
-      multibindings.addAll(explicitMultibindings.get(key));
-      if (!MapType.isMap(key)
-          || MapType.from(key).isRawType()
-          || MapType.from(key).valuesAreFrameworkType()) {
-        // @Binds @IntoMap declarations have key Map<K, V>, unlike @Provides @IntoMap or @Produces
-        // @IntoMap, which have Map<K, Provider/Producer<V>> keys. So unwrap the key's type's
-        // value type if it's a Map<K, Provider/Producer<V>> before looking in
-        // delegateMultibindingDeclarations. createDelegateBindings() will create bindings with the
-        // properly wrapped key type.
-        multibindings.addAll(
-            createDelegateBindings(
-                delegateMultibindingDeclarations.get(keyFactory.unwrapMapValueType(key))));
-      }
-      return multibindings.build();
-    }
-
-    /**
-     * Returns the {@link OptionalBindingDeclaration}s that match the {@code key} from this and all
-     * ancestor resolvers.
-     */
-    private ImmutableSet<OptionalBindingDeclaration> getOptionalBindingDeclarations(Key key) {
-      Optional<Key> unwrapped = keyFactory.unwrapOptional(key);
-      if (!unwrapped.isPresent()) {
-        return ImmutableSet.of();
-      }
-      ImmutableSet.Builder<OptionalBindingDeclaration> declarations = ImmutableSet.builder();
-      for (Resolver resolver : getResolverLineage()) {
-        declarations.addAll(resolver.optionalBindingDeclarations.get(unwrapped.get()));
-      }
-      return declarations.build();
-    }
-
-    /**
-     * Returns the {@link ResolvedBindings} for {@code key} that was resolved in this resolver or an
-     * ancestor resolver. Only checks for {@link ContributionBinding}s as {@link
-     * MembersInjectionBinding}s are not inherited.
-     */
-    private Optional<ResolvedBindings> getPreviouslyResolvedBindings(Key key) {
-      Optional<ResolvedBindings> result =
-          Optional.ofNullable(resolvedContributionBindings.get(key));
-      if (result.isPresent()) {
-        return result;
-      } else if (parentResolver.isPresent()) {
-        return parentResolver.get().getPreviouslyResolvedBindings(key);
-      } else {
-        return Optional.empty();
-      }
-    }
-
-    private void resolveMembersInjection(Key key) {
-      ResolvedBindings bindings = lookUpMembersInjectionBinding(key);
-      resolveDependencies(bindings);
-      resolvedMembersInjectionBindings.put(key, bindings);
-    }
-
-    void resolve(Key key) {
-      // If we find a cycle, stop resolving. The original request will add it with all of the
-      // other resolved deps.
-      if (cycleStack.contains(key)) {
-        return;
-      }
-
-      // If the binding was previously resolved in this (sub)component, don't resolve it again.
-      if (resolvedContributionBindings.containsKey(key)) {
-        return;
-      }
-
-      /*
-       * If the binding was previously resolved in an ancestor component, then we may be able to
-       * avoid resolving it here and just depend on the ancestor component resolution.
-       *
-       * 1. If it depends transitively on multibinding contributions or optional bindings with
-       *    bindings from this subcomponent, then we have to resolve it in this subcomponent so
-       *    that it sees the local bindings.
-       *
-       * 2. If there are any explicit bindings in this component, they may conflict with those in
-       *    the ancestor component, so resolve them here so that conflicts can be caught.
-       */
-      if (getPreviouslyResolvedBindings(key).isPresent()) {
-        /* Resolve in the parent in case there are multibinding contributions or conflicts in some
-         * component between this one and the previously-resolved one. */
-        parentResolver.get().resolve(key);
-        if (!new LocalDependencyChecker().dependsOnLocalBindings(key)
-            && getLocalExplicitBindings(key).isEmpty()) {
-          /* Cache the inherited parent component's bindings in case resolving at the parent found
-           * bindings in some component between this one and the previously-resolved one. */
-          resolvedContributionBindings.put(key, getPreviouslyResolvedBindings(key).get());
-          return;
-        }
-      }
-
-      cycleStack.push(key);
-      try {
-        ResolvedBindings bindings = lookUpBindings(key);
-        resolvedContributionBindings.put(key, bindings);
-        resolveDependencies(bindings);
-      } finally {
-        cycleStack.pop();
-      }
-    }
-
-    /**
-     * {@link #resolve(Key) Resolves} each of the dependencies of the bindings owned by this
-     * component.
-     */
-    private void resolveDependencies(ResolvedBindings resolvedBindings) {
-      for (Binding binding : resolvedBindings.bindingsOwnedBy(componentDescriptor)) {
-        for (DependencyRequest dependency : binding.dependencies()) {
-          resolve(dependency.key());
-        }
-      }
-    }
-
-    /**
-     * Returns all of the {@link ResolvedBindings} for {@link ContributionBinding}s from this and
-     * all ancestor resolvers, indexed by {@link ResolvedBindings#key()}.
-     */
-    Map<Key, ResolvedBindings> getResolvedContributionBindings() {
-      Map<Key, ResolvedBindings> bindings = new LinkedHashMap<>();
-      parentResolver.ifPresent(parent -> bindings.putAll(parent.getResolvedContributionBindings()));
-      bindings.putAll(resolvedContributionBindings);
-      return bindings;
-    }
-
-    /**
-     * Returns all of the {@link ResolvedBindings} for {@link MembersInjectionBinding} from this
-     * resolvers, indexed by {@link ResolvedBindings#key()}.
-     */
-    ImmutableMap<Key, ResolvedBindings> getResolvedMembersInjectionBindings() {
-      return ImmutableMap.copyOf(resolvedMembersInjectionBindings);
-    }
-
-    private final class LocalDependencyChecker {
-      private final Set<Object> cycleChecker = new HashSet<>();
-
-      /**
-       * Returns {@code true} if any of the bindings resolved for {@code key} are multibindings with
-       * contributions declared within this component's modules or optional bindings with present
-       * values declared within this component's modules, or if any of its unscoped dependencies
-       * depend on such bindings.
-       *
-       * <p>We don't care about scoped dependencies because they will never depend on bindings from
-       * subcomponents.
-       *
-       * @throws IllegalArgumentException if {@link #getPreviouslyResolvedBindings(Key)} is empty
-       */
-      private boolean dependsOnLocalBindings(Key key) {
-        // Don't recur infinitely if there are valid cycles in the dependency graph.
-        // http://b/23032377
-        if (!cycleChecker.add(key)) {
-          return false;
-        }
-        return reentrantComputeIfAbsent(
-            keyDependsOnLocalBindingsCache, key, this::dependsOnLocalBindingsUncached);
-      }
-
-      /**
-       * Returns {@code true} if {@code binding} is unscoped (or has {@link Reusable @Reusable}
-       * scope) and depends on multibindings with contributions declared within this component's
-       * modules, or if any of its unscoped or {@link Reusable @Reusable} scoped dependencies depend
-       * on such local multibindings.
-       *
-       * <p>We don't care about non-reusable scoped dependencies because they will never depend on
-       * multibindings with contributions from subcomponents.
-       */
-      private boolean dependsOnLocalBindings(Binding binding) {
-        if (!cycleChecker.add(binding)) {
-          return false;
-        }
-        return reentrantComputeIfAbsent(
-            bindingDependsOnLocalBindingsCache, binding, this::dependsOnLocalBindingsUncached);
-      }
-
-      private boolean dependsOnLocalBindingsUncached(Key key) {
-        checkArgument(
-            getPreviouslyResolvedBindings(key).isPresent(),
-            "no previously resolved bindings in %s for %s",
-            Resolver.this,
-            key);
-        ResolvedBindings previouslyResolvedBindings = getPreviouslyResolvedBindings(key).get();
-        if (hasLocalMultibindingContributions(key)
-            || hasLocalOptionalBindingContribution(previouslyResolvedBindings)) {
-          return true;
-        }
-
-        for (Binding binding : previouslyResolvedBindings.bindings()) {
-          if (dependsOnLocalBindings(binding)) {
-            return true;
-          }
-        }
-        return false;
-      }
-
-      private boolean dependsOnLocalBindingsUncached(Binding binding) {
-        if ((!binding.scope().isPresent() || binding.scope().get().isReusable())
-            // TODO(beder): Figure out what happens with production subcomponents.
-            && !binding.bindingType().equals(BindingType.PRODUCTION)) {
-          for (DependencyRequest dependency : binding.dependencies()) {
-            if (dependsOnLocalBindings(dependency.key())) {
-              return true;
-            }
-          }
-        }
-        return false;
-      }
-
-      /**
-       * Returns {@code true} if there is at least one multibinding contribution declared within
-       * this component's modules that matches the key.
-       */
-      private boolean hasLocalMultibindingContributions(Key requestKey) {
-        return keysMatchingRequest(requestKey)
-            .stream()
-            .anyMatch(key -> !getLocalExplicitMultibindings(key).isEmpty());
-      }
-
-      /**
-       * Returns {@code true} if there is a contribution in this component for an {@code
-       * Optional<Foo>} key that has not been contributed in a parent.
-       */
-      private boolean hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings) {
-        if (resolvedBindings
-            .contributionBindings()
-            .stream()
-            .map(ContributionBinding::kind)
-            .anyMatch(isEqual(OPTIONAL))) {
-          return !getLocalExplicitBindings(keyFactory.unwrapOptional(resolvedBindings.key()).get())
-              .isEmpty();
-        } else {
-          // If a parent contributes a @Provides Optional<Foo> binding and a child has a
-          // @BindsOptionalOf Foo method, the two should conflict, even if there is no binding for
-          // Foo on its own
-          return !getOptionalBindingDeclarations(resolvedBindings.key()).isEmpty();
-        }
-      }
-    }
-  }
-
-  /**
-   * A multimap of those {@code declarations} that are multibinding contribution declarations,
-   * indexed by the key of the set or map to which they contribute.
-   */
-  static <T extends BindingDeclaration>
-      ImmutableSetMultimap<Key, T> multibindingContributionsByMultibindingKey(
-          Iterable<T> declarations) {
-    ImmutableSetMultimap.Builder<Key, T> builder = ImmutableSetMultimap.builder();
-    for (T declaration : declarations) {
-      if (declaration.key().multibindingContributionIdentifier().isPresent()) {
-        builder.put(
-            declaration
-                .key()
-                .toBuilder()
-                .multibindingContributionIdentifier(Optional.empty())
-                .build(),
-            declaration);
-      }
-    }
-    return builder.build();
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/BindingNode.java b/java/dagger/internal/codegen/binding/BindingNode.java
deleted file mode 100644
index 78d440d..0000000
--- a/java/dagger/internal/codegen/binding/BindingNode.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.binding;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.BindingType.PRODUCTION;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import dagger.BindsOptionalOf;
-import dagger.Module;
-import dagger.model.BindingKind;
-import dagger.model.ComponentPath;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.model.Scope;
-import dagger.multibindings.Multibinds;
-import java.util.Optional;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-/**
- * An implementation of {@link dagger.model.Binding} that also exposes {@link BindingDeclaration}s
- * associated with the binding.
- */
-// TODO(dpb): Consider a supertype of dagger.model.Binding that
-// dagger.internal.codegen.binding.Binding
-// could also implement.
-@AutoValue
-public abstract class BindingNode implements dagger.model.Binding {
-  public static BindingNode create(
-      ComponentPath component,
-      Binding delegate,
-      ImmutableSet<MultibindingDeclaration> multibindingDeclarations,
-      ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations,
-      ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations,
-      BindingDeclarationFormatter bindingDeclarationFormatter) {
-    BindingNode node =
-        new AutoValue_BindingNode(
-            component,
-            delegate,
-            multibindingDeclarations,
-            optionalBindingDeclarations,
-            subcomponentDeclarations);
-    node.bindingDeclarationFormatter = checkNotNull(bindingDeclarationFormatter);
-    return node;
-  }
-
-  private BindingDeclarationFormatter bindingDeclarationFormatter;
-
-  public abstract Binding delegate();
-
-  public abstract ImmutableSet<MultibindingDeclaration> multibindingDeclarations();
-
-  public abstract ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations();
-
-  public abstract ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations();
-
-  /**
-   * The {@link Element}s (other than the binding's {@link #bindingElement()}) that are associated
-   * with the binding.
-   *
-   * <ul>
-   *   <li>{@linkplain BindsOptionalOf optional binding} declarations
-   *   <li>{@linkplain Module#subcomponents() module subcomponent} declarations
-   *   <li>{@linkplain Multibinds multibinding} declarations
-   * </ul>
-   */
-  public final Iterable<BindingDeclaration> associatedDeclarations() {
-    return Iterables.concat(
-        multibindingDeclarations(), optionalBindingDeclarations(), subcomponentDeclarations());
-  }
-
-  @Override
-  public Key key() {
-    return delegate().key();
-  }
-
-  @Override
-  public ImmutableSet<DependencyRequest> dependencies() {
-    return delegate().dependencies();
-  }
-
-  @Override
-  public Optional<Element> bindingElement() {
-    return delegate().bindingElement();
-  }
-
-  @Override
-  public Optional<TypeElement> contributingModule() {
-    return delegate().contributingModule();
-  }
-
-  @Override
-  public boolean requiresModuleInstance() {
-    return delegate().requiresModuleInstance();
-  }
-
-  @Override
-  public Optional<Scope> scope() {
-    return delegate().scope();
-  }
-
-  @Override
-  public boolean isNullable() {
-    return delegate().isNullable();
-  }
-
-  @Override
-  public boolean isProduction() {
-    return delegate().bindingType().equals(PRODUCTION);
-  }
-
-  @Override
-  public BindingKind kind() {
-    return delegate().kind();
-  }
-
-  @Override
-  public final String toString() {
-    return bindingDeclarationFormatter.format(delegate());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/BindingRequest.java b/java/dagger/internal/codegen/binding/BindingRequest.java
deleted file mode 100644
index d61d9cf..0000000
--- a/java/dagger/internal/codegen/binding/BindingRequest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.binding;
-
-import static dagger.internal.codegen.base.RequestKinds.requestType;
-
-import com.google.auto.value.AutoValue;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-import java.util.Optional;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A request for a binding, which may be in the form of a request for a dependency to pass to a
- * constructor or module method ({@link RequestKind}) or an internal request for a framework
- * instance ({@link FrameworkType}).
- */
-@AutoValue
-public abstract class BindingRequest {
-  /** Creates a {@link BindingRequest} for the given {@link DependencyRequest}. */
-  public static BindingRequest bindingRequest(DependencyRequest dependencyRequest) {
-    return bindingRequest(dependencyRequest.key(), dependencyRequest.kind());
-  }
-
-  /**
-   * Creates a {@link BindingRequest} for a normal dependency request for the given {@link Key} and
-   * {@link RequestKind}.
-   */
-  public static BindingRequest bindingRequest(Key key, RequestKind requestKind) {
-    // When there's a request that has a 1:1 mapping to a FrameworkType, the request should be
-    // associated with that FrameworkType as well, because we want to ensure that if a request
-    // comes in for that as a dependency first and as a framework instance later, they resolve to
-    // the same binding expression.
-    // TODO(cgdecker): Instead of doing this, make ComponentBindingExpressions create a
-    // BindingExpression for the RequestKind that simply delegates to the BindingExpression for the
-    // FrameworkType. Then there are separate BindingExpressions, but we don't end up doing weird
-    // things like creating two fields when there should only be one.
-    return new AutoValue_BindingRequest(
-        key, Optional.of(requestKind), FrameworkType.forRequestKind(requestKind));
-  }
-
-  /**
-   * Creates a {@link BindingRequest} for a request for a framework instance for the given {@link
-   * Key} with the given {@link FrameworkType}.
-   */
-  public static BindingRequest bindingRequest(Key key, FrameworkType frameworkType) {
-    return new AutoValue_BindingRequest(
-        key, frameworkType.requestKind(), Optional.of(frameworkType));
-  }
-
-  /** Returns the {@link Key} for the requested binding. */
-  public abstract Key key();
-
-  /** Returns the request kind associated with this request, if any. */
-  public abstract Optional<RequestKind> requestKind();
-
-  /** Returns the framework type associated with this request, if any. */
-  public abstract Optional<FrameworkType> frameworkType();
-
-  /** Returns whether this request is of the given kind. */
-  public final boolean isRequestKind(RequestKind requestKind) {
-    return requestKind.equals(requestKind().orElse(null));
-  }
-
-  public final TypeMirror requestedType(TypeMirror contributedType, DaggerTypes types) {
-    if (requestKind().isPresent()) {
-      return requestType(requestKind().get(), contributedType, types);
-    }
-    return types.wrapType(contributedType, frameworkType().get().frameworkClass());
-  }
-
-  /** Returns a name that can be used for the kind of request this is. */
-  public final String kindName() {
-    Object requestKindObject =
-        requestKind().isPresent()
-            ? requestKind().get()
-            : frameworkType().get().frameworkClass().getSimpleName();
-    return requestKindObject.toString();
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/BindingType.java b/java/dagger/internal/codegen/binding/BindingType.java
deleted file mode 100644
index 7f5ea54..0000000
--- a/java/dagger/internal/codegen/binding/BindingType.java
+++ /dev/null
@@ -1,31 +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.binding;
-
-import dagger.MembersInjector;
-
-/** Whether a binding or declaration is for provision, production, or a {@link MembersInjector}. */
-public enum BindingType {
-  /** A binding with this type is a {@link ProvisionBinding}. */
-  PROVISION,
-
-  /** A binding with this type is a {@link MembersInjectionBinding}. */
-  MEMBERS_INJECTION,
-
-  /** A binding with this type is a {@link ProductionBinding}. */
-  PRODUCTION,
-}
diff --git a/java/dagger/internal/codegen/binding/BindsTypeChecker.java b/java/dagger/internal/codegen/binding/BindsTypeChecker.java
deleted file mode 100644
index f3e0a1b..0000000
--- a/java/dagger/internal/codegen/binding/BindsTypeChecker.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2017 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.binding;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-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.TypeMirror;
-
-/**
- * Checks the assignability of one type to another, given a {@link ContributionType} context. This
- * is used by {@link dagger.internal.codegen.validation.BindsMethodValidator} to validate that the
- * right-hand- side of a {@link dagger.Binds} method is valid, as well as in {@link
- * dagger.internal.codegen.writing.DelegateBindingExpression} when the right-hand-side in generated
- * code might be an erased type due to accessibility.
- */
-public final class BindsTypeChecker {
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-
-  // TODO(bcorso): Make this pkg-private. Used by DelegateBindingExpression.
-  @Inject
-  public BindsTypeChecker(DaggerTypes types, DaggerElements elements) {
-    this.types = types;
-    this.elements = elements;
-  }
-
-  /**
-   * Checks the assignability of {@code rightHandSide} to {@code leftHandSide} given a {@link
-   * ContributionType} context.
-   */
-  public boolean isAssignable(
-      TypeMirror rightHandSide, TypeMirror leftHandSide, ContributionType contributionType) {
-    return types.isAssignable(rightHandSide, desiredAssignableType(leftHandSide, contributionType));
-  }
-
-  private TypeMirror desiredAssignableType(
-      TypeMirror leftHandSide, ContributionType contributionType) {
-    switch (contributionType) {
-      case UNIQUE:
-        return leftHandSide;
-      case SET:
-        DeclaredType parameterizedSetType = types.getDeclaredType(setElement(), leftHandSide);
-        return methodParameterType(parameterizedSetType, "add");
-      case SET_VALUES:
-        return methodParameterType(MoreTypes.asDeclared(leftHandSide), "addAll");
-      case MAP:
-        DeclaredType parameterizedMapType =
-            types.getDeclaredType(mapElement(), unboundedWildcard(), leftHandSide);
-        return methodParameterTypes(parameterizedMapType, "put").get(1);
-    }
-    throw new AssertionError("Unknown contribution type: " + contributionType);
-  }
-
-  private ImmutableList<TypeMirror> methodParameterTypes(DeclaredType type, String methodName) {
-    ImmutableList.Builder<ExecutableElement> methodsForName = ImmutableList.builder();
-    for (ExecutableElement method :
-        // type.asElement().getEnclosedElements() is not used because some non-standard JDKs (e.g.
-        // J2CL) don't redefine Set.add() (whose only purpose of being redefined in the standard JDK
-        // is documentation, and J2CL's implementation doesn't declare docs for JDK types).
-        // MoreElements.getLocalAndInheritedMethods ensures that the method will always be present.
-        MoreElements.getLocalAndInheritedMethods(MoreTypes.asTypeElement(type), types, elements)) {
-      if (method.getSimpleName().contentEquals(methodName)) {
-        methodsForName.add(method);
-      }
-    }
-    ExecutableElement method = getOnlyElement(methodsForName.build());
-    return ImmutableList.copyOf(
-        MoreTypes.asExecutable(types.asMemberOf(type, method)).getParameterTypes());
-  }
-
-  private TypeMirror methodParameterType(DeclaredType type, String methodName) {
-    return getOnlyElement(methodParameterTypes(type, methodName));
-  }
-
-  private TypeElement setElement() {
-    return elements.getTypeElement(Set.class);
-  }
-
-  private TypeElement mapElement() {
-    return elements.getTypeElement(Map.class);
-  }
-
-  private TypeMirror unboundedWildcard() {
-    return types.getWildcardType(null, null);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ChildFactoryMethodEdgeImpl.java b/java/dagger/internal/codegen/binding/ChildFactoryMethodEdgeImpl.java
deleted file mode 100644
index c056588..0000000
--- a/java/dagger/internal/codegen/binding/ChildFactoryMethodEdgeImpl.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.binding;
-
-import static dagger.internal.codegen.base.ElementFormatter.elementToString;
-
-import dagger.model.BindingGraph.ChildFactoryMethodEdge;
-import javax.lang.model.element.ExecutableElement;
-
-/** An implementation of {@link ChildFactoryMethodEdge}. */
-public final class ChildFactoryMethodEdgeImpl implements ChildFactoryMethodEdge {
-
-  private final ExecutableElement factoryMethod;
-
-  ChildFactoryMethodEdgeImpl(ExecutableElement factoryMethod) {
-    this.factoryMethod = factoryMethod;
-  }
-
-  @Override
-  public ExecutableElement factoryMethod() {
-    return factoryMethod;
-  }
-
-  @Override
-  public String toString() {
-    return elementToString(factoryMethod);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentCreatorAnnotation.java b/java/dagger/internal/codegen/binding/ComponentCreatorAnnotation.java
deleted file mode 100644
index 6297188..0000000
--- a/java/dagger/internal/codegen/binding/ComponentCreatorAnnotation.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2019 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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.base.Ascii.toUpperCase;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.extension.DaggerStreams.valuesOf;
-import static java.util.stream.Collectors.mapping;
-
-import com.google.common.collect.ImmutableSet;
-import dagger.Component;
-import dagger.Subcomponent;
-import dagger.internal.codegen.base.ComponentAnnotation;
-import dagger.producers.ProductionComponent;
-import dagger.producers.ProductionSubcomponent;
-import java.lang.annotation.Annotation;
-import java.util.stream.Collector;
-import java.util.stream.Stream;
-import javax.lang.model.element.TypeElement;
-
-/** Simple representation of a component creator annotation type. */
-public enum ComponentCreatorAnnotation {
-  COMPONENT_BUILDER(Component.Builder.class),
-  COMPONENT_FACTORY(Component.Factory.class),
-  SUBCOMPONENT_BUILDER(Subcomponent.Builder.class),
-  SUBCOMPONENT_FACTORY(Subcomponent.Factory.class),
-  PRODUCTION_COMPONENT_BUILDER(ProductionComponent.Builder.class),
-  PRODUCTION_COMPONENT_FACTORY(ProductionComponent.Factory.class),
-  PRODUCTION_SUBCOMPONENT_BUILDER(ProductionSubcomponent.Builder.class),
-  PRODUCTION_SUBCOMPONENT_FACTORY(ProductionSubcomponent.Factory.class),
-  ;
-
-  private final Class<? extends Annotation> annotation;
-  private final ComponentCreatorKind creatorKind;
-  private final Class<? extends Annotation> componentAnnotation;
-
-  @SuppressWarnings("unchecked") // Builder/factory annotations live within their parent annotation.
-  ComponentCreatorAnnotation(Class<? extends Annotation> annotation) {
-    this.annotation = annotation;
-    this.creatorKind = ComponentCreatorKind.valueOf(toUpperCase(annotation.getSimpleName()));
-    this.componentAnnotation = (Class<? extends Annotation>) annotation.getEnclosingClass();
-  }
-
-  /** The actual annotation type. */
-  public Class<? extends Annotation> annotation() {
-    return annotation;
-  }
-
-  /** The component annotation type that encloses this creator annotation type. */
-  public final Class<? extends Annotation> componentAnnotation() {
-    return componentAnnotation;
-  }
-
-  /** Returns {@code true} if the creator annotation is for a subcomponent. */
-  public final boolean isSubcomponentCreatorAnnotation() {
-    return componentAnnotation().getSimpleName().endsWith("Subcomponent");
-  }
-
-  /**
-   * Returns {@code true} if the creator annotation is for a production component or subcomponent.
-   */
-  public final boolean isProductionCreatorAnnotation() {
-    return componentAnnotation().getSimpleName().startsWith("Production");
-  }
-
-  /** The creator kind the annotation is associated with. */
-  // TODO(dpb): Remove ComponentCreatorKind.
-  public ComponentCreatorKind creatorKind() {
-    return creatorKind;
-  }
-
-  @Override
-  public final String toString() {
-    return annotation().getName();
-  }
-
-  /** Returns all component creator annotations. */
-  public static ImmutableSet<Class<? extends Annotation>> allCreatorAnnotations() {
-    return stream().collect(toAnnotationClasses());
-  }
-
-  /** Returns all root component creator annotations. */
-  public static ImmutableSet<Class<? extends Annotation>> rootComponentCreatorAnnotations() {
-    return stream()
-        .filter(
-            componentCreatorAnnotation ->
-                !componentCreatorAnnotation.isSubcomponentCreatorAnnotation())
-        .collect(toAnnotationClasses());
-  }
-
-  /** Returns all subcomponent creator annotations. */
-  public static ImmutableSet<Class<? extends Annotation>> subcomponentCreatorAnnotations() {
-    return stream()
-        .filter(
-            componentCreatorAnnotation ->
-                componentCreatorAnnotation.isSubcomponentCreatorAnnotation())
-        .collect(toAnnotationClasses());
-  }
-
-  /** Returns all production component creator annotations. */
-  public static ImmutableSet<Class<? extends Annotation>> productionCreatorAnnotations() {
-    return stream()
-        .filter(
-            componentCreatorAnnotation ->
-                componentCreatorAnnotation.isProductionCreatorAnnotation())
-        .collect(toAnnotationClasses());
-  }
-
-  /** Returns the legal creator annotations for the given {@code componentAnnotation}. */
-  public static ImmutableSet<Class<? extends Annotation>> creatorAnnotationsFor(
-      ComponentAnnotation componentAnnotation) {
-    return stream()
-        .filter(
-            creatorAnnotation ->
-                creatorAnnotation
-                    .componentAnnotation()
-                    .getSimpleName()
-                    .equals(componentAnnotation.simpleName()))
-        .collect(toAnnotationClasses());
-  }
-
-  /** Returns all creator annotations present on the given {@code type}. */
-  public static ImmutableSet<ComponentCreatorAnnotation> getCreatorAnnotations(TypeElement type) {
-    return stream()
-        .filter(cca -> isAnnotationPresent(type, cca.annotation()))
-        .collect(toImmutableSet());
-  }
-
-  private static Stream<ComponentCreatorAnnotation> stream() {
-    return valuesOf(ComponentCreatorAnnotation.class);
-  }
-
-  private static Collector<ComponentCreatorAnnotation, ?, ImmutableSet<Class<? extends Annotation>>>
-      toAnnotationClasses() {
-    return mapping(ComponentCreatorAnnotation::annotation, toImmutableSet());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java b/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java
deleted file mode 100644
index 5ea30ed..0000000
--- a/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.common.base.Verify.verify;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.getCreatorAnnotations;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import dagger.BindsInstance;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import java.util.List;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A descriptor for a component <i>creator</i> type: that is, a type annotated with
- * {@code @Component.Builder} (or one of the corresponding production or subcomponent versions).
- */
-@AutoValue
-public abstract class ComponentCreatorDescriptor {
-
-  /** Returns the annotation marking this creator. */
-  public abstract ComponentCreatorAnnotation annotation();
-
-  /** The kind of this creator. */
-  public final ComponentCreatorKind kind() {
-    return annotation().creatorKind();
-  }
-
-  /** The annotated creator type. */
-  public abstract TypeElement typeElement();
-
-  /** The method that creates and returns a component instance. */
-  public abstract ExecutableElement factoryMethod();
-
-  /**
-   * Multimap of component requirements to setter methods that set that requirement.
-   *
-   * <p>In a valid creator, there will be exactly one element per component requirement, so this
-   * method should only be called when validating the descriptor.
-   */
-  abstract ImmutableSetMultimap<ComponentRequirement, ExecutableElement> unvalidatedSetterMethods();
-
-  /**
-   * Multimap of component requirements to factory method parameters that set that requirement.
-   *
-   * <p>In a valid creator, there will be exactly one element per component requirement, so this
-   * method should only be called when validating the descriptor.
-   */
-  abstract ImmutableSetMultimap<ComponentRequirement, VariableElement>
-      unvalidatedFactoryParameters();
-
-  /**
-   * Multimap of component requirements to elements (methods or parameters) that set that
-   * requirement.
-   *
-   * <p>In a valid creator, there will be exactly one element per component requirement, so this
-   * method should only be called when validating the descriptor.
-   */
-  public final ImmutableSetMultimap<ComponentRequirement, Element>
-      unvalidatedRequirementElements() {
-    // ComponentCreatorValidator ensures that there are either setter methods or factory method
-    // parameters, but not both, so we can cheat a little here since we know that only one of
-    // the two multimaps will be non-empty.
-    return ImmutableSetMultimap.copyOf( // no actual copy
-        unvalidatedSetterMethods().isEmpty()
-            ? unvalidatedFactoryParameters()
-            : unvalidatedSetterMethods());
-  }
-
-  /**
-   * Map of component requirements to elements (setter methods or factory method parameters) that
-   * set them.
-   */
-  @Memoized
-  ImmutableMap<ComponentRequirement, Element> requirementElements() {
-    return flatten(unvalidatedRequirementElements());
-  }
-
-  /** Map of component requirements to setter methods for those requirements. */
-  @Memoized
-  public ImmutableMap<ComponentRequirement, ExecutableElement> setterMethods() {
-    return flatten(unvalidatedSetterMethods());
-  }
-
-  /** Map of component requirements to factory method parameters for those requirements. */
-  @Memoized
-  public ImmutableMap<ComponentRequirement, VariableElement> factoryParameters() {
-    return flatten(unvalidatedFactoryParameters());
-  }
-
-  private static <K, V> ImmutableMap<K, V> flatten(Multimap<K, V> multimap) {
-    return ImmutableMap.copyOf(
-        Maps.transformValues(multimap.asMap(), values -> getOnlyElement(values)));
-  }
-
-  /** Returns the set of component requirements this creator allows the user to set. */
-  public final ImmutableSet<ComponentRequirement> userSettableRequirements() {
-    // Note: they should have been validated at the point this is used, so this set is valid.
-    return unvalidatedRequirementElements().keySet();
-  }
-
-  /** Returns the set of requirements for modules and component dependencies for this creator. */
-  public final ImmutableSet<ComponentRequirement> moduleAndDependencyRequirements() {
-    return userSettableRequirements().stream()
-        .filter(requirement -> !requirement.isBoundInstance())
-        .collect(toImmutableSet());
-  }
-
-  /** Returns the set of bound instance requirements for this creator. */
-  final ImmutableSet<ComponentRequirement> boundInstanceRequirements() {
-    return userSettableRequirements().stream()
-        .filter(ComponentRequirement::isBoundInstance)
-        .collect(toImmutableSet());
-  }
-
-  /** Returns the element in this creator that sets the given {@code requirement}. */
-  final Element elementForRequirement(ComponentRequirement requirement) {
-    return requirementElements().get(requirement);
-  }
-
-  /** Creates a new {@link ComponentCreatorDescriptor} for the given creator {@code type}. */
-  public static ComponentCreatorDescriptor create(
-      DeclaredType type,
-      DaggerElements elements,
-      DaggerTypes types,
-      DependencyRequestFactory dependencyRequestFactory) {
-    TypeElement typeElement = asTypeElement(type);
-    TypeMirror componentType = typeElement.getEnclosingElement().asType();
-
-    ImmutableSetMultimap.Builder<ComponentRequirement, ExecutableElement> setterMethods =
-        ImmutableSetMultimap.builder();
-
-    ExecutableElement factoryMethod = null;
-    for (ExecutableElement method : elements.getUnimplementedMethods(typeElement)) {
-      ExecutableType resolvedMethodType = MoreTypes.asExecutable(types.asMemberOf(type, method));
-
-      if (types.isSubtype(componentType, resolvedMethodType.getReturnType())) {
-        factoryMethod = method;
-      } else {
-        VariableElement parameter = getOnlyElement(method.getParameters());
-        TypeMirror parameterType = getOnlyElement(resolvedMethodType.getParameterTypes());
-        setterMethods.put(
-            requirement(method, parameter, parameterType, dependencyRequestFactory, method),
-            method);
-      }
-    }
-    verify(factoryMethod != null); // validation should have ensured this.
-
-    ImmutableSetMultimap.Builder<ComponentRequirement, VariableElement> factoryParameters =
-        ImmutableSetMultimap.builder();
-
-    ExecutableType resolvedFactoryMethodType =
-        MoreTypes.asExecutable(types.asMemberOf(type, factoryMethod));
-    List<? extends VariableElement> parameters = factoryMethod.getParameters();
-    List<? extends TypeMirror> parameterTypes = resolvedFactoryMethodType.getParameterTypes();
-    for (int i = 0; i < parameters.size(); i++) {
-      VariableElement parameter = parameters.get(i);
-      TypeMirror parameterType = parameterTypes.get(i);
-      factoryParameters.put(
-          requirement(factoryMethod, parameter, parameterType, dependencyRequestFactory, parameter),
-          parameter);
-    }
-
-    // Validation should have ensured exactly one creator annotation is present on the type.
-    ComponentCreatorAnnotation annotation = getOnlyElement(getCreatorAnnotations(typeElement));
-    return new AutoValue_ComponentCreatorDescriptor(
-        annotation, typeElement, factoryMethod, setterMethods.build(), factoryParameters.build());
-  }
-
-  private static ComponentRequirement requirement(
-      ExecutableElement method,
-      VariableElement parameter,
-      TypeMirror type,
-      DependencyRequestFactory dependencyRequestFactory,
-      Element elementForVariableName) {
-    if (isAnnotationPresent(method, BindsInstance.class)
-        || isAnnotationPresent(parameter, BindsInstance.class)) {
-      DependencyRequest request =
-          dependencyRequestFactory.forRequiredResolvedVariable(parameter, type);
-      String variableName = elementForVariableName.getSimpleName().toString();
-      return ComponentRequirement.forBoundInstance(
-          request.key(), request.isNullable(), variableName);
-    }
-
-    return moduleAnnotation(asTypeElement(type)).isPresent()
-        ? ComponentRequirement.forModule(type)
-        : ComponentRequirement.forDependency(type);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentCreatorKind.java b/java/dagger/internal/codegen/binding/ComponentCreatorKind.java
deleted file mode 100644
index b2581d6..0000000
--- a/java/dagger/internal/codegen/binding/ComponentCreatorKind.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 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.binding;
-
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
-
-import com.google.common.base.Ascii;
-
-/** Enumeration of the different kinds of component creators. */
-public enum ComponentCreatorKind {
-  /** {@code @Component.Builder} or one of its subcomponent/production variants. */
-  BUILDER,
-
-  /** {@code @Component.Factory} or one of its subcomponent/production variants. */
-  FACTORY,
-  ;
-
-  /** Name to use as (or as part of) a type name for a creator of this kind. */
-  public String typeName() {
-    return UPPER_UNDERSCORE.to(UPPER_CAMEL, name());
-  }
-
-  /** Name to use for a component's static method returning a creator of this kind. */
-  public String methodName() {
-    return Ascii.toLowerCase(name());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentDescriptor.java b/java/dagger/internal/codegen/binding/ComponentDescriptor.java
deleted file mode 100644
index a7e4cc4..0000000
--- a/java/dagger/internal/codegen/binding/ComponentDescriptor.java
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.type.TypeKind.VOID;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import com.google.errorprone.annotations.CheckReturnValue;
-import dagger.Component;
-import dagger.Module;
-import dagger.Subcomponent;
-import dagger.internal.codegen.base.ComponentAnnotation;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import dagger.model.Scope;
-import dagger.producers.CancellationPolicy;
-import dagger.producers.ProductionComponent;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.stream.Stream;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A component declaration.
- *
- * <p>Represents one type annotated with {@code @Component}, {@code Subcomponent},
- * {@code @ProductionComponent}, or {@code @ProductionSubcomponent}.
- *
- * <p>When validating bindings installed in modules, a {@link ComponentDescriptor} can also
- * represent a synthetic component for the module, where there is an entry point for each binding in
- * the module.
- */
-@AutoValue
-public abstract class ComponentDescriptor {
-  /** The annotation that specifies that {@link #typeElement()} is a component. */
-  public abstract ComponentAnnotation annotation();
-
-  /** Returns {@code true} if this is a subcomponent. */
-  public final boolean isSubcomponent() {
-    return annotation().isSubcomponent();
-  }
-
-  /**
-   * Returns {@code true} if this is a production component or subcomponent, or a
-   * {@code @ProducerModule} when doing module binding validation.
-   */
-  public final boolean isProduction() {
-    return annotation().isProduction();
-  }
-
-  /**
-   * Returns {@code true} if this is a real component, and not a fictional one used to validate
-   * module bindings.
-   */
-  public final boolean isRealComponent() {
-    return annotation().isRealComponent();
-  }
-
-  /**
-   * The element that defines the component. This is the element to which the {@link #annotation()}
-   * was applied.
-   */
-  public abstract TypeElement typeElement();
-
-  /**
-   * The set of component dependencies listed in {@link Component#dependencies} or {@link
-   * ProductionComponent#dependencies()}.
-   */
-  public abstract ImmutableSet<ComponentRequirement> dependencies();
-
-  /** The non-abstract {@link #modules()} and the {@link #dependencies()}. */
-  public final ImmutableSet<ComponentRequirement> dependenciesAndConcreteModules() {
-    return Stream.concat(
-            moduleTypes().stream()
-                .filter(dep -> !dep.getModifiers().contains(ABSTRACT))
-                .map(module -> ComponentRequirement.forModule(module.asType())),
-            dependencies().stream())
-        .collect(toImmutableSet());
-  }
-
-  /**
-   * The {@link ModuleDescriptor modules} declared in {@link Component#modules()} and reachable by
-   * traversing {@link Module#includes()}.
-   */
-  public abstract ImmutableSet<ModuleDescriptor> modules();
-
-  /** The types of the {@link #modules()}. */
-  public final ImmutableSet<TypeElement> moduleTypes() {
-    return modules().stream().map(ModuleDescriptor::moduleElement).collect(toImmutableSet());
-  }
-
-  /**
-   * The types for which the component will need instances if all of its bindings are used. For the
-   * types the component will need in a given binding graph, use {@link
-   * BindingGraph#componentRequirements()}.
-   *
-   * <ul>
-   *   <li>{@linkplain #modules()} modules} with concrete instance bindings
-   *   <li>Bound instances
-   *   <li>{@linkplain #dependencies() dependencies}
-   * </ul>
-   */
-  @Memoized
-  ImmutableSet<ComponentRequirement> requirements() {
-    ImmutableSet.Builder<ComponentRequirement> requirements = ImmutableSet.builder();
-    modules().stream()
-        .filter(
-            module ->
-                module.bindings().stream().anyMatch(ContributionBinding::requiresModuleInstance))
-        .map(module -> ComponentRequirement.forModule(module.moduleElement().asType()))
-        .forEach(requirements::add);
-    requirements.addAll(dependencies());
-    requirements.addAll(
-        creatorDescriptor()
-            .map(ComponentCreatorDescriptor::boundInstanceRequirements)
-            .orElse(ImmutableSet.of()));
-    return requirements.build();
-  }
-
-  /**
-   * This component's {@linkplain #dependencies() dependencies} keyed by each provision or
-   * production method defined by that dependency. Note that the dependencies' types are not simply
-   * the enclosing type of the method; a method may be declared by a supertype of the actual
-   * dependency.
-   */
-  public abstract ImmutableMap<ExecutableElement, ComponentRequirement>
-      dependenciesByDependencyMethod();
-
-  /** The {@linkplain #dependencies() component dependency} that defines a method. */
-  public final ComponentRequirement getDependencyThatDefinesMethod(Element method) {
-    checkArgument(
-        method instanceof ExecutableElement, "method must be an executable element: %s", method);
-    return checkNotNull(
-        dependenciesByDependencyMethod().get(method), "no dependency implements %s", method);
-  }
-
-  /** The scopes of the component. */
-  public abstract ImmutableSet<Scope> scopes();
-
-  /**
-   * All {@link Subcomponent}s which are direct children of this component. This includes
-   * subcomponents installed from {@link Module#subcomponents()} as well as subcomponent {@linkplain
-   * #childComponentsDeclaredByFactoryMethods() factory methods} and {@linkplain
-   * #childComponentsDeclaredByBuilderEntryPoints() builder methods}.
-   */
-  public final ImmutableSet<ComponentDescriptor> childComponents() {
-    return ImmutableSet.<ComponentDescriptor>builder()
-        .addAll(childComponentsDeclaredByFactoryMethods().values())
-        .addAll(childComponentsDeclaredByBuilderEntryPoints().values())
-        .addAll(childComponentsDeclaredByModules())
-        .build();
-  }
-
-  /**
-   * All {@linkplain Subcomponent direct child} components that are declared by a {@linkplain
-   * Module#subcomponents() module's subcomponents}.
-   */
-  abstract ImmutableSet<ComponentDescriptor> childComponentsDeclaredByModules();
-
-  /**
-   * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
-   * factory method.
-   */
-  public abstract ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor>
-      childComponentsDeclaredByFactoryMethods();
-
-  /** Returns a map of {@link #childComponents()} indexed by {@link #typeElement()}. */
-  @Memoized
-  public ImmutableMap<TypeElement, ComponentDescriptor> childComponentsByElement() {
-    return Maps.uniqueIndex(childComponents(), ComponentDescriptor::typeElement);
-  }
-
-  /** Returns the factory method that declares a child component. */
-  final Optional<ComponentMethodDescriptor> getFactoryMethodForChildComponent(
-      ComponentDescriptor childComponent) {
-    return Optional.ofNullable(
-        childComponentsDeclaredByFactoryMethods().inverse().get(childComponent));
-  }
-
-  /**
-   * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
-   * builder method.
-   */
-  abstract ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor>
-      childComponentsDeclaredByBuilderEntryPoints();
-
-  private final Supplier<ImmutableMap<TypeElement, ComponentDescriptor>>
-      childComponentsByBuilderType =
-          Suppliers.memoize(
-              () ->
-                  childComponents().stream()
-                      .filter(child -> child.creatorDescriptor().isPresent())
-                      .collect(
-                          toImmutableMap(
-                              child -> child.creatorDescriptor().get().typeElement(),
-                              child -> child)));
-
-  /** Returns the child component with the given builder type. */
-  final ComponentDescriptor getChildComponentWithBuilderType(TypeElement builderType) {
-    return checkNotNull(
-        childComponentsByBuilderType.get().get(builderType),
-        "no child component found for builder type %s",
-        builderType.getQualifiedName());
-  }
-
-  public abstract ImmutableSet<ComponentMethodDescriptor> componentMethods();
-
-  /** Returns the first component method associated with this binding request, if one exists. */
-  public Optional<ComponentMethodDescriptor> firstMatchingComponentMethod(BindingRequest request) {
-    return componentMethods().stream()
-        .filter(method -> doesComponentMethodMatch(method, request))
-        .findFirst();
-  }
-
-  /** Returns true if the component method matches the binding request. */
-  private static boolean doesComponentMethodMatch(
-      ComponentMethodDescriptor componentMethod, BindingRequest request) {
-    return componentMethod
-        .dependencyRequest()
-        .map(BindingRequest::bindingRequest)
-        .filter(request::equals)
-        .isPresent();
-  }
-
-  /** The entry point methods on the component type. Each has a {@link DependencyRequest}. */
-  public final ImmutableSet<ComponentMethodDescriptor> entryPointMethods() {
-    return componentMethods()
-        .stream()
-        .filter(method -> method.dependencyRequest().isPresent())
-        .collect(toImmutableSet());
-  }
-
-  // TODO(gak): Consider making this non-optional and revising the
-  // interaction between the spec & generation
-  /** Returns a descriptor for the creator type for this component type, if the user defined one. */
-  public abstract Optional<ComponentCreatorDescriptor> creatorDescriptor();
-
-  /**
-   * Returns {@code true} for components that have a creator, either because the user {@linkplain
-   * #creatorDescriptor() specified one} or because it's a top-level component with an implicit
-   * builder.
-   */
-  public final boolean hasCreator() {
-    return !isSubcomponent() || creatorDescriptor().isPresent();
-  }
-
-  /**
-   * Returns the {@link CancellationPolicy} for this component, or an empty optional if either the
-   * component is not a production component or no {@code CancellationPolicy} annotation is present.
-   */
-  public final Optional<CancellationPolicy> cancellationPolicy() {
-    return isProduction()
-        ? Optional.ofNullable(typeElement().getAnnotation(CancellationPolicy.class))
-        : Optional.empty();
-  }
-
-  @Memoized
-  @Override
-  public int hashCode() {
-    // TODO(b/122962745): Only use typeElement().hashCode()
-    return Objects.hash(typeElement(), annotation());
-  }
-
-  // TODO(ronshapiro): simplify the equality semantics
-  @Override
-  public abstract boolean equals(Object obj);
-
-  /** A component method. */
-  @AutoValue
-  public abstract static class ComponentMethodDescriptor {
-    /** The method itself. Note that this may be declared on a supertype of the component. */
-    public abstract ExecutableElement methodElement();
-
-    /**
-     * The dependency request for production, provision, and subcomponent creator methods. Absent
-     * for subcomponent factory methods.
-     */
-    public abstract Optional<DependencyRequest> dependencyRequest();
-
-    /** The subcomponent for subcomponent factory methods and subcomponent creator methods. */
-    public abstract Optional<ComponentDescriptor> subcomponent();
-
-    /**
-     * Returns the return type of {@link #methodElement()} as resolved in the {@link
-     * ComponentDescriptor#typeElement() component type}. If there are no type variables in the
-     * return type, this is the equivalent of {@code methodElement().getReturnType()}.
-     */
-    public TypeMirror resolvedReturnType(DaggerTypes types) {
-      checkState(dependencyRequest().isPresent());
-
-      TypeMirror returnType = methodElement().getReturnType();
-      if (returnType.getKind().isPrimitive() || returnType.getKind().equals(VOID)) {
-        return returnType;
-      }
-      return BindingRequest.bindingRequest(dependencyRequest().get())
-          .requestedType(dependencyRequest().get().key().type(), types);
-    }
-
-    /** A {@link ComponentMethodDescriptor}builder for a method. */
-    public static Builder builder(ExecutableElement method) {
-      return new AutoValue_ComponentDescriptor_ComponentMethodDescriptor.Builder()
-          .methodElement(method);
-    }
-
-    /** A builder of {@link ComponentMethodDescriptor}s. */
-    @AutoValue.Builder
-    @CanIgnoreReturnValue
-    public interface Builder {
-      /** @see ComponentMethodDescriptor#methodElement() */
-      Builder methodElement(ExecutableElement methodElement);
-
-      /** @see ComponentMethodDescriptor#dependencyRequest() */
-      Builder dependencyRequest(DependencyRequest dependencyRequest);
-
-      /** @see ComponentMethodDescriptor#subcomponent() */
-      Builder subcomponent(ComponentDescriptor subcomponent);
-
-      /** Builds the descriptor. */
-      @CheckReturnValue
-      ComponentMethodDescriptor build();
-    }
-  }
-
-  /** No-argument methods defined on {@link Object} that are ignored for contribution. */
-  private static final ImmutableSet<String> NON_CONTRIBUTING_OBJECT_METHOD_NAMES =
-      ImmutableSet.of("toString", "hashCode", "clone", "getClass");
-
-  /**
-   * Returns {@code true} if a method could be a component entry point but not a members-injection
-   * method.
-   */
-  static boolean isComponentContributionMethod(DaggerElements elements, ExecutableElement method) {
-    return method.getParameters().isEmpty()
-        && !method.getReturnType().getKind().equals(VOID)
-        && !elements.getTypeElement(Object.class).equals(method.getEnclosingElement())
-        && !NON_CONTRIBUTING_OBJECT_METHOD_NAMES.contains(method.getSimpleName().toString());
-  }
-
-  /** Returns {@code true} if a method could be a component production entry point. */
-  static boolean isComponentProductionMethod(DaggerElements elements, ExecutableElement method) {
-    return isComponentContributionMethod(elements, method) && isFutureType(method.getReturnType());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java b/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java
deleted file mode 100644
index f13aa50..0000000
--- a/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotation;
-import static dagger.internal.codegen.base.Scopes.productionScope;
-import static dagger.internal.codegen.base.Scopes.scopesOf;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.creatorAnnotationsFor;
-import static dagger.internal.codegen.binding.ComponentDescriptor.isComponentContributionMethod;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.enclosedAnnotatedTypes;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.isSubcomponentCreator;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static javax.lang.model.type.TypeKind.DECLARED;
-import static javax.lang.model.type.TypeKind.VOID;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.base.ComponentAnnotation;
-import dagger.internal.codegen.base.ModuleAnnotation;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Scope;
-import java.util.Optional;
-import java.util.function.Function;
-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;
-import javax.lang.model.type.TypeMirror;
-
-/** A factory for {@link ComponentDescriptor}s. */
-public final class ComponentDescriptorFactory {
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final DependencyRequestFactory dependencyRequestFactory;
-  private final ModuleDescriptor.Factory moduleDescriptorFactory;
-  private final InjectionAnnotations injectionAnnotations;
-
-  @Inject
-  ComponentDescriptorFactory(
-      DaggerElements elements,
-      DaggerTypes types,
-      DependencyRequestFactory dependencyRequestFactory,
-      ModuleDescriptor.Factory moduleDescriptorFactory,
-      InjectionAnnotations injectionAnnotations) {
-    this.elements = elements;
-    this.types = types;
-    this.dependencyRequestFactory = dependencyRequestFactory;
-    this.moduleDescriptorFactory = moduleDescriptorFactory;
-    this.injectionAnnotations = injectionAnnotations;
-  }
-
-  /** Returns a descriptor for a root component type. */
-  public ComponentDescriptor rootComponentDescriptor(TypeElement typeElement) {
-    return create(
-        typeElement,
-        checkAnnotation(
-            typeElement,
-            ComponentAnnotation::rootComponentAnnotation,
-            "must have a component annotation"));
-  }
-
-  /** Returns a descriptor for a subcomponent type. */
-  public ComponentDescriptor subcomponentDescriptor(TypeElement typeElement) {
-    return create(
-        typeElement,
-        checkAnnotation(
-            typeElement,
-            ComponentAnnotation::subcomponentAnnotation,
-            "must have a subcomponent annotation"));
-  }
-
-  /**
-   * Returns a descriptor for a fictional component based on a module type in order to validate its
-   * bindings.
-   */
-  public ComponentDescriptor moduleComponentDescriptor(TypeElement typeElement) {
-    return create(
-        typeElement,
-        ComponentAnnotation.fromModuleAnnotation(
-            checkAnnotation(
-                typeElement, ModuleAnnotation::moduleAnnotation, "must have a module annotation")));
-  }
-
-  private static <A> A checkAnnotation(
-      TypeElement typeElement,
-      Function<TypeElement, Optional<A>> annotationFunction,
-      String message) {
-    return annotationFunction
-        .apply(typeElement)
-        .orElseThrow(() -> new IllegalArgumentException(typeElement + " " + message));
-  }
-
-  private ComponentDescriptor create(
-      TypeElement typeElement, ComponentAnnotation componentAnnotation) {
-    ImmutableSet<ComponentRequirement> componentDependencies =
-        componentAnnotation.dependencyTypes().stream()
-            .map(ComponentRequirement::forDependency)
-            .collect(toImmutableSet());
-
-    ImmutableMap.Builder<ExecutableElement, ComponentRequirement> dependenciesByDependencyMethod =
-        ImmutableMap.builder();
-
-    for (ComponentRequirement componentDependency : componentDependencies) {
-      for (ExecutableElement dependencyMethod :
-          methodsIn(elements.getAllMembers(componentDependency.typeElement()))) {
-        if (isComponentContributionMethod(elements, dependencyMethod)) {
-          dependenciesByDependencyMethod.put(dependencyMethod, componentDependency);
-        }
-      }
-    }
-
-    // Start with the component's modules. For fictional components built from a module, start with
-    // that module.
-    ImmutableSet<TypeElement> modules =
-        componentAnnotation.isRealComponent()
-            ? componentAnnotation.modules()
-            : ImmutableSet.of(typeElement);
-
-    ImmutableSet<ModuleDescriptor> transitiveModules =
-        moduleDescriptorFactory.transitiveModules(modules);
-
-    ImmutableSet.Builder<ComponentDescriptor> subcomponentsFromModules = ImmutableSet.builder();
-    for (ModuleDescriptor module : transitiveModules) {
-      for (SubcomponentDeclaration subcomponentDeclaration : module.subcomponentDeclarations()) {
-        TypeElement subcomponent = subcomponentDeclaration.subcomponentType();
-        subcomponentsFromModules.add(subcomponentDescriptor(subcomponent));
-      }
-    }
-
-    ImmutableSet.Builder<ComponentMethodDescriptor> componentMethodsBuilder =
-        ImmutableSet.builder();
-    ImmutableBiMap.Builder<ComponentMethodDescriptor, ComponentDescriptor>
-        subcomponentsByFactoryMethod = ImmutableBiMap.builder();
-    ImmutableBiMap.Builder<ComponentMethodDescriptor, ComponentDescriptor>
-        subcomponentsByBuilderMethod = ImmutableBiMap.builder();
-    if (componentAnnotation.isRealComponent()) {
-      ImmutableSet<ExecutableElement> unimplementedMethods =
-          elements.getUnimplementedMethods(typeElement);
-      for (ExecutableElement componentMethod : unimplementedMethods) {
-        ComponentMethodDescriptor componentMethodDescriptor =
-            getDescriptorForComponentMethod(typeElement, componentAnnotation, componentMethod);
-        componentMethodsBuilder.add(componentMethodDescriptor);
-        componentMethodDescriptor
-            .subcomponent()
-            .ifPresent(
-                subcomponent -> {
-                  // If the dependency request is present, that means the method returns the
-                  // subcomponent factory.
-                  if (componentMethodDescriptor.dependencyRequest().isPresent()) {
-                    subcomponentsByBuilderMethod.put(componentMethodDescriptor, subcomponent);
-                  } else {
-                    subcomponentsByFactoryMethod.put(componentMethodDescriptor, subcomponent);
-                  }
-                });
-      }
-    }
-
-    // Validation should have ensured that this set will have at most one element.
-    ImmutableSet<DeclaredType> enclosedCreators =
-        creatorAnnotationsFor(componentAnnotation).stream()
-            .flatMap(
-                creatorAnnotation ->
-                    enclosedAnnotatedTypes(typeElement, creatorAnnotation).stream())
-            .collect(toImmutableSet());
-    Optional<ComponentCreatorDescriptor> creatorDescriptor =
-        enclosedCreators.isEmpty()
-            ? Optional.empty()
-            : Optional.of(
-                ComponentCreatorDescriptor.create(
-                    getOnlyElement(enclosedCreators), elements, types, dependencyRequestFactory));
-
-    ImmutableSet<Scope> scopes = scopesOf(typeElement);
-    if (componentAnnotation.isProduction()) {
-      scopes = ImmutableSet.<Scope>builder().addAll(scopes).add(productionScope(elements)).build();
-    }
-
-    return new AutoValue_ComponentDescriptor(
-        componentAnnotation,
-        typeElement,
-        componentDependencies,
-        transitiveModules,
-        dependenciesByDependencyMethod.build(),
-        scopes,
-        subcomponentsFromModules.build(),
-        subcomponentsByFactoryMethod.build(),
-        subcomponentsByBuilderMethod.build(),
-        componentMethodsBuilder.build(),
-        creatorDescriptor);
-  }
-
-  private ComponentMethodDescriptor getDescriptorForComponentMethod(
-      TypeElement componentElement,
-      ComponentAnnotation componentAnnotation,
-      ExecutableElement componentMethod) {
-    ComponentMethodDescriptor.Builder descriptor =
-        ComponentMethodDescriptor.builder(componentMethod);
-
-    ExecutableType resolvedComponentMethod =
-        MoreTypes.asExecutable(
-            types.asMemberOf(MoreTypes.asDeclared(componentElement.asType()), componentMethod));
-    TypeMirror returnType = resolvedComponentMethod.getReturnType();
-    if (returnType.getKind().equals(DECLARED)
-        && !injectionAnnotations.getQualifier(componentMethod).isPresent()) {
-      TypeElement returnTypeElement = asTypeElement(returnType);
-      if (subcomponentAnnotation(returnTypeElement).isPresent()) {
-        // It's a subcomponent factory method. There is no dependency request, and there could be
-        // any number of parameters. Just return the descriptor.
-        return descriptor.subcomponent(subcomponentDescriptor(returnTypeElement)).build();
-      }
-      if (isSubcomponentCreator(returnTypeElement)) {
-        descriptor.subcomponent(
-            subcomponentDescriptor(asType(returnTypeElement.getEnclosingElement())));
-      }
-    }
-
-    switch (componentMethod.getParameters().size()) {
-      case 0:
-        checkArgument(
-            !returnType.getKind().equals(VOID),
-            "component method cannot be void: %s",
-            componentMethod);
-        descriptor.dependencyRequest(
-            componentAnnotation.isProduction()
-                ? dependencyRequestFactory.forComponentProductionMethod(
-                    componentMethod, resolvedComponentMethod)
-                : dependencyRequestFactory.forComponentProvisionMethod(
-                    componentMethod, resolvedComponentMethod));
-        break;
-
-      case 1:
-        checkArgument(
-            returnType.getKind().equals(VOID)
-                || MoreTypes.equivalence()
-                    .equivalent(returnType, resolvedComponentMethod.getParameterTypes().get(0)),
-            "members injection method must return void or parameter type: %s",
-            componentMethod);
-        descriptor.dependencyRequest(
-            dependencyRequestFactory.forComponentMembersInjectionMethod(
-                componentMethod, resolvedComponentMethod));
-        break;
-
-      default:
-        throw new IllegalArgumentException(
-            "component method has too many parameters: " + componentMethod);
-    }
-
-    return descriptor.build();
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentKind.java b/java/dagger/internal/codegen/binding/ComponentKind.java
deleted file mode 100644
index 1cb3d7c..0000000
--- a/java/dagger/internal/codegen/binding/ComponentKind.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.collect.Sets.immutableEnumSet;
-import static dagger.internal.codegen.extension.DaggerStreams.stream;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.extension.DaggerStreams.valuesOf;
-import static java.util.EnumSet.allOf;
-
-import com.google.common.collect.ImmutableSet;
-import dagger.Component;
-import dagger.Module;
-import dagger.Subcomponent;
-import dagger.producers.ProducerModule;
-import dagger.producers.ProductionComponent;
-import dagger.producers.ProductionSubcomponent;
-import java.lang.annotation.Annotation;
-import java.util.Optional;
-import javax.lang.model.element.TypeElement;
-
-/** Enumeration of the different kinds of components. */
-public enum ComponentKind {
-  /** {@code @Component} */
-  COMPONENT(Component.class, true, false),
-
-  /** {@code @Subcomponent} */
-  SUBCOMPONENT(Subcomponent.class, false, false),
-
-  /** {@code @ProductionComponent} */
-  PRODUCTION_COMPONENT(ProductionComponent.class, true, true),
-
-  /** {@code @ProductionSubcomponent} */
-  PRODUCTION_SUBCOMPONENT(ProductionSubcomponent.class, false, true),
-
-  /**
-   * Kind for a descriptor that was generated from a {@link Module} instead of a component type in
-   * order to validate the module's bindings.
-   */
-  MODULE(Module.class, true, false),
-
-  /**
-   * Kind for a descriptor was generated from a {@link ProducerModule} instead of a component type
-   * in order to validate the module's bindings.
-   */
-  PRODUCER_MODULE(ProducerModule.class, true, true),
-  ;
-
-  private static final ImmutableSet<ComponentKind> ROOT_COMPONENT_KINDS =
-      valuesOf(ComponentKind.class)
-          .filter(kind -> !kind.isForModuleValidation())
-          .filter(kind -> kind.isRoot())
-          .collect(toImmutableSet());
-
-  private static final ImmutableSet<ComponentKind> SUBCOMPONENT_KINDS =
-      valuesOf(ComponentKind.class)
-          .filter(kind -> !kind.isForModuleValidation())
-          .filter(kind -> !kind.isRoot())
-          .collect(toImmutableSet());
-
-  /** Returns the set of kinds for root components. */
-  public static ImmutableSet<ComponentKind> rootComponentKinds() {
-    return ROOT_COMPONENT_KINDS;
-  }
-
-  /** Returns the set of kinds for subcomponents. */
-  public static ImmutableSet<ComponentKind> subcomponentKinds() {
-    return SUBCOMPONENT_KINDS;
-  }
-
-  /** Returns the annotations for components of the given kinds. */
-  public static ImmutableSet<Class<? extends Annotation>> annotationsFor(
-      Iterable<ComponentKind> kinds) {
-    return stream(kinds).map(ComponentKind::annotation).collect(toImmutableSet());
-  }
-
-  /** Returns the set of component kinds the given {@code element} has annotations for. */
-  public static ImmutableSet<ComponentKind> getComponentKinds(TypeElement element) {
-    return valuesOf(ComponentKind.class)
-        .filter(kind -> isAnnotationPresent(element, kind.annotation()))
-        .collect(toImmutableSet());
-  }
-
-  /**
-   * Returns the kind of an annotated element if it is annotated with one of the {@linkplain
-   * #annotation() annotations}.
-   *
-   * @throws IllegalArgumentException if the element is annotated with more than one of the
-   *     annotations
-   */
-  public static Optional<ComponentKind> forAnnotatedElement(TypeElement element) {
-    ImmutableSet<ComponentKind> kinds = getComponentKinds(element);
-    if (kinds.size() > 1) {
-      throw new IllegalArgumentException(
-          element + " cannot be annotated with more than one of " + annotationsFor(kinds));
-    }
-    return kinds.stream().findAny();
-  }
-
-  private final Class<? extends Annotation> annotation;
-  private final boolean isRoot;
-  private final boolean production;
-
-  ComponentKind(
-      Class<? extends Annotation> annotation,
-      boolean isRoot,
-      boolean production) {
-    this.annotation = annotation;
-    this.isRoot = isRoot;
-    this.production = production;
-  }
-
-  /** Returns the annotation that marks a component of this kind. */
-  public Class<? extends Annotation> annotation() {
-    return annotation;
-  }
-
-  /** Returns the kinds of modules that can be used with a component of this kind. */
-  public ImmutableSet<ModuleKind> legalModuleKinds() {
-    return isProducer()
-        ? immutableEnumSet(allOf(ModuleKind.class))
-        : immutableEnumSet(ModuleKind.MODULE);
-  }
-
-  /** Returns the kinds of subcomponents a component of this kind can have. */
-  public ImmutableSet<ComponentKind> legalSubcomponentKinds() {
-    return isProducer()
-        ? immutableEnumSet(PRODUCTION_SUBCOMPONENT)
-        : immutableEnumSet(SUBCOMPONENT, PRODUCTION_SUBCOMPONENT);
-  }
-
-  /**
-   * Returns {@code true} if the descriptor is for a root component (not a subcomponent) or is for
-   * {@linkplain #isForModuleValidation() module-validation}.
-   */
-  public boolean isRoot() {
-    return isRoot;
-  }
-
-  /** Returns true if this is a production component. */
-  public boolean isProducer() {
-    return production;
-  }
-
-  /** Returns {@code true} if the descriptor is for a module in order to validate its bindings. */
-  public boolean isForModuleValidation() {
-    switch (this) {
-      case MODULE:
-      case PRODUCER_MODULE:
-        return true;
-      default:
-        // fall through
-    }
-    return false;
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentNodeImpl.java b/java/dagger/internal/codegen/binding/ComponentNodeImpl.java
deleted file mode 100644
index 0947c25..0000000
--- a/java/dagger/internal/codegen/binding/ComponentNodeImpl.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.binding;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-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
-public abstract class ComponentNodeImpl implements ComponentNode {
-  public static ComponentNode create(
-      ComponentPath componentPath, ComponentDescriptor componentDescriptor) {
-    return new AutoValue_ComponentNodeImpl(componentPath, componentDescriptor);
-  }
-
-  @Override
-  public final boolean isSubcomponent() {
-    return componentDescriptor().isSubcomponent();
-  }
-
-  @Override
-  public boolean isRealComponent() {
-    return componentDescriptor().isRealComponent();
-  }
-
-  @Override
-  public final ImmutableSet<DependencyRequest> entryPoints() {
-    return componentDescriptor().entryPointMethods().stream()
-        .map(method -> method.dependencyRequest().get())
-        .collect(toImmutableSet());
-  }
-
-  @Override
-  public ImmutableSet<Scope> scopes() {
-    return componentDescriptor().scopes();
-  }
-
-  public abstract ComponentDescriptor componentDescriptor();
-
-  @Override
-  public final String toString() {
-    return componentPath().toString();
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentRequirement.java b/java/dagger/internal/codegen/binding/ComponentRequirement.java
deleted file mode 100644
index fa24b56..0000000
--- a/java/dagger/internal/codegen/binding/ComponentRequirement.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2016 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.binding;
-
-import static com.google.auto.common.MoreElements.getLocalAndInheritedMethods;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.SourceFiles.simpleVariableName;
-import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
-import static javax.lang.model.element.ElementKind.CONSTRUCTOR;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Equivalence;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.Binds;
-import dagger.BindsOptionalOf;
-import dagger.Provides;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingKind;
-import dagger.model.Key;
-import dagger.multibindings.Multibinds;
-import dagger.producers.Produces;
-import java.util.Optional;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-/** A type that a component needs an instance of. */
-@AutoValue
-public abstract class ComponentRequirement {
-  /** The kind of the {@link ComponentRequirement}. */
-  public enum Kind {
-    /** A type listed in the component's {@code dependencies} attribute. */
-    DEPENDENCY,
-
-    /** A type listed in the component or subcomponent's {@code modules} attribute. */
-    MODULE,
-
-    /**
-     * An object that is passed to a builder's {@link dagger.BindsInstance @BindsInstance} method.
-     */
-    BOUND_INSTANCE,
-    ;
-
-    public boolean isBoundInstance() {
-      return equals(BOUND_INSTANCE);
-    }
-
-    public boolean isModule() {
-      return equals(MODULE);
-    }
-  }
-
-  /** The kind of requirement. */
-  public abstract Kind kind();
-
-  /** Returns true if this is a {@link Kind#BOUND_INSTANCE} requirement. */
-  // TODO(ronshapiro): consider removing this and inlining the usages
-  final boolean isBoundInstance() {
-    return kind().isBoundInstance();
-  }
-
-  /**
-   * The type of the instance the component must have, wrapped so that requirements can be used as
-   * value types.
-   */
-  public abstract Equivalence.Wrapper<TypeMirror> wrappedType();
-
-  /** The type of the instance the component must have. */
-  public TypeMirror type() {
-    return wrappedType().get();
-  }
-
-  /** The element associated with the type of this requirement. */
-  public TypeElement typeElement() {
-    return MoreTypes.asTypeElement(type());
-  }
-
-  /** The action a component builder should take if it {@code null} is passed. */
-  public enum NullPolicy {
-    /** Make a new instance. */
-    NEW,
-    /** Throw an exception. */
-    THROW,
-    /** Allow use of null values. */
-    ALLOW,
-  }
-
-  /**
-   * An override for the requirement's null policy. If set, this is used as the null policy instead
-   * of the default behavior in {@link #nullPolicy}.
-   *
-   * <p>Some implementations' null policy can be determined upon construction (e.g., for binding
-   * instances), but others' require Elements and Types, which must wait until {@link #nullPolicy}
-   * is called.
-   */
-  abstract Optional<NullPolicy> overrideNullPolicy();
-
-  /** The requirement's null policy. */
-  public NullPolicy nullPolicy(
-      DaggerElements elements, DaggerTypes types, KotlinMetadataUtil metadataUtil) {
-    if (overrideNullPolicy().isPresent()) {
-      return overrideNullPolicy().get();
-    }
-    switch (kind()) {
-      case MODULE:
-        return componentCanMakeNewInstances(typeElement(), metadataUtil)
-            ? NullPolicy.NEW
-            : requiresAPassedInstance(elements, types, metadataUtil)
-                ? NullPolicy.THROW
-                : NullPolicy.ALLOW;
-      case DEPENDENCY:
-      case BOUND_INSTANCE:
-        return NullPolicy.THROW;
-    }
-    throw new AssertionError();
-  }
-
-  /**
-   * Returns true if the passed {@link ComponentRequirement} requires a passed instance in order to
-   * be used within a component.
-   */
-  public boolean requiresAPassedInstance(
-      DaggerElements elements, DaggerTypes types, KotlinMetadataUtil metadataUtil) {
-    if (!kind().isModule()) {
-      // Bound instances and dependencies always require the user to provide an instance.
-      return true;
-    }
-    return requiresModuleInstance(elements, types, metadataUtil)
-        && !componentCanMakeNewInstances(typeElement(), metadataUtil);
-  }
-
-  /**
-   * Returns {@code true} if an instance is needed for this (module) requirement.
-   *
-   * <p>An instance is only needed if there is a binding method on the module that is neither {@code
-   * abstract} nor {@code static}; if all bindings are one of those, then there should be no
-   * possible dependency on instance state in the module's bindings.
-   *
-   * <p>Alternatively, if the module is a Kotlin Object then the binding methods are considered
-   * {@code static}, requiring no module instance.
-   */
-  private boolean requiresModuleInstance(
-      DaggerElements elements, DaggerTypes types, KotlinMetadataUtil metadataUtil) {
-    boolean isKotlinObject =
-        metadataUtil.isObjectClass(typeElement())
-            || metadataUtil.isCompanionObjectClass(typeElement());
-    if (isKotlinObject) {
-      return false;
-    }
-
-    ImmutableSet<ExecutableElement> methods =
-        getLocalAndInheritedMethods(typeElement(), types, elements);
-    return methods.stream()
-        .filter(this::isBindingMethod)
-        .map(ExecutableElement::getModifiers)
-        .anyMatch(modifiers -> !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC));
-  }
-
-  private boolean isBindingMethod(ExecutableElement method) {
-    // TODO(cgdecker): At the very least, we should have utility methods to consolidate this stuff
-    // in one place; listing individual annotations all over the place is brittle.
-    return isAnyAnnotationPresent(
-        method,
-        Provides.class,
-        Produces.class,
-        // TODO(ronshapiro): it would be cool to have internal meta-annotations that could describe
-        // these, like @AbstractBindingMethod
-        Binds.class,
-        Multibinds.class,
-        BindsOptionalOf.class);
-  }
-
-  /** The key for this requirement, if one is available. */
-  public abstract Optional<Key> key();
-
-  /** Returns the name for this requirement that could be used as a variable. */
-  public abstract String variableName();
-
-  /** Returns a parameter spec for this requirement. */
-  public ParameterSpec toParameterSpec() {
-    return ParameterSpec.builder(TypeName.get(type()), variableName()).build();
-  }
-
-  public static ComponentRequirement forDependency(TypeMirror type) {
-    return new AutoValue_ComponentRequirement(
-        Kind.DEPENDENCY,
-        MoreTypes.equivalence().wrap(checkNotNull(type)),
-        Optional.empty(),
-        Optional.empty(),
-        simpleVariableName(MoreTypes.asTypeElement(type)));
-  }
-
-  public static ComponentRequirement forModule(TypeMirror type) {
-    return new AutoValue_ComponentRequirement(
-        Kind.MODULE,
-        MoreTypes.equivalence().wrap(checkNotNull(type)),
-        Optional.empty(),
-        Optional.empty(),
-        simpleVariableName(MoreTypes.asTypeElement(type)));
-  }
-
-  static ComponentRequirement forBoundInstance(Key key, boolean nullable, String variableName) {
-    return new AutoValue_ComponentRequirement(
-        Kind.BOUND_INSTANCE,
-        MoreTypes.equivalence().wrap(key.type()),
-        nullable ? Optional.of(NullPolicy.ALLOW) : Optional.empty(),
-        Optional.of(key),
-        variableName);
-  }
-
-  public static ComponentRequirement forBoundInstance(ContributionBinding binding) {
-    checkArgument(binding.kind().equals(BindingKind.BOUND_INSTANCE));
-    return forBoundInstance(
-        binding.key(),
-        binding.nullableType().isPresent(),
-        binding.bindingElement().get().getSimpleName().toString());
-  }
-
-  /**
-   * Returns true if and only if a component can instantiate new instances (typically of a module)
-   * rather than requiring that they be passed.
-   */
-  // TODO(bcorso): Should this method throw if its called knowing that an instance is not needed?
-  public static boolean componentCanMakeNewInstances(
-      TypeElement typeElement, KotlinMetadataUtil metadataUtil) {
-    switch (typeElement.getKind()) {
-      case CLASS:
-        break;
-      case ENUM:
-      case ANNOTATION_TYPE:
-      case INTERFACE:
-        return false;
-      default:
-        throw new AssertionError("TypeElement cannot have kind: " + typeElement.getKind());
-    }
-
-    if (typeElement.getModifiers().contains(ABSTRACT)) {
-      return false;
-    }
-
-    if (requiresEnclosingInstance(typeElement)) {
-      return false;
-    }
-
-    if (metadataUtil.isObjectClass(typeElement)
-        || metadataUtil.isCompanionObjectClass(typeElement)) {
-      return false;
-    }
-
-    for (Element enclosed : typeElement.getEnclosedElements()) {
-      if (enclosed.getKind().equals(CONSTRUCTOR)
-          && MoreElements.asExecutable(enclosed).getParameters().isEmpty()
-          && !enclosed.getModifiers().contains(PRIVATE)) {
-        return true;
-      }
-    }
-
-    // TODO(gak): still need checks for visibility
-
-    return false;
-  }
-
-  private static boolean requiresEnclosingInstance(TypeElement typeElement) {
-    switch (typeElement.getNestingKind()) {
-      case TOP_LEVEL:
-        return false;
-      case MEMBER:
-        return !typeElement.getModifiers().contains(STATIC);
-      case ANONYMOUS:
-      case LOCAL:
-        return true;
-    }
-    throw new AssertionError(
-        "TypeElement cannot have nesting kind: " + typeElement.getNestingKind());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ConfigurationAnnotations.java b/java/dagger/internal/codegen/binding/ConfigurationAnnotations.java
deleted file mode 100644
index 539a66a..0000000
--- a/java/dagger/internal/codegen/binding/ConfigurationAnnotations.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.consumingIterable;
-import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotation;
-import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
-import static dagger.internal.codegen.base.MoreAnnotationMirrors.getTypeListValue;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.subcomponentCreatorAnnotations;
-import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
-import static javax.lang.model.util.ElementFilter.typesIn;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-import dagger.Component;
-import dagger.Module;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.lang.annotation.Annotation;
-import java.util.ArrayDeque;
-import java.util.List;
-import java.util.Optional;
-import java.util.Queue;
-import java.util.Set;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * Utility methods related to dagger configuration annotations (e.g.: {@link Component} and {@link
- * Module}).
- */
-public final class ConfigurationAnnotations {
-
-  public static Optional<TypeElement> getSubcomponentCreator(TypeElement subcomponent) {
-    checkArgument(subcomponentAnnotation(subcomponent).isPresent());
-    for (TypeElement nestedType : typesIn(subcomponent.getEnclosedElements())) {
-      if (isSubcomponentCreator(nestedType)) {
-        return Optional.of(nestedType);
-      }
-    }
-    return Optional.empty();
-  }
-
-  static boolean isSubcomponentCreator(Element element) {
-    return isAnyAnnotationPresent(element, subcomponentCreatorAnnotations());
-  }
-
-  // Dagger 1 support.
-  public static ImmutableList<TypeMirror> getModuleInjects(AnnotationMirror moduleAnnotation) {
-    checkNotNull(moduleAnnotation);
-    return getTypeListValue(moduleAnnotation, "injects");
-  }
-
-  /** Returns the first type that specifies this' nullability, or empty if none. */
-  public static Optional<DeclaredType> getNullableType(Element element) {
-    List<? extends AnnotationMirror> mirrors = element.getAnnotationMirrors();
-    for (AnnotationMirror mirror : mirrors) {
-      if (mirror.getAnnotationType().asElement().getSimpleName().contentEquals("Nullable")) {
-        return Optional.of(mirror.getAnnotationType());
-      }
-    }
-    return Optional.empty();
-  }
-
-  /**
-   * Returns the full set of modules transitively {@linkplain Module#includes included} from the
-   * given seed modules. If a module is malformed and a type listed in {@link Module#includes} is
-   * not annotated with {@link Module}, it is ignored.
-   *
-   * @deprecated Use {@link ComponentDescriptor#modules()}.
-   */
-  @Deprecated
-  public static ImmutableSet<TypeElement> getTransitiveModules(
-      DaggerTypes types, DaggerElements elements, Iterable<TypeElement> seedModules) {
-    TypeMirror objectType = elements.getTypeElement(Object.class).asType();
-    Queue<TypeElement> moduleQueue = new ArrayDeque<>();
-    Iterables.addAll(moduleQueue, seedModules);
-    Set<TypeElement> moduleElements = Sets.newLinkedHashSet();
-    for (TypeElement moduleElement : consumingIterable(moduleQueue)) {
-      moduleAnnotation(moduleElement)
-          .ifPresent(
-              moduleAnnotation -> {
-                ImmutableSet.Builder<TypeElement> moduleDependenciesBuilder =
-                    ImmutableSet.builder();
-                moduleDependenciesBuilder.addAll(moduleAnnotation.includes());
-                // We don't recur on the parent class because we don't want the parent class as a
-                // root that the component depends on, and also because we want the dependencies
-                // rooted against this element, not the parent.
-                addIncludesFromSuperclasses(
-                    types, moduleElement, moduleDependenciesBuilder, objectType);
-                ImmutableSet<TypeElement> moduleDependencies = moduleDependenciesBuilder.build();
-                moduleElements.add(moduleElement);
-                for (TypeElement dependencyType : moduleDependencies) {
-                  if (!moduleElements.contains(dependencyType)) {
-                    moduleQueue.add(dependencyType);
-                  }
-                }
-              });
-    }
-    return ImmutableSet.copyOf(moduleElements);
-  }
-
-  /** Returns the enclosed types annotated with the given annotation. */
-  public static ImmutableList<DeclaredType> enclosedAnnotatedTypes(
-      TypeElement typeElement, Class<? extends Annotation> annotation) {
-    final ImmutableList.Builder<DeclaredType> builders = ImmutableList.builder();
-    for (TypeElement element : typesIn(typeElement.getEnclosedElements())) {
-      if (MoreElements.isAnnotationPresent(element, annotation)) {
-        builders.add(MoreTypes.asDeclared(element.asType()));
-      }
-    }
-    return builders.build();
-  }
-
-  /** Traverses includes from superclasses and adds them into the builder. */
-  private static void addIncludesFromSuperclasses(
-      DaggerTypes types,
-      TypeElement element,
-      ImmutableSet.Builder<TypeElement> builder,
-      TypeMirror objectType) {
-    // Also add the superclass to the queue, in case any @Module definitions were on that.
-    TypeMirror superclass = element.getSuperclass();
-    while (!types.isSameType(objectType, superclass)
-        && superclass.getKind().equals(TypeKind.DECLARED)) {
-      element = MoreElements.asType(types.asElement(superclass));
-      moduleAnnotation(element)
-          .ifPresent(moduleAnnotation -> builder.addAll(moduleAnnotation.includes()));
-      superclass = element.getSuperclass();
-    }
-  }
-
-  private ConfigurationAnnotations() {}
-}
diff --git a/java/dagger/internal/codegen/binding/ContributionBinding.java b/java/dagger/internal/codegen/binding/ContributionBinding.java
deleted file mode 100644
index 1942e8c..0000000
--- a/java/dagger/internal/codegen/binding/ContributionBinding.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static dagger.internal.codegen.base.MoreAnnotationMirrors.unwrapOptionalEquivalence;
-import static dagger.internal.codegen.binding.ContributionBinding.FactoryCreationStrategy.CLASS_CONSTRUCTOR;
-import static dagger.internal.codegen.binding.ContributionBinding.FactoryCreationStrategy.DELEGATE;
-import static dagger.internal.codegen.binding.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
-import static java.util.Arrays.asList;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.base.Equivalence;
-import com.google.common.base.Preconditions;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import com.google.errorprone.annotations.CheckReturnValue;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.ContributionType.HasContributionType;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.SetType;
-import dagger.model.BindingKind;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * An abstract class for a value object representing the mechanism by which a {@link Key} can be
- * contributed to a dependency graph.
- */
-public abstract class ContributionBinding extends Binding implements HasContributionType {
-
-  /** Returns the type that specifies this' nullability, absent if not nullable. */
-  public abstract Optional<DeclaredType> nullableType();
-
-  public abstract Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedMapKeyAnnotation();
-
-  public final Optional<AnnotationMirror> mapKeyAnnotation() {
-    return unwrapOptionalEquivalence(wrappedMapKeyAnnotation());
-  }
-
-  /** If {@link #bindingElement()} is a method that returns a primitive type, returns that type. */
-  public final Optional<TypeMirror> contributedPrimitiveType() {
-    return bindingElement()
-        .filter(bindingElement -> bindingElement instanceof ExecutableElement)
-        .map(bindingElement -> MoreElements.asExecutable(bindingElement).getReturnType())
-        .filter(type -> type.getKind().isPrimitive());
-  }
-
-  @Override
-  public boolean requiresModuleInstance() {
-    return !isContributingModuleKotlinObject().orElse(false) && super.requiresModuleInstance();
-  }
-
-  @Override
-  public final boolean isNullable() {
-    return nullableType().isPresent();
-  }
-
-  /**
-   * Returns {@code true} if the contributing module is a Kotlin object. Note that a companion
-   * object is also considered a Kotlin object.
-   */
-  abstract Optional<Boolean> isContributingModuleKotlinObject();
-
-  /** The strategy for getting an instance of a factory for a {@link ContributionBinding}. */
-  public enum FactoryCreationStrategy {
-    /** The factory class is a single instance. */
-    SINGLETON_INSTANCE,
-    /** The factory must be created by calling the constructor. */
-    CLASS_CONSTRUCTOR,
-    /** The factory is simply delegated to another. */
-    DELEGATE,
-  }
-
-  /**
-   * Returns the {@link FactoryCreationStrategy} appropriate for a binding.
-   *
-   * <p>Delegate bindings use the {@link FactoryCreationStrategy#DELEGATE} strategy.
-   *
-   * <p>Bindings without dependencies that don't require a module instance use the {@link
-   * FactoryCreationStrategy#SINGLETON_INSTANCE} strategy.
-   *
-   * <p>All other bindings use the {@link FactoryCreationStrategy#CLASS_CONSTRUCTOR} strategy.
-   */
-  public final FactoryCreationStrategy factoryCreationStrategy() {
-    switch (kind()) {
-      case DELEGATE:
-        return DELEGATE;
-      case PROVISION:
-        return dependencies().isEmpty() && !requiresModuleInstance()
-            ? SINGLETON_INSTANCE
-            : CLASS_CONSTRUCTOR;
-      case INJECTION:
-      case MULTIBOUND_SET:
-      case MULTIBOUND_MAP:
-        return dependencies().isEmpty() ? SINGLETON_INSTANCE : CLASS_CONSTRUCTOR;
-      default:
-        return CLASS_CONSTRUCTOR;
-    }
-  }
-
-  /**
-   * The {@link TypeMirror type} for the {@code Factory<T>} or {@code Producer<T>} which is created
-   * for this binding. Uses the binding's key, V in the case of {@code Map<K, FrameworkClass<V>>>},
-   * and E {@code Set<E>} for {@link dagger.multibindings.IntoSet @IntoSet} methods.
-   */
-  public final TypeMirror contributedType() {
-    switch (contributionType()) {
-      case MAP:
-        return MapType.from(key()).unwrappedFrameworkValueType();
-      case SET:
-        return SetType.from(key()).elementType();
-      case SET_VALUES:
-      case UNIQUE:
-        return key().type();
-    }
-    throw new AssertionError();
-  }
-
-  /**
-   * Returns {@link BindingKind#MULTIBOUND_SET} or {@link
-   * BindingKind#MULTIBOUND_MAP} if the key is a set or map.
-   *
-   * @throws IllegalArgumentException if {@code key} is neither a set nor a map
-   */
-  static BindingKind bindingKindForMultibindingKey(Key key) {
-    if (SetType.isSet(key)) {
-      return BindingKind.MULTIBOUND_SET;
-    } else if (MapType.isMap(key)) {
-      return BindingKind.MULTIBOUND_MAP;
-    } else {
-      throw new IllegalArgumentException(String.format("key is not for a set or map: %s", key));
-    }
-  }
-
-  public abstract Builder<?, ?> toBuilder();
-
-  /**
-   * Base builder for {@link com.google.auto.value.AutoValue @AutoValue} subclasses of {@link
-   * ContributionBinding}.
-   */
-  @CanIgnoreReturnValue
-  public abstract static class Builder<C extends ContributionBinding, B extends Builder<C, B>> {
-    public abstract B dependencies(Iterable<DependencyRequest> dependencies);
-
-    public B dependencies(DependencyRequest... dependencies) {
-      return dependencies(asList(dependencies));
-    }
-
-    public abstract B unresolved(C unresolved);
-
-    public abstract B contributionType(ContributionType contributionType);
-
-    public abstract B bindingElement(Element bindingElement);
-
-    abstract B bindingElement(Optional<Element> bindingElement);
-
-    public final B clearBindingElement() {
-      return bindingElement(Optional.empty());
-    };
-
-    abstract B contributingModule(TypeElement contributingModule);
-
-    abstract B isContributingModuleKotlinObject(boolean isModuleKotlinObject);
-
-    public abstract B key(Key key);
-
-    public abstract B nullableType(Optional<DeclaredType> nullableType);
-
-    abstract B wrappedMapKeyAnnotation(
-        Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedMapKeyAnnotation);
-
-    public abstract B kind(BindingKind kind);
-
-    @CheckReturnValue
-    abstract C autoBuild();
-
-    @CheckReturnValue
-    public C build() {
-      C binding = autoBuild();
-      Preconditions.checkState(
-          binding.contributingModule().isPresent()
-              == binding.isContributingModuleKotlinObject().isPresent(),
-          "The contributionModule and isModuleKotlinObject must both be set together.");
-      return binding;
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/DelegateDeclaration.java b/java/dagger/internal/codegen/binding/DelegateDeclaration.java
deleted file mode 100644
index b6c3c38..0000000
--- a/java/dagger/internal/codegen/binding/DelegateDeclaration.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2016 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.binding;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.base.MoreAnnotationMirrors.wrapOptionalInEquivalence;
-import static dagger.internal.codegen.binding.MapKeys.getMapKey;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.base.Equivalence;
-import com.google.common.collect.Iterables;
-import dagger.Binds;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.ContributionType.HasContributionType;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.ExecutableType;
-
-/** The declaration for a delegate binding established by a {@link Binds} method. */
-@AutoValue
-public abstract class DelegateDeclaration extends BindingDeclaration
-    implements HasContributionType {
-  abstract DependencyRequest delegateRequest();
-
-  abstract Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedMapKey();
-
-  @Memoized
-  @Override
-  public abstract int hashCode();
-
-  @Override
-  public abstract boolean equals(Object obj);
-
-  /** A {@link DelegateDeclaration} factory. */
-  public static final class Factory {
-    private final DaggerTypes types;
-    private final KeyFactory keyFactory;
-    private final DependencyRequestFactory dependencyRequestFactory;
-
-    @Inject
-    Factory(
-        DaggerTypes types,
-        KeyFactory keyFactory,
-        DependencyRequestFactory dependencyRequestFactory) {
-      this.types = types;
-      this.keyFactory = keyFactory;
-      this.dependencyRequestFactory = dependencyRequestFactory;
-    }
-
-    public DelegateDeclaration create(
-        ExecutableElement bindsMethod, TypeElement contributingModule) {
-      checkArgument(MoreElements.isAnnotationPresent(bindsMethod, Binds.class));
-      ExecutableType resolvedMethod =
-          MoreTypes.asExecutable(
-              types.asMemberOf(MoreTypes.asDeclared(contributingModule.asType()), bindsMethod));
-      DependencyRequest delegateRequest =
-          dependencyRequestFactory.forRequiredResolvedVariable(
-              Iterables.getOnlyElement(bindsMethod.getParameters()),
-              Iterables.getOnlyElement(resolvedMethod.getParameterTypes()));
-      return new AutoValue_DelegateDeclaration(
-          ContributionType.fromBindingElement(bindsMethod),
-          keyFactory.forBindsMethod(bindsMethod, contributingModule),
-          Optional.<Element>of(bindsMethod),
-          Optional.of(contributingModule),
-          delegateRequest,
-          wrapOptionalInEquivalence(getMapKey(bindsMethod)));
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/DependencyEdgeImpl.java b/java/dagger/internal/codegen/binding/DependencyEdgeImpl.java
deleted file mode 100644
index f11517e..0000000
--- a/java/dagger/internal/codegen/binding/DependencyEdgeImpl.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.binding;
-
-import dagger.internal.codegen.base.ElementFormatter;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.DependencyRequest;
-
-/** An implementation of {@link DependencyEdge}. */
-final class DependencyEdgeImpl implements DependencyEdge {
-
-  private final DependencyRequest dependencyRequest;
-  private final boolean entryPoint;
-
-  DependencyEdgeImpl(DependencyRequest dependencyRequest, boolean entryPoint) {
-    this.dependencyRequest = dependencyRequest;
-    this.entryPoint = entryPoint;
-  }
-
-  @Override
-  public DependencyRequest dependencyRequest() {
-    return dependencyRequest;
-  }
-
-  @Override
-  public boolean isEntryPoint() {
-    return entryPoint;
-  }
-
-  @Override
-  public String toString() {
-    String string =
-        dependencyRequest
-            .requestElement()
-            .map(ElementFormatter::elementToString)
-            .orElseGet(
-                () ->
-                    "synthetic request for "
-                        + dependencyRequest.kind().format(dependencyRequest.key()));
-    return entryPoint ? string + " (entry point)" : string;
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/DependencyRequestFactory.java b/java/dagger/internal/codegen/binding/DependencyRequestFactory.java
deleted file mode 100644
index 707de4c..0000000
--- a/java/dagger/internal/codegen/binding/DependencyRequestFactory.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.auto.common.MoreTypes.isTypeOf;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.RequestKinds.extractKeyType;
-import static dagger.internal.codegen.base.RequestKinds.frameworkClass;
-import static dagger.internal.codegen.base.RequestKinds.getRequestKind;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.getNullableType;
-import static dagger.internal.codegen.langmodel.DaggerTypes.unwrapType;
-import static dagger.model.RequestKind.FUTURE;
-import static dagger.model.RequestKind.INSTANCE;
-import static dagger.model.RequestKind.MEMBERS_INJECTION;
-import static dagger.model.RequestKind.PRODUCER;
-import static dagger.model.RequestKind.PROVIDER;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
-import dagger.Lazy;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.OptionalType;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-import java.util.List;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * Factory for {@link DependencyRequest}s.
- *
- * <p>Any factory method may throw {@link TypeNotPresentException} if a type is not available, which
- * may mean that the type will be generated in a later round of processing.
- */
-public final class DependencyRequestFactory {
-  private final KeyFactory keyFactory;
-  private final InjectionAnnotations injectionAnnotations;
-
-  @Inject
-  DependencyRequestFactory(KeyFactory keyFactory, InjectionAnnotations injectionAnnotations) {
-    this.keyFactory = keyFactory;
-    this.injectionAnnotations = injectionAnnotations;
-  }
-
-  ImmutableSet<DependencyRequest> forRequiredResolvedVariables(
-      List<? extends VariableElement> variables, List<? extends TypeMirror> resolvedTypes) {
-    checkState(resolvedTypes.size() == variables.size());
-    ImmutableSet.Builder<DependencyRequest> builder = ImmutableSet.builder();
-    for (int i = 0; i < variables.size(); i++) {
-      builder.add(forRequiredResolvedVariable(variables.get(i), resolvedTypes.get(i)));
-    }
-    return builder.build();
-  }
-
-  /**
-   * Creates synthetic dependency requests for each individual multibinding contribution in {@code
-   * multibindingContributions}.
-   */
-  ImmutableSet<DependencyRequest> forMultibindingContributions(
-      Key multibindingKey, Iterable<ContributionBinding> multibindingContributions) {
-    ImmutableSet.Builder<DependencyRequest> requests = ImmutableSet.builder();
-    for (ContributionBinding multibindingContribution : multibindingContributions) {
-      requests.add(forMultibindingContribution(multibindingKey, multibindingContribution));
-    }
-    return requests.build();
-  }
-
-  /** Creates a synthetic dependency request for one individual {@code multibindingContribution}. */
-  private DependencyRequest forMultibindingContribution(
-      Key multibindingKey, ContributionBinding multibindingContribution) {
-    checkArgument(
-        multibindingContribution.key().multibindingContributionIdentifier().isPresent(),
-        "multibindingContribution's key must have a multibinding contribution identifier: %s",
-        multibindingContribution);
-    return DependencyRequest.builder()
-        .kind(multibindingContributionRequestKind(multibindingKey, multibindingContribution))
-        .key(multibindingContribution.key())
-        .build();
-  }
-
-  // TODO(b/28555349): support PROVIDER_OF_LAZY here too
-  private static final ImmutableSet<RequestKind> WRAPPING_MAP_VALUE_FRAMEWORK_TYPES =
-      ImmutableSet.of(PROVIDER, PRODUCER);
-
-  private RequestKind multibindingContributionRequestKind(
-      Key multibindingKey, ContributionBinding multibindingContribution) {
-    switch (multibindingContribution.contributionType()) {
-      case MAP:
-        MapType mapType = MapType.from(multibindingKey);
-        for (RequestKind kind : WRAPPING_MAP_VALUE_FRAMEWORK_TYPES) {
-          if (mapType.valuesAreTypeOf(frameworkClass(kind))) {
-            return kind;
-          }
-        }
-        // fall through
-      case SET:
-      case SET_VALUES:
-        return INSTANCE;
-      case UNIQUE:
-        throw new IllegalArgumentException(
-            "multibindingContribution must be a multibinding: " + multibindingContribution);
-    }
-    throw new AssertionError(multibindingContribution.toString());
-  }
-
-  DependencyRequest forRequiredResolvedVariable(
-      VariableElement variableElement, TypeMirror resolvedType) {
-    checkNotNull(variableElement);
-    checkNotNull(resolvedType);
-    // Ban @Assisted parameters, they are not considered dependency requests.
-    checkArgument(!AssistedInjectionAnnotations.isAssistedParameter(variableElement));
-    Optional<AnnotationMirror> qualifier = injectionAnnotations.getQualifier(variableElement);
-    return newDependencyRequest(variableElement, resolvedType, qualifier);
-  }
-
-  public DependencyRequest forComponentProvisionMethod(
-      ExecutableElement provisionMethod, ExecutableType provisionMethodType) {
-    checkNotNull(provisionMethod);
-    checkNotNull(provisionMethodType);
-    checkArgument(
-        provisionMethod.getParameters().isEmpty(),
-        "Component provision methods must be empty: %s",
-        provisionMethod);
-    Optional<AnnotationMirror> qualifier = injectionAnnotations.getQualifier(provisionMethod);
-    return newDependencyRequest(provisionMethod, provisionMethodType.getReturnType(), qualifier);
-  }
-
-  public DependencyRequest forComponentProductionMethod(
-      ExecutableElement productionMethod, ExecutableType productionMethodType) {
-    checkNotNull(productionMethod);
-    checkNotNull(productionMethodType);
-    checkArgument(
-        productionMethod.getParameters().isEmpty(),
-        "Component production methods must be empty: %s",
-        productionMethod);
-    TypeMirror type = productionMethodType.getReturnType();
-    Optional<AnnotationMirror> qualifier = injectionAnnotations.getQualifier(productionMethod);
-    // Only a component production method can be a request for a ListenableFuture, so we
-    // special-case it here.
-    if (isTypeOf(ListenableFuture.class, type)) {
-      return DependencyRequest.builder()
-          .kind(FUTURE)
-          .key(keyFactory.forQualifiedType(qualifier, unwrapType(type)))
-          .requestElement(productionMethod)
-          .build();
-    } else {
-      return newDependencyRequest(productionMethod, type, qualifier);
-    }
-  }
-
-  DependencyRequest forComponentMembersInjectionMethod(
-      ExecutableElement membersInjectionMethod, ExecutableType membersInjectionMethodType) {
-    checkNotNull(membersInjectionMethod);
-    checkNotNull(membersInjectionMethodType);
-    Optional<AnnotationMirror> qualifier =
-        injectionAnnotations.getQualifier(membersInjectionMethod);
-    checkArgument(!qualifier.isPresent());
-    TypeMirror membersInjectedType = getOnlyElement(membersInjectionMethodType.getParameterTypes());
-    return DependencyRequest.builder()
-        .kind(MEMBERS_INJECTION)
-        .key(keyFactory.forMembersInjectedType(membersInjectedType))
-        .requestElement(membersInjectionMethod)
-        .build();
-  }
-
-  DependencyRequest forProductionImplementationExecutor() {
-    return DependencyRequest.builder()
-        .kind(PROVIDER)
-        .key(keyFactory.forProductionImplementationExecutor())
-        .build();
-  }
-
-  DependencyRequest forProductionComponentMonitor() {
-    return DependencyRequest.builder()
-        .kind(PROVIDER)
-        .key(keyFactory.forProductionComponentMonitor())
-        .build();
-  }
-
-  /**
-   * Returns a synthetic request for the present value of an optional binding generated from a
-   * {@link dagger.BindsOptionalOf} declaration.
-   */
-  DependencyRequest forSyntheticPresentOptionalBinding(Key requestKey, RequestKind kind) {
-    Optional<Key> key = keyFactory.unwrapOptional(requestKey);
-    checkArgument(key.isPresent(), "not a request for optional: %s", requestKey);
-    return DependencyRequest.builder()
-        .kind(kind)
-        .key(key.get())
-        .isNullable(
-            allowsNull(getRequestKind(OptionalType.from(requestKey).valueType()), Optional.empty()))
-        .build();
-  }
-
-  private DependencyRequest newDependencyRequest(
-      Element requestElement, TypeMirror type, Optional<AnnotationMirror> qualifier) {
-    RequestKind requestKind = getRequestKind(type);
-    return DependencyRequest.builder()
-        .kind(requestKind)
-        .key(keyFactory.forQualifiedType(qualifier, extractKeyType(type)))
-        .requestElement(requestElement)
-        .isNullable(allowsNull(requestKind, getNullableType(requestElement)))
-        .build();
-  }
-
-  /**
-   * Returns {@code true} if a given request element allows null values. {@link
-   * RequestKind#INSTANCE} requests must be annotated with {@code @Nullable} in order to allow null
-   * values. All other request kinds implicitly allow null values because they are are wrapped
-   * inside {@link Provider}, {@link Lazy}, etc.
-   */
-  private boolean allowsNull(RequestKind kind, Optional<DeclaredType> nullableType) {
-    return nullableType.isPresent() || !kind.equals(INSTANCE);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/DependencyRequestFormatter.java b/java/dagger/internal/codegen/binding/DependencyRequestFormatter.java
deleted file mode 100644
index 888dec2..0000000
--- a/java/dagger/internal/codegen/binding/DependencyRequestFormatter.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static dagger.internal.codegen.base.ElementFormatter.elementToString;
-import static dagger.internal.codegen.base.RequestKinds.requestType;
-
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import dagger.Provides;
-import dagger.internal.codegen.base.Formatter;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import dagger.producers.Produces;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementVisitor;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementKindVisitor8;
-
-/**
- * Formats a {@link DependencyRequest} into a {@link String} suitable for an error message listing a
- * chain of dependencies.
- *
- * <dl>
- *   <dt>For component provision methods
- *   <dd>{@code @Qualifier SomeType is provided at\n ComponentType.method()}
- *   <dt>For component injection methods
- *   <dd>{@code SomeType is injected at\n ComponentType.method(foo)}
- *   <dt>For parameters to {@link Provides @Provides}, {@link Produces @Produces}, or {@link
- *       Inject @Inject} methods:
- *   <dd>{@code @Qualified ResolvedType is injected at\n EnclosingType.method([…, ]param[, …])}
- *   <dt>For parameters to {@link Inject @Inject} constructors:
- *   <dd>{@code @Qualified ResolvedType is injected at\n EnclosingType([…, ]param[, …])}
- *   <dt>For {@link Inject @Inject} fields:
- *   <dd>{@code @Qualified ResolvedType is injected at\n EnclosingType.field}
- * </dl>
- */
-public final class DependencyRequestFormatter extends Formatter<DependencyRequest> {
-
-  private final DaggerTypes types;
-
-  @Inject
-  DependencyRequestFormatter(DaggerTypes types) {
-    this.types = types;
-  }
-
-  @Override
-  public String format(DependencyRequest request) {
-    return request
-        .requestElement()
-        .map(element -> element.accept(formatVisitor, request))
-        .orElse("");
-  }
-
-  /**
-   * Appends a newline and the formatted dependency request unless {@link
-   * #format(DependencyRequest)} returns the empty string.
-   */
-  @CanIgnoreReturnValue
-  public StringBuilder appendFormatLine(
-      StringBuilder builder, DependencyRequest dependencyRequest) {
-    String formatted = format(dependencyRequest);
-    if (!formatted.isEmpty()) {
-      builder.append('\n').append(formatted);
-    }
-    return builder;
-  }
-
-  private final ElementVisitor<String, DependencyRequest> formatVisitor =
-      new ElementKindVisitor8<String, DependencyRequest>() {
-
-        @Override
-        public String visitExecutableAsMethod(ExecutableElement method, DependencyRequest request) {
-          return INDENT
-              + request.key()
-              + " is "
-              + componentMethodRequestVerb(request)
-              + " at\n"
-              + DOUBLE_INDENT
-              + elementToString(method);
-        }
-
-        @Override
-        public String visitVariable(VariableElement variable, DependencyRequest request) {
-          TypeMirror requestedType = requestType(request.kind(), request.key().type(), types);
-          return INDENT
-              + formatQualifier(request.key().qualifier())
-              + requestedType
-              + " is injected at\n"
-              + DOUBLE_INDENT
-              + elementToString(variable);
-        }
-
-        @Override
-        public String visitType(TypeElement e, DependencyRequest request) {
-          return ""; // types by themselves provide no useful information.
-        }
-
-        @Override
-        protected String defaultAction(Element element, DependencyRequest request) {
-          throw new IllegalStateException(
-              "Invalid request " + element.getKind() + " element " + element);
-        }
-      };
-
-  private String formatQualifier(Optional<AnnotationMirror> maybeQualifier) {
-    return maybeQualifier.map(qualifier -> qualifier + " ").orElse("");
-  }
-
-  /**
-   * Returns the verb for a component method dependency request. Returns "produced", "provided", or
-   * "injected", depending on the kind of request.
-   */
-  private String componentMethodRequestVerb(DependencyRequest request) {
-    switch (request.kind()) {
-      case FUTURE:
-      case PRODUCER:
-      case INSTANCE:
-      case LAZY:
-      case PROVIDER:
-      case PROVIDER_OF_LAZY:
-        return "requested";
-
-      case MEMBERS_INJECTION:
-        return "injected";
-
-      case PRODUCED:
-        break;
-    }
-    throw new AssertionError("illegal request kind for method: " + request);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/DependencyVariableNamer.java b/java/dagger/internal/codegen/binding/DependencyVariableNamer.java
deleted file mode 100644
index e01d22e..0000000
--- a/java/dagger/internal/codegen/binding/DependencyVariableNamer.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static dagger.internal.codegen.binding.SourceFiles.simpleVariableName;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.base.Ascii;
-import com.google.common.base.CaseFormat;
-import dagger.Lazy;
-import dagger.model.DependencyRequest;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.inject.Provider;
-
-/**
- * Picks a reasonable name for what we think is being provided from the variable name associated
- * with the {@link DependencyRequest}.  I.e. strips out words like "lazy" and "provider" if we
- * believe that those refer to {@link Lazy} and {@link Provider} rather than the type being
- * provided.
- */
-//TODO(gak): develop the heuristics to get better names
-final class DependencyVariableNamer {
-  private static final Pattern LAZY_PROVIDER_PATTERN = Pattern.compile("lazy(\\w+)Provider");
-
-  static String name(DependencyRequest dependency) {
-    if (!dependency.requestElement().isPresent()) {
-      return simpleVariableName(MoreTypes.asTypeElement(dependency.key().type()));
-    }
-
-    String variableName = dependency.requestElement().get().getSimpleName().toString();
-    if (Ascii.isUpperCase(variableName.charAt(0))) {
-      variableName = toLowerCamel(variableName);
-    }
-    switch (dependency.kind()) {
-      case INSTANCE:
-        return variableName;
-      case LAZY:
-        return variableName.startsWith("lazy") && !variableName.equals("lazy")
-            ? toLowerCamel(variableName.substring(4))
-            : variableName;
-      case PROVIDER_OF_LAZY:
-        Matcher matcher = LAZY_PROVIDER_PATTERN.matcher(variableName);
-        if (matcher.matches()) {
-          return toLowerCamel(matcher.group(1));
-        }
-        // fall through
-      case PROVIDER:
-        return variableName.endsWith("Provider") && !variableName.equals("Provider")
-            ? variableName.substring(0, variableName.length() - 8)
-            : variableName;
-      case PRODUCED:
-        return variableName.startsWith("produced") && !variableName.equals("produced")
-            ? toLowerCamel(variableName.substring(8))
-            : variableName;
-      case PRODUCER:
-        return variableName.endsWith("Producer") && !variableName.equals("Producer")
-            ? variableName.substring(0, variableName.length() - 8)
-            : variableName;
-      default:
-        throw new AssertionError();
-    }
-  }
-
-  private static String toLowerCamel(String name) {
-    return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, name);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ErrorMessages.java b/java/dagger/internal/codegen/binding/ErrorMessages.java
deleted file mode 100644
index 8962ade..0000000
--- a/java/dagger/internal/codegen/binding/ErrorMessages.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableMap;
-import dagger.internal.codegen.base.ComponentAnnotation;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.function.UnaryOperator;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-/** The collection of error messages to be reported back to users. */
-public final class ErrorMessages {
-
-  private static final UnaryOperator<String> PRODUCTION =
-      s ->
-          s.replace("component", "production component")
-              .replace("Component", "ProductionComponent");
-
-  private static final UnaryOperator<String> SUBCOMPONENT =
-      s -> s.replace("component", "subcomponent").replace("Component", "Subcomponent");
-
-  private static final UnaryOperator<String> FACTORY = s -> s.replace("Builder", "Factory");
-
-  private static final ImmutableMap<ComponentKind, Function<String, String>>
-      COMPONENT_TRANSFORMATIONS =
-          ImmutableMap.of(
-              ComponentKind.COMPONENT, UnaryOperator.identity(),
-              ComponentKind.SUBCOMPONENT, SUBCOMPONENT,
-              ComponentKind.PRODUCTION_COMPONENT, PRODUCTION,
-              ComponentKind.PRODUCTION_SUBCOMPONENT, PRODUCTION.andThen(SUBCOMPONENT));
-
-  public static ComponentMessages componentMessagesFor(ComponentKind componentKind) {
-    return new ComponentMessages(COMPONENT_TRANSFORMATIONS.get(componentKind));
-  }
-
-  public static ComponentMessages componentMessagesFor(ComponentAnnotation componentAnnotation) {
-    return new ComponentMessages(
-        transformation(componentAnnotation.isProduction(), componentAnnotation.isSubcomponent()));
-  }
-
-  public static ComponentCreatorMessages creatorMessagesFor(
-      ComponentCreatorAnnotation creatorAnnotation) {
-    Function<String, String> transformation =
-        transformation(
-            creatorAnnotation.isProductionCreatorAnnotation(),
-            creatorAnnotation.isSubcomponentCreatorAnnotation());
-    switch (creatorAnnotation.creatorKind()) {
-      case BUILDER:
-        return new BuilderMessages(transformation);
-      case FACTORY:
-        return new FactoryMessages(transformation);
-    }
-    throw new AssertionError(creatorAnnotation);
-  }
-
-  private static Function<String, String> transformation(
-      boolean isProduction, boolean isSubcomponent) {
-    Function<String, String> transformation = isProduction ? PRODUCTION : UnaryOperator.identity();
-    return isSubcomponent ? transformation.andThen(SUBCOMPONENT) : transformation;
-  }
-
-  private abstract static class Messages {
-    private final Function<String, String> transformation;
-
-    Messages(Function<String, String> transformation) {
-      this.transformation = transformation;
-    }
-
-    protected final String process(String s) {
-      return transformation.apply(s);
-    }
-  }
-
-  /** Errors for components. */
-  public static final class ComponentMessages extends Messages {
-    ComponentMessages(Function<String, String> transformation) {
-      super(transformation);
-    }
-
-    public final String moreThanOne() {
-      return process("@Component has more than one @Component.Builder or @Component.Factory: %s");
-    }
-  }
-
-  /** Errors for component creators. */
-  public abstract static class ComponentCreatorMessages extends Messages {
-    ComponentCreatorMessages(Function<String, String> transformation) {
-      super(transformation);
-    }
-
-    public static String builderMethodRequiresNoArgs() {
-      return "Methods returning a @Component.Builder must have no arguments";
-    }
-
-    public static String moreThanOneRefToSubcomponent() {
-      return "Only one method can create a given subcomponent. %s is created by: %s";
-    }
-
-    public final String invalidConstructor() {
-      return process("@Component.Builder classes must have exactly one constructor,"
-          + " and it must not be private or have any parameters");
-    }
-
-    public final String generics() {
-      return process("@Component.Builder types must not have any generic types");
-    }
-
-    public final String mustBeInComponent() {
-      return process("@Component.Builder types must be nested within a @Component");
-    }
-
-    public final String mustBeClassOrInterface() {
-      return process("@Component.Builder types must be abstract classes or interfaces");
-    }
-
-    public final String isPrivate() {
-      return process("@Component.Builder types must not be private");
-    }
-
-    public final String mustBeStatic() {
-      return process("@Component.Builder types must be static");
-    }
-
-    public final String mustBeAbstract() {
-      return process("@Component.Builder types must be abstract");
-    }
-
-    public abstract String missingFactoryMethod();
-
-    public abstract String multipleSettersForModuleOrDependencyType();
-
-    public abstract String extraSetters();
-
-    public abstract String missingSetters();
-
-    public abstract String twoFactoryMethods();
-
-    public abstract String inheritedTwoFactoryMethods();
-
-    public abstract String factoryMethodMustReturnComponentType();
-
-    public final String inheritedFactoryMethodMustReturnComponentType() {
-      return factoryMethodMustReturnComponentType() + ". Inherited method: %s";
-    }
-
-    public abstract String factoryMethodMayNotBeAnnotatedWithBindsInstance();
-
-    public final String inheritedFactoryMethodMayNotBeAnnotatedWithBindsInstance() {
-      return factoryMethodMayNotBeAnnotatedWithBindsInstance() + ". Inherited method: %s";
-    }
-
-    public final String setterMethodsMustTakeOneArg() {
-      return process("@Component.Builder methods must not have more than one argument");
-    }
-
-    public final String inheritedSetterMethodsMustTakeOneArg() {
-      return setterMethodsMustTakeOneArg() + ". Inherited method: %s";
-    }
-
-    public final String setterMethodsMustReturnVoidOrBuilder() {
-      return process("@Component.Builder setter methods must return void, the builder,"
-          + " or a supertype of the builder");
-    }
-
-    public final String inheritedSetterMethodsMustReturnVoidOrBuilder() {
-      return setterMethodsMustReturnVoidOrBuilder() + ". Inherited method: %s";
-    }
-
-    public final String methodsMayNotHaveTypeParameters() {
-      return process("@Component.Builder methods must not have type parameters");
-    }
-
-    public final String inheritedMethodsMayNotHaveTypeParameters() {
-      return methodsMayNotHaveTypeParameters() + ". Inherited method: %s";
-    }
-
-    public abstract String nonBindsInstanceParametersMayNotBePrimitives();
-
-    public final String inheritedNonBindsInstanceParametersMayNotBePrimitives() {
-      return nonBindsInstanceParametersMayNotBePrimitives() + ". Inherited method: %s";
-    }
-
-    public final String factoryMethodReturnsSupertypeWithMissingMethods(
-        TypeElement component,
-        TypeElement componentBuilder,
-        TypeMirror returnType,
-        ExecutableElement buildMethod,
-        Set<ExecutableElement> additionalMethods) {
-      return String.format(
-          "%1$s.%2$s() returns %3$s, but %4$s declares additional component method(s): %5$s. In "
-              + "order to provide type-safe access to these methods, override %2$s() to return "
-              + "%4$s",
-          componentBuilder.getQualifiedName(),
-          buildMethod.getSimpleName(),
-          returnType,
-          component.getQualifiedName(),
-          Joiner.on(", ").join(additionalMethods));
-    }
-
-    public final String bindsInstanceNotAllowedOnBothSetterMethodAndParameter() {
-      return process("@Component.Builder setter methods may not have @BindsInstance on both the "
-          + "method and its parameter; choose one or the other");
-    }
-
-    public final String inheritedBindsInstanceNotAllowedOnBothSetterMethodAndParameter() {
-      return bindsInstanceNotAllowedOnBothSetterMethodAndParameter() + ". Inherited method: %s";
-    }
-  }
-
-  private static final class BuilderMessages extends ComponentCreatorMessages {
-    BuilderMessages(Function<String, String> transformation) {
-      super(transformation);
-    }
-
-    @Override
-    public String missingFactoryMethod() {
-      return process(
-          "@Component.Builder types must have exactly one no-args method that "
-              + " returns the @Component type");
-    }
-
-    @Override
-    public String multipleSettersForModuleOrDependencyType() {
-      return process(
-          "@Component.Builder types must not have more than one setter method per module or "
-              + "dependency, but %s is set by %s");
-    }
-
-    @Override
-    public String extraSetters() {
-      return process(
-          "@Component.Builder has setters for modules or components that aren't required: %s");
-    }
-
-    @Override
-    public String missingSetters() {
-      return process(
-          "@Component.Builder is missing setters for required modules or components: %s");
-    }
-
-    @Override
-    public String twoFactoryMethods() {
-      return process(
-          "@Component.Builder types must have exactly one zero-arg method, and that"
-              + " method must return the @Component type. Already found: %s");
-    }
-
-    @Override
-    public String inheritedTwoFactoryMethods() {
-      return process(
-          "@Component.Builder types must have exactly one zero-arg method, and that"
-              + " method must return the @Component type. Found %s and %s");
-    }
-
-    @Override
-    public String factoryMethodMustReturnComponentType() {
-      return process(
-          "@Component.Builder methods that have no arguments must return the @Component type or a "
-              + "supertype of the @Component");
-    }
-
-    @Override
-    public String factoryMethodMayNotBeAnnotatedWithBindsInstance() {
-      return process(
-          "@Component.Builder no-arg build methods may not be annotated with @BindsInstance");
-    }
-
-    @Override
-    public String nonBindsInstanceParametersMayNotBePrimitives() {
-      return process(
-          "@Component.Builder methods that are not annotated with @BindsInstance "
-              + "must take either a module or a component dependency, not a primitive");
-    }
-  }
-
-  private static final class FactoryMessages extends ComponentCreatorMessages {
-    FactoryMessages(Function<String, String> transformation) {
-      super(transformation.andThen(FACTORY));
-    }
-
-    @Override
-    public String missingFactoryMethod() {
-      return process(
-          "@Component.Factory types must have exactly one method that "
-              + "returns the @Component type");
-    }
-
-    @Override
-    public String multipleSettersForModuleOrDependencyType() {
-      return process(
-          "@Component.Factory methods must not have more than one parameter per module or "
-              + "dependency, but %s is set by %s");
-    }
-
-    @Override
-    public String extraSetters() {
-      return process(
-          "@Component.Factory method has parameters for modules or components that aren't "
-              + "required: %s");
-    }
-
-    @Override
-    public String missingSetters() {
-      return process(
-          "@Component.Factory method is missing parameters for required modules or components: %s");
-    }
-
-    @Override
-    public String twoFactoryMethods() {
-      return process(
-          "@Component.Factory types must have exactly one abstract method. Already found: %s");
-    }
-
-    @Override
-    public String inheritedTwoFactoryMethods() {
-      return twoFactoryMethods();
-    }
-
-    @Override
-    public String factoryMethodMustReturnComponentType() {
-      return process(
-          "@Component.Factory abstract methods must return the @Component type or a "
-              + "supertype of the @Component");
-    }
-
-    @Override
-    public String factoryMethodMayNotBeAnnotatedWithBindsInstance() {
-      return process("@Component.Factory method may not be annotated with @BindsInstance");
-    }
-
-    @Override
-    public String nonBindsInstanceParametersMayNotBePrimitives() {
-      return process(
-          "@Component.Factory method parameters that are not annotated with @BindsInstance "
-              + "must be either a module or a component dependency, not a primitive");
-    }
-  }
-
-  private ErrorMessages() {}
-}
diff --git a/java/dagger/internal/codegen/binding/FrameworkField.java b/java/dagger/internal/codegen/binding/FrameworkField.java
deleted file mode 100644
index 3b0b73f..0000000
--- a/java/dagger/internal/codegen/binding/FrameworkField.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static dagger.model.BindingKind.MEMBERS_INJECTOR;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.base.CaseFormat;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import java.util.Optional;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementVisitor;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementKindVisitor8;
-
-/**
- * A value object that represents a field in the generated Component class.
- *
- * <p>Examples:
- *
- * <ul>
- *   <li>{@code Provider<String>}
- *   <li>{@code Producer<Widget>}
- *   <li>{@code Provider<Map<SomeMapKey, MapValue>>}.
- * </ul>
- */
-@AutoValue
-public abstract class FrameworkField {
-
-  /**
-   * Creates a framework field.
-   *
-   * @param frameworkClassName the name of the framework class (e.g., {@link javax.inject.Provider})
-   * @param valueTypeName the name of the type parameter of the framework class (e.g., {@code Foo}
-   *     for {@code Provider<Foo>}
-   * @param fieldName the name of the field
-   */
-  public static FrameworkField create(
-      ClassName frameworkClassName, TypeName valueTypeName, String fieldName) {
-    String suffix = frameworkClassName.simpleName();
-    return new AutoValue_FrameworkField(
-        ParameterizedTypeName.get(frameworkClassName, valueTypeName),
-        fieldName.endsWith(suffix) ? fieldName : fieldName + suffix);
-  }
-
-  /**
-   * A framework field for a {@link ContributionBinding}.
-   *
-   * @param frameworkClass if present, the field will use this framework class instead of the normal
-   *     one for the binding's type.
-   */
-  public static FrameworkField forBinding(
-      ContributionBinding binding, Optional<ClassName> frameworkClass) {
-    return create(
-        frameworkClass.orElse(
-            ClassName.get(
-                FrameworkType.forBindingType(binding.bindingType()).frameworkClass())),
-        TypeName.get(fieldValueType(binding)),
-        frameworkFieldName(binding));
-  }
-
-  private static TypeMirror fieldValueType(ContributionBinding binding) {
-    return binding.contributionType().isMultibinding()
-        ? binding.contributedType()
-        : binding.key().type();
-  }
-
-  private static String frameworkFieldName(ContributionBinding binding) {
-    if (binding.bindingElement().isPresent()) {
-      String name = BINDING_ELEMENT_NAME.visit(binding.bindingElement().get(), binding);
-      return binding.kind().equals(MEMBERS_INJECTOR) ? name + "MembersInjector" : name;
-    }
-    return KeyVariableNamer.name(binding.key());
-  }
-
-  private static final ElementVisitor<String, Binding> BINDING_ELEMENT_NAME =
-      new ElementKindVisitor8<String, Binding>() {
-
-        @Override
-        protected String defaultAction(Element e, Binding p) {
-          throw new IllegalArgumentException("Unexpected binding " + p);
-        }
-
-        @Override
-        public String visitExecutableAsConstructor(ExecutableElement e, Binding p) {
-          return visit(e.getEnclosingElement(), p);
-        }
-
-        @Override
-        public String visitExecutableAsMethod(ExecutableElement e, Binding p) {
-          return e.getSimpleName().toString();
-        }
-
-        @Override
-        public String visitType(TypeElement e, Binding p) {
-          return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, e.getSimpleName().toString());
-        }
-
-        @Override
-        public String visitVariableAsParameter(VariableElement e, Binding p) {
-          return e.getSimpleName().toString();
-        }
-      };
-
-  public abstract ParameterizedTypeName type();
-
-  public abstract String name();
-}
diff --git a/java/dagger/internal/codegen/binding/FrameworkType.java b/java/dagger/internal/codegen/binding/FrameworkType.java
deleted file mode 100644
index 6b160b6..0000000
--- a/java/dagger/internal/codegen/binding/FrameworkType.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2016 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.binding;
-
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
-import static dagger.model.RequestKind.INSTANCE;
-
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import dagger.Lazy;
-import dagger.internal.DoubleCheck;
-import dagger.internal.ProviderOfLazy;
-import dagger.internal.codegen.base.RequestKinds;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import dagger.model.RequestKind;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import dagger.producers.internal.Producers;
-import java.util.Optional;
-import javax.inject.Provider;
-import javax.lang.model.type.TypeMirror;
-
-/** One of the core types initialized as fields in a generated component. */
-public enum FrameworkType {
-  /** A {@link Provider}. */
-  PROVIDER {
-    @Override
-    public Class<?> frameworkClass() {
-      return Provider.class;
-    }
-
-    @Override
-    public Optional<RequestKind> requestKind() {
-      return Optional.of(RequestKind.PROVIDER);
-    }
-
-    @Override
-    public CodeBlock to(RequestKind requestKind, CodeBlock from) {
-      switch (requestKind) {
-        case INSTANCE:
-          return CodeBlock.of("$L.get()", from);
-
-        case LAZY:
-          return CodeBlock.of("$T.lazy($L)", DoubleCheck.class, from);
-
-        case PROVIDER:
-          return from;
-
-        case PROVIDER_OF_LAZY:
-          return CodeBlock.of("$T.create($L)", ProviderOfLazy.class, from);
-
-        case PRODUCER:
-          return CodeBlock.of("$T.producerFromProvider($L)", Producers.class, from);
-
-        case FUTURE:
-          return CodeBlock.of("$T.immediateFuture($L)", Futures.class, to(INSTANCE, from));
-
-        case PRODUCED:
-          return CodeBlock.of("$T.successful($L)", Produced.class, to(INSTANCE, from));
-
-        default:
-          throw new IllegalArgumentException(
-              String.format("Cannot request a %s from a %s", requestKind, this));
-      }
-    }
-
-    @Override
-    public Expression to(RequestKind requestKind, Expression from, DaggerTypes types) {
-      CodeBlock codeBlock = to(requestKind, from.codeBlock());
-      switch (requestKind) {
-        case INSTANCE:
-          return Expression.create(types.unwrapTypeOrObject(from.type()), codeBlock);
-
-        case PROVIDER:
-          return from;
-
-        case PROVIDER_OF_LAZY:
-          TypeMirror lazyType = types.rewrapType(from.type(), Lazy.class);
-          return Expression.create(types.wrapType(lazyType, Provider.class), codeBlock);
-
-        case FUTURE:
-          return Expression.create(
-              types.rewrapType(from.type(), ListenableFuture.class), codeBlock);
-
-        default:
-          return Expression.create(
-              types.rewrapType(from.type(), RequestKinds.frameworkClass(requestKind)), codeBlock);
-      }
-    }
-  },
-
-  /** A {@link Producer}. */
-  PRODUCER_NODE {
-    @Override
-    public Class<?> frameworkClass() {
-      // TODO(cgdecker): Replace this with new class for representing internal producer nodes.
-      // Currently the new class is CancellableProducer, but it may be changed to ProducerNode and
-      // made to not implement Producer.
-      return Producer.class;
-    }
-
-    @Override
-    public Optional<RequestKind> requestKind() {
-      return Optional.empty();
-    }
-
-    @Override
-    public CodeBlock to(RequestKind requestKind, CodeBlock from) {
-      switch (requestKind) {
-        case FUTURE:
-          return CodeBlock.of("$L.get()", from);
-
-        case PRODUCER:
-          return from;
-
-        default:
-          throw new IllegalArgumentException(
-              String.format("Cannot request a %s from a %s", requestKind, this));
-      }
-    }
-
-    @Override
-    public Expression to(RequestKind requestKind, Expression from, DaggerTypes types) {
-      switch (requestKind) {
-        case FUTURE:
-          return Expression.create(
-              types.rewrapType(from.type(), ListenableFuture.class),
-              to(requestKind, from.codeBlock()));
-
-        case PRODUCER:
-          return Expression.create(from.type(), to(requestKind, from.codeBlock()));
-
-        default:
-          throw new IllegalArgumentException(
-              String.format("Cannot request a %s from a %s", requestKind, this));
-      }
-    }
-  },
-  ;
-
-  /** Returns the framework type appropriate for fields for a given binding type. */
-  public static FrameworkType forBindingType(BindingType bindingType) {
-    switch (bindingType) {
-      case PROVISION:
-        return PROVIDER;
-      case PRODUCTION:
-        return PRODUCER_NODE;
-      case MEMBERS_INJECTION:
-    }
-    throw new AssertionError(bindingType);
-  }
-
-  /** Returns the framework type that exactly matches the given request kind, if one exists. */
-  public static Optional<FrameworkType> forRequestKind(RequestKind requestKind) {
-    switch (requestKind) {
-      case PROVIDER:
-        return Optional.of(FrameworkType.PROVIDER);
-      default:
-        return Optional.empty();
-    }
-  }
-
-  /** The class of fields of this type. */
-  public abstract Class<?> frameworkClass();
-
-  /** Returns the {@link #frameworkClass()} parameterized with a type. */
-  public ParameterizedTypeName frameworkClassOf(TypeName valueType) {
-    return ParameterizedTypeName.get(ClassName.get(frameworkClass()), valueType);
-  }
-
-  /** The request kind that an instance of this framework type can satisfy directly, if any. */
-  public abstract Optional<RequestKind> requestKind();
-
-  /**
-   * Returns a {@link CodeBlock} that evaluates to a requested object given an expression that
-   * evaluates to an instance of this framework type.
-   *
-   * @param requestKind the kind of {@link DependencyRequest} that the returned expression can
-   *     satisfy
-   * @param from a {@link CodeBlock} that evaluates to an instance of this framework type
-   * @throws IllegalArgumentException if a valid expression cannot be generated for {@code
-   *     requestKind}
-   */
-  public abstract CodeBlock to(RequestKind requestKind, CodeBlock from);
-
-  /**
-   * Returns an {@link Expression} that evaluates to a requested object given an expression that
-   * evaluates to an instance of this framework type.
-   *
-   * @param requestKind the kind of {@link DependencyRequest} that the returned expression can
-   *     satisfy
-   * @param from an expression that evaluates to an instance of this framework type
-   * @throws IllegalArgumentException if a valid expression cannot be generated for {@code
-   *     requestKind}
-   */
-  public abstract Expression to(RequestKind requestKind, Expression from, DaggerTypes types);
-
-  @Override
-  public String toString() {
-    return UPPER_UNDERSCORE.to(UPPER_CAMEL, super.toString());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/FrameworkTypeMapper.java b/java/dagger/internal/codegen/binding/FrameworkTypeMapper.java
deleted file mode 100644
index 85463af..0000000
--- a/java/dagger/internal/codegen/binding/FrameworkTypeMapper.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static dagger.internal.codegen.binding.BindingType.PRODUCTION;
-
-import dagger.model.RequestKind;
-import dagger.producers.Producer;
-import javax.inject.Provider;
-
-/**
- * A mapper for associating a {@link RequestKind} to a {@link FrameworkType}, dependent on the type
- * of code to be generated (e.g., for {@link Provider} or {@link Producer}).
- */
-public enum FrameworkTypeMapper {
-  FOR_PROVIDER() {
-    @Override
-    public FrameworkType getFrameworkType(RequestKind requestKind) {
-      switch (requestKind) {
-        case INSTANCE:
-        case PROVIDER:
-        case PROVIDER_OF_LAZY:
-        case LAZY:
-          return FrameworkType.PROVIDER;
-        case PRODUCED:
-        case PRODUCER:
-          throw new IllegalArgumentException(requestKind.toString());
-        default:
-          throw new AssertionError(requestKind);
-      }
-    }
-  },
-  FOR_PRODUCER() {
-    @Override
-    public FrameworkType getFrameworkType(RequestKind requestKind) {
-      switch (requestKind) {
-        case INSTANCE:
-        case PRODUCED:
-        case PRODUCER:
-          return FrameworkType.PRODUCER_NODE;
-        case PROVIDER:
-        case PROVIDER_OF_LAZY:
-        case LAZY:
-          return FrameworkType.PROVIDER;
-        default:
-          throw new AssertionError(requestKind);
-      }
-    }
-  };
-
-  public static FrameworkTypeMapper forBindingType(BindingType bindingType) {
-    return bindingType.equals(PRODUCTION) ? FOR_PRODUCER : FOR_PROVIDER;
-  }
-
-  public abstract FrameworkType getFrameworkType(RequestKind requestKind);
-}
diff --git a/java/dagger/internal/codegen/binding/InjectBindingRegistry.java b/java/dagger/internal/codegen/binding/InjectBindingRegistry.java
deleted file mode 100644
index 5203130..0000000
--- a/java/dagger/internal/codegen/binding/InjectBindingRegistry.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2017 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.binding;
-
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import dagger.Component;
-import dagger.Provides;
-import dagger.internal.codegen.base.SourceFileGenerationException;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.model.Key;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-
-/**
- * Maintains the collection of provision bindings from {@link Inject} constructors and members
- * injection bindings from {@link Inject} fields and methods known to the annotation processor. Note
- * that this registry <b>does not</b> handle any explicit bindings (those from {@link Provides}
- * methods, {@link Component} dependencies, etc.).
- */
-public interface InjectBindingRegistry {
-  /**
-   * Returns a {@link ProvisionBinding} for {@code key}. If none has been registered yet, registers
-   * one.
-   */
-  Optional<ProvisionBinding> getOrFindProvisionBinding(Key key);
-
-  /**
-   * Returns a {@link MembersInjectionBinding} for {@code key}. If none has been registered yet,
-   * registers one, along with all necessary members injection bindings for superclasses.
-   */
-  Optional<MembersInjectionBinding> getOrFindMembersInjectionBinding(Key key);
-
-  /**
-   * Returns a {@link ProvisionBinding} for a {@link dagger.MembersInjector} of {@code key}. If none
-   * has been registered yet, registers one.
-   */
-  Optional<ProvisionBinding> getOrFindMembersInjectorProvisionBinding(Key key);
-
-  @CanIgnoreReturnValue
-  Optional<ProvisionBinding> tryRegisterConstructor(ExecutableElement constructorElement);
-
-  @CanIgnoreReturnValue
-  Optional<MembersInjectionBinding> tryRegisterMembersInjectedType(TypeElement typeElement);
-
-  /**
-   * This method ensures that sources for all registered {@link Binding bindings} (either explicitly
-   * or implicitly via {@link #getOrFindMembersInjectionBinding} or {@link
-   * #getOrFindProvisionBinding}) are generated.
-   */
-  void generateSourcesForRequiredBindings(
-      SourceFileGenerator<ProvisionBinding> factoryGenerator,
-      SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator)
-      throws SourceFileGenerationException;
-}
diff --git a/java/dagger/internal/codegen/binding/InjectionAnnotations.java b/java/dagger/internal/codegen/binding/InjectionAnnotations.java
deleted file mode 100644
index 748755e..0000000
--- a/java/dagger/internal/codegen/binding/InjectionAnnotations.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreElements.asVariable;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.base.MoreAnnotationValues.getStringValue;
-import static dagger.internal.codegen.binding.SourceFiles.memberInjectedFieldSignatureForVariable;
-import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.util.ElementFilter.constructorsIn;
-
-import com.google.auto.common.AnnotationMirrors;
-import com.google.auto.common.SuperficialValidation;
-import com.google.common.base.Equivalence;
-import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.InjectedFieldSignature;
-import dagger.internal.codegen.extension.DaggerCollectors;
-import dagger.internal.codegen.extension.DaggerStreams;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.Optional;
-import java.util.stream.Stream;
-import javax.inject.Inject;
-import javax.inject.Qualifier;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.util.ElementFilter;
-
-/** Utilities relating to annotations defined in the {@code javax.inject} package. */
-public final class InjectionAnnotations {
-
-  private static final Equivalence<AnnotationMirror> EQUIVALENCE = AnnotationMirrors.equivalence();
-
-  private final DaggerElements elements;
-  private final KotlinMetadataUtil kotlinMetadataUtil;
-
-  @Inject
-  InjectionAnnotations(DaggerElements elements, KotlinMetadataUtil kotlinMetadataUtil) {
-    this.elements = elements;
-    this.kotlinMetadataUtil = kotlinMetadataUtil;
-  }
-
-  public Optional<AnnotationMirror> getQualifier(Element e) {
-    if (!SuperficialValidation.validateElement(e)) {
-      throw new TypeNotPresentException(e.toString(), null);
-    }
-    checkNotNull(e);
-    ImmutableCollection<? extends AnnotationMirror> qualifierAnnotations = getQualifiers(e);
-    switch (qualifierAnnotations.size()) {
-      case 0:
-        return Optional.empty();
-      case 1:
-        return Optional.<AnnotationMirror>of(qualifierAnnotations.iterator().next());
-      default:
-        throw new IllegalArgumentException(
-            e + " was annotated with more than one @Qualifier annotation");
-    }
-  }
-
-  public ImmutableCollection<? extends AnnotationMirror> getQualifiers(Element element) {
-    ImmutableSet<? extends AnnotationMirror> qualifiers =
-        AnnotationMirrors.getAnnotatedAnnotations(element, Qualifier.class);
-    if (element.getKind() == ElementKind.FIELD
-        // static injected fields are not supported, no need to get qualifier from kotlin metadata
-        && !element.getModifiers().contains(STATIC)
-        && isAnnotationPresent(element, Inject.class)
-        && kotlinMetadataUtil.hasMetadata(element)) {
-      return Stream.concat(
-              qualifiers.stream(), getQualifiersForKotlinProperty(asVariable(element)).stream())
-          .map(EQUIVALENCE::wrap) // Wrap in equivalence to deduplicate
-          .distinct()
-          .map(Wrapper::get)
-          .collect(DaggerStreams.toImmutableList());
-    } else {
-      return qualifiers.asList();
-    }
-  }
-
-  /** Returns the constructors in {@code type} that are annotated with {@link Inject}. */
-  public static ImmutableSet<ExecutableElement> injectedConstructors(TypeElement type) {
-    return FluentIterable.from(constructorsIn(type.getEnclosedElements()))
-        .filter(constructor -> isAnnotationPresent(constructor, Inject.class))
-        .toSet();
-  }
-
-  /**
-   * Gets the qualifiers annotation of a Kotlin Property. Finding these annotations involve finding
-   * the synthetic method for annotations as described by the Kotlin metadata or finding the
-   * corresponding MembersInjector method for the field, which also contains the qualifier
-   * annotation.
-   */
-  private ImmutableCollection<? extends AnnotationMirror> getQualifiersForKotlinProperty(
-      VariableElement fieldElement) {
-    // TODO(bcorso): Consider moving this to KotlinMetadataUtil
-    if (kotlinMetadataUtil.isMissingSyntheticPropertyForAnnotations(fieldElement)) {
-      // If we detect that the synthetic method for annotations is missing, possibly due to the
-      // element being from a compiled class, then find the MembersInjector that was generated
-      // for the enclosing class and extract the qualifier information from it.
-      TypeElement membersInjector =
-          elements.getTypeElement(
-              membersInjectorNameForType(asType(fieldElement.getEnclosingElement())));
-      if (membersInjector != null) {
-        String memberInjectedFieldSignature = memberInjectedFieldSignatureForVariable(fieldElement);
-        // TODO(danysantiago): We have to iterate over all the injection methods for every qualifier
-        //  look up. Making this N^2 when looking through all the injected fields. :(
-        return ElementFilter.methodsIn(membersInjector.getEnclosedElements()).stream()
-            .filter(
-                method ->
-                    getAnnotationMirror(method, InjectedFieldSignature.class)
-                        .map(annotation -> getStringValue(annotation, "value"))
-                        .map(memberInjectedFieldSignature::equals)
-                        // If a method is not an @InjectedFieldSignature method then filter it out
-                        .orElse(false))
-            .collect(DaggerCollectors.toOptional())
-            .map(this::getQualifiers)
-            .orElseThrow(
-                () ->
-                    new IllegalStateException(
-                        String.format(
-                            "No matching InjectedFieldSignature for %1$s. This likely means that "
-                                + "%1$s was compiled with an older, incompatible version of "
-                                + "Dagger. Please update all Dagger dependencies to the same "
-                                + "version.",
-                            memberInjectedFieldSignature)));
-      } else {
-        throw new IllegalStateException(
-            "No MembersInjector found for " + fieldElement.getEnclosingElement());
-      }
-    } else {
-      return kotlinMetadataUtil.getSyntheticPropertyAnnotations(fieldElement, Qualifier.class);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/InjectionSiteFactory.java b/java/dagger/internal/codegen/binding/InjectionSiteFactory.java
deleted file mode 100644
index 7a6f8d2..0000000
--- a/java/dagger/internal/codegen/binding/InjectionSiteFactory.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2017 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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static dagger.internal.codegen.langmodel.DaggerElements.DECLARATION_ORDER;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.SetMultimap;
-import dagger.internal.codegen.binding.MembersInjectionBinding.InjectionSite;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementKindVisitor8;
-
-/** A factory for {@link Binding} objects. */
-final class InjectionSiteFactory {
-
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-  private final DependencyRequestFactory dependencyRequestFactory;
-
-  @Inject
-  InjectionSiteFactory(
-      DaggerTypes types,
-      DaggerElements elements,
-      DependencyRequestFactory dependencyRequestFactory) {
-    this.types = types;
-    this.elements = elements;
-    this.dependencyRequestFactory = dependencyRequestFactory;
-  }
-
-  /** Returns the injection sites for a type. */
-  ImmutableSortedSet<InjectionSite> getInjectionSites(DeclaredType declaredType) {
-    Set<InjectionSite> injectionSites = new HashSet<>();
-    List<TypeElement> ancestors = new ArrayList<>();
-    InjectionSiteVisitor injectionSiteVisitor = new InjectionSiteVisitor();
-    for (Optional<DeclaredType> currentType = Optional.of(declaredType);
-        currentType.isPresent();
-        currentType = types.nonObjectSuperclass(currentType.get())) {
-      DeclaredType type = currentType.get();
-      ancestors.add(MoreElements.asType(type.asElement()));
-      for (Element enclosedElement : type.asElement().getEnclosedElements()) {
-        injectionSiteVisitor.visit(enclosedElement, type).ifPresent(injectionSites::add);
-      }
-    }
-    return ImmutableSortedSet.copyOf(
-        // supertypes before subtypes
-        Comparator.comparing(
-                (InjectionSite injectionSite) ->
-                    ancestors.indexOf(injectionSite.element().getEnclosingElement()))
-            .reversed()
-            // fields before methods
-            .thenComparing(injectionSite -> injectionSite.element().getKind())
-            // then sort by whichever element comes first in the parent
-            // this isn't necessary, but makes the processor nice and predictable
-            .thenComparing(InjectionSite::element, DECLARATION_ORDER),
-        injectionSites);
-  }
-
-  private final class InjectionSiteVisitor
-      extends ElementKindVisitor8<Optional<InjectionSite>, DeclaredType> {
-    private final SetMultimap<String, ExecutableElement> subclassMethodMap =
-        LinkedHashMultimap.create();
-
-    InjectionSiteVisitor() {
-      super(Optional.empty());
-    }
-
-    @Override
-    public Optional<InjectionSite> visitExecutableAsMethod(
-        ExecutableElement method, DeclaredType type) {
-      subclassMethodMap.put(method.getSimpleName().toString(), method);
-      if (!shouldBeInjected(method)) {
-        return Optional.empty();
-      }
-      // This visitor assumes that subclass methods are visited before superclass methods, so we can
-      // skip any overridden method that has already been visited. To decrease the number of methods
-      // that are checked, we store the already injected methods in a SetMultimap and only check the
-      // methods with the same name.
-      String methodName = method.getSimpleName().toString();
-      TypeElement enclosingType = MoreElements.asType(method.getEnclosingElement());
-      for (ExecutableElement subclassMethod : subclassMethodMap.get(methodName)) {
-        if (method != subclassMethod && elements.overrides(subclassMethod, method, enclosingType)) {
-          return Optional.empty();
-        }
-      }
-      ExecutableType resolved = MoreTypes.asExecutable(types.asMemberOf(type, method));
-      return Optional.of(
-          InjectionSite.method(
-              method,
-              dependencyRequestFactory.forRequiredResolvedVariables(
-                  method.getParameters(), resolved.getParameterTypes())));
-    }
-
-    @Override
-    public Optional<InjectionSite> visitVariableAsField(
-        VariableElement field, DeclaredType type) {
-      if (!shouldBeInjected(field)) {
-        return Optional.empty();
-      }
-      TypeMirror resolved = types.asMemberOf(type, field);
-      return Optional.of(
-          InjectionSite.field(
-              field, dependencyRequestFactory.forRequiredResolvedVariable(field, resolved)));
-    }
-
-    private boolean shouldBeInjected(Element injectionSite) {
-      return isAnnotationPresent(injectionSite, Inject.class)
-          && !injectionSite.getModifiers().contains(PRIVATE)
-          && !injectionSite.getModifiers().contains(STATIC);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/KeyFactory.java b/java/dagger/internal/codegen/binding/KeyFactory.java
deleted file mode 100644
index d923666..0000000
--- a/java/dagger/internal/codegen/binding/KeyFactory.java
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.auto.common.MoreTypes.asExecutable;
-import static com.google.auto.common.MoreTypes.isType;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.RequestKinds.extractKeyType;
-import static dagger.internal.codegen.binding.MapKeys.getMapKey;
-import static dagger.internal.codegen.binding.MapKeys.mapKeyType;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.extension.Optionals.firstPresent;
-import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
-import static dagger.internal.codegen.langmodel.DaggerTypes.unwrapType;
-import static java.util.Arrays.asList;
-import static javax.lang.model.element.ElementKind.METHOD;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSet;
-import dagger.Binds;
-import dagger.BindsOptionalOf;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.FrameworkTypes;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.OptionalType;
-import dagger.internal.codegen.base.RequestKinds;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.base.SimpleAnnotationMirror;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-import dagger.model.Key.MultibindingContributionIdentifier;
-import dagger.model.RequestKind;
-import dagger.multibindings.Multibinds;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import dagger.producers.Production;
-import dagger.producers.internal.ProductionImplementation;
-import dagger.producers.monitoring.ProductionComponentMonitor;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.stream.Stream;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.PrimitiveType;
-import javax.lang.model.type.TypeMirror;
-
-/** A factory for {@link Key}s. */
-public final class KeyFactory {
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-  private final InjectionAnnotations injectionAnnotations;
-
-  @Inject
-  KeyFactory(
-      DaggerTypes types, DaggerElements elements, InjectionAnnotations injectionAnnotations) {
-    this.types = checkNotNull(types);
-    this.elements = checkNotNull(elements);
-    this.injectionAnnotations = injectionAnnotations;
-  }
-
-  private TypeMirror boxPrimitives(TypeMirror type) {
-    return type.getKind().isPrimitive() ? types.boxedClass((PrimitiveType) type).asType() : type;
-  }
-
-  private DeclaredType setOf(TypeMirror elementType) {
-    return types.getDeclaredType(elements.getTypeElement(Set.class), boxPrimitives(elementType));
-  }
-
-  private DeclaredType mapOf(TypeMirror keyType, TypeMirror valueType) {
-    return types.getDeclaredType(
-        elements.getTypeElement(Map.class), boxPrimitives(keyType), boxPrimitives(valueType));
-  }
-
-  /** Returns {@code Map<KeyType, FrameworkType<ValueType>>}. */
-  private TypeMirror mapOfFrameworkType(
-      TypeMirror keyType, TypeElement frameworkType, TypeMirror valueType) {
-    return mapOf(keyType, types.getDeclaredType(frameworkType, boxPrimitives(valueType)));
-  }
-
-  Key forComponentMethod(ExecutableElement componentMethod) {
-    checkArgument(componentMethod.getKind().equals(METHOD));
-    return forMethod(componentMethod, componentMethod.getReturnType());
-  }
-
-  Key forProductionComponentMethod(ExecutableElement componentMethod) {
-    checkArgument(componentMethod.getKind().equals(METHOD));
-    TypeMirror returnType = componentMethod.getReturnType();
-    TypeMirror keyType =
-        isFutureType(returnType)
-            ? getOnlyElement(MoreTypes.asDeclared(returnType).getTypeArguments())
-            : returnType;
-    return forMethod(componentMethod, keyType);
-  }
-
-  Key forSubcomponentCreatorMethod(
-      ExecutableElement subcomponentCreatorMethod, DeclaredType declaredContainer) {
-    checkArgument(subcomponentCreatorMethod.getKind().equals(METHOD));
-    ExecutableType resolvedMethod =
-        asExecutable(types.asMemberOf(declaredContainer, subcomponentCreatorMethod));
-    return Key.builder(resolvedMethod.getReturnType()).build();
-  }
-
-  public Key forSubcomponentCreator(TypeMirror creatorType) {
-    return Key.builder(creatorType).build();
-  }
-
-  public Key forProvidesMethod(ExecutableElement method, TypeElement contributingModule) {
-    return forBindingMethod(
-        method, contributingModule, Optional.of(elements.getTypeElement(Provider.class)));
-  }
-
-  public Key forProducesMethod(ExecutableElement method, TypeElement contributingModule) {
-    return forBindingMethod(
-        method, contributingModule, Optional.of(elements.getTypeElement(Producer.class)));
-  }
-
-  /** Returns the key bound by a {@link Binds} method. */
-  Key forBindsMethod(ExecutableElement method, TypeElement contributingModule) {
-    checkArgument(isAnnotationPresent(method, Binds.class));
-    return forBindingMethod(method, contributingModule, Optional.empty());
-  }
-
-  /** Returns the base key bound by a {@link BindsOptionalOf} method. */
-  Key forBindsOptionalOfMethod(ExecutableElement method, TypeElement contributingModule) {
-    checkArgument(isAnnotationPresent(method, BindsOptionalOf.class));
-    return forBindingMethod(method, contributingModule, Optional.empty());
-  }
-
-  private Key forBindingMethod(
-      ExecutableElement method,
-      TypeElement contributingModule,
-      Optional<TypeElement> frameworkType) {
-    checkArgument(method.getKind().equals(METHOD));
-    ExecutableType methodType =
-        MoreTypes.asExecutable(
-            types.asMemberOf(MoreTypes.asDeclared(contributingModule.asType()), method));
-    ContributionType contributionType = ContributionType.fromBindingElement(method);
-    TypeMirror returnType = methodType.getReturnType();
-    if (frameworkType.isPresent()
-        && frameworkType.get().equals(elements.getTypeElement(Producer.class))
-        && isType(returnType)) {
-      if (isFutureType(methodType.getReturnType())) {
-        returnType = getOnlyElement(MoreTypes.asDeclared(returnType).getTypeArguments());
-      } else if (contributionType.equals(ContributionType.SET_VALUES)
-          && SetType.isSet(returnType)) {
-        SetType setType = SetType.from(returnType);
-        if (isFutureType(setType.elementType())) {
-          returnType =
-              types.getDeclaredType(
-                  elements.getTypeElement(Set.class), unwrapType(setType.elementType()));
-        }
-      }
-    }
-    TypeMirror keyType = bindingMethodKeyType(returnType, method, contributionType, frameworkType);
-    Key key = forMethod(method, keyType);
-    return contributionType.equals(ContributionType.UNIQUE)
-        ? key
-        : key.toBuilder()
-            .multibindingContributionIdentifier(
-                new MultibindingContributionIdentifier(method, contributingModule))
-            .build();
-  }
-
-  /**
-   * Returns the key for a {@link Multibinds @Multibinds} method.
-   *
-   * <p>The key's type is either {@code Set<T>} or {@code Map<K, Provider<V>>}. The latter works
-   * even for maps used by {@code Producer}s.
-   */
-  Key forMultibindsMethod(ExecutableType executableType, ExecutableElement method) {
-    checkArgument(method.getKind().equals(METHOD), "%s must be a method", method);
-    TypeMirror returnType = executableType.getReturnType();
-    TypeMirror keyType =
-        MapType.isMap(returnType)
-            ? mapOfFrameworkType(
-                MapType.from(returnType).keyType(),
-                elements.getTypeElement(Provider.class),
-                MapType.from(returnType).valueType())
-            : returnType;
-    return forMethod(method, keyType);
-  }
-
-  private TypeMirror bindingMethodKeyType(
-      TypeMirror returnType,
-      ExecutableElement method,
-      ContributionType contributionType,
-      Optional<TypeElement> frameworkType) {
-    switch (contributionType) {
-      case UNIQUE:
-        return returnType;
-      case SET:
-        return setOf(returnType);
-      case MAP:
-        TypeMirror mapKeyType = mapKeyType(getMapKey(method).get(), types);
-        return frameworkType.isPresent()
-            ? mapOfFrameworkType(mapKeyType, frameworkType.get(), returnType)
-            : mapOf(mapKeyType, returnType);
-      case SET_VALUES:
-        // TODO(gak): do we want to allow people to use "covariant return" here?
-        checkArgument(SetType.isSet(returnType));
-        return returnType;
-    }
-    throw new AssertionError();
-  }
-
-  /**
-   * Returns the key for a binding associated with a {@link DelegateDeclaration}.
-   *
-   * <p>If {@code delegateDeclaration} is {@code @IntoMap}, transforms the {@code Map<K, V>} key
-   * from {@link DelegateDeclaration#key()} to {@code Map<K, FrameworkType<V>>}. If {@code
-   * delegateDeclaration} is not a map contribution, its key is returned.
-   */
-  Key forDelegateBinding(DelegateDeclaration delegateDeclaration, Class<?> frameworkType) {
-    return delegateDeclaration.contributionType().equals(ContributionType.MAP)
-        ? wrapMapValue(delegateDeclaration.key(), frameworkType)
-        : delegateDeclaration.key();
-  }
-
-  private Key forMethod(ExecutableElement method, TypeMirror keyType) {
-    return forQualifiedType(injectionAnnotations.getQualifier(method), keyType);
-  }
-
-  public Key forInjectConstructorWithResolvedType(TypeMirror type) {
-    return Key.builder(type).build();
-  }
-
-  // TODO(ronshapiro): Remove these conveniences which are simple wrappers around Key.Builder
-  Key forType(TypeMirror type) {
-    return Key.builder(type).build();
-  }
-
-  public Key forMembersInjectedType(TypeMirror type) {
-    return Key.builder(type).build();
-  }
-
-  Key forQualifiedType(Optional<AnnotationMirror> qualifier, TypeMirror type) {
-    return Key.builder(boxPrimitives(type)).qualifier(qualifier).build();
-  }
-
-  public Key forProductionExecutor() {
-    return Key.builder(elements.getTypeElement(Executor.class).asType())
-        .qualifier(SimpleAnnotationMirror.of(elements.getTypeElement(Production.class)))
-        .build();
-  }
-
-  public Key forProductionImplementationExecutor() {
-    return Key.builder(elements.getTypeElement(Executor.class).asType())
-        .qualifier(SimpleAnnotationMirror.of(elements.getTypeElement(ProductionImplementation.class)))
-        .build();
-  }
-
-  public Key forProductionComponentMonitor() {
-    return Key.builder(elements.getTypeElement(ProductionComponentMonitor.class).asType()).build();
-  }
-
-  /**
-   * If {@code requestKey} is for a {@code Map<K, V>} or {@code Map<K, Produced<V>>}, returns keys
-   * for {@code Map<K, Provider<V>>} and {@code Map<K, Producer<V>>} (if Dagger-Producers is on
-   * the classpath).
-   */
-  ImmutableSet<Key> implicitFrameworkMapKeys(Key requestKey) {
-    return Stream.of(implicitMapProviderKeyFrom(requestKey), implicitMapProducerKeyFrom(requestKey))
-        .filter(Optional::isPresent)
-        .map(Optional::get)
-        .collect(toImmutableSet());
-  }
-
-  /**
-   * Optionally extract a {@link Key} for the underlying provision binding(s) if such a valid key
-   * can be inferred from the given key. Specifically, if the key represents a {@link Map}{@code
-   * <K, V>} or {@code Map<K, Producer<V>>}, a key of {@code Map<K, Provider<V>>} will be
-   * returned.
-   */
-  Optional<Key> implicitMapProviderKeyFrom(Key possibleMapKey) {
-    return firstPresent(
-        rewrapMapKey(possibleMapKey, Produced.class, Provider.class),
-        wrapMapKey(possibleMapKey, Provider.class));
-  }
-
-  /**
-   * Optionally extract a {@link Key} for the underlying production binding(s) if such a
-   * valid key can be inferred from the given key.  Specifically, if the key represents a
-   * {@link Map}{@code <K, V>} or {@code Map<K, Produced<V>>}, a key of
-   * {@code Map<K, Producer<V>>} will be returned.
-   */
-  Optional<Key> implicitMapProducerKeyFrom(Key possibleMapKey) {
-    return firstPresent(
-        rewrapMapKey(possibleMapKey, Produced.class, Producer.class),
-        wrapMapKey(possibleMapKey, Producer.class));
-  }
-
-  /**
-   * If {@code key}'s type is {@code Map<K, Provider<V>>}, {@code Map<K, Producer<V>>}, or {@code
-   * Map<K, Produced<V>>}, returns a key with the same qualifier and {@link
-   * Key#multibindingContributionIdentifier()} whose type is simply {@code Map<K, V>}.
-   *
-   * <p>Otherwise, returns {@code key}.
-   */
-  public Key unwrapMapValueType(Key key) {
-    if (MapType.isMap(key)) {
-      MapType mapType = MapType.from(key);
-      if (!mapType.isRawType()) {
-        for (Class<?> frameworkClass : asList(Provider.class, Producer.class, Produced.class)) {
-          if (mapType.valuesAreTypeOf(frameworkClass)) {
-            return key.toBuilder()
-                .type(mapOf(mapType.keyType(), mapType.unwrappedValueType(frameworkClass)))
-                .build();
-          }
-        }
-      }
-    }
-    return key;
-  }
-
-  /**
-   * Converts a {@link Key} of type {@code Map<K, V>} to {@code Map<K, Provider<V>>}.
-   */
-  private Key wrapMapValue(Key key, Class<?> newWrappingClass) {
-    checkArgument(
-        FrameworkTypes.isFrameworkType(elements.getTypeElement(newWrappingClass).asType()));
-    return wrapMapKey(key, newWrappingClass).get();
-  }
-
-  /**
-   * If {@code key}'s type is {@code Map<K, CurrentWrappingClass<Bar>>}, returns a key with type
-   * {@code Map<K, NewWrappingClass<Bar>>} with the same qualifier. Otherwise returns {@link
-   * Optional#empty()}.
-   *
-   * <p>Returns {@link Optional#empty()} if {@code newWrappingClass} is not in the classpath.
-   *
-   * @throws IllegalArgumentException if {@code newWrappingClass} is the same as {@code
-   *     currentWrappingClass}
-   */
-  public Optional<Key> rewrapMapKey(
-      Key possibleMapKey, Class<?> currentWrappingClass, Class<?> newWrappingClass) {
-    checkArgument(!currentWrappingClass.equals(newWrappingClass));
-    if (MapType.isMap(possibleMapKey)) {
-      MapType mapType = MapType.from(possibleMapKey);
-      if (!mapType.isRawType() && mapType.valuesAreTypeOf(currentWrappingClass)) {
-        TypeElement wrappingElement = elements.getTypeElement(newWrappingClass);
-        if (wrappingElement == null) {
-          // This target might not be compiled with Producers, so wrappingClass might not have an
-          // associated element.
-          return Optional.empty();
-        }
-        DeclaredType wrappedValueType =
-            types.getDeclaredType(
-                wrappingElement, mapType.unwrappedValueType(currentWrappingClass));
-        return Optional.of(
-            possibleMapKey.toBuilder().type(mapOf(mapType.keyType(), wrappedValueType)).build());
-      }
-    }
-    return Optional.empty();
-  }
-
-  /**
-   * If {@code key}'s type is {@code Map<K, Foo>} and {@code Foo} is not {@code WrappingClass
-   * <Bar>}, returns a key with type {@code Map<K, WrappingClass<Foo>>} with the same qualifier.
-   * Otherwise returns {@link Optional#empty()}.
-   *
-   * <p>Returns {@link Optional#empty()} if {@code WrappingClass} is not in the classpath.
-   */
-  private Optional<Key> wrapMapKey(Key possibleMapKey, Class<?> wrappingClass) {
-    if (MapType.isMap(possibleMapKey)) {
-      MapType mapType = MapType.from(possibleMapKey);
-      if (!mapType.isRawType() && !mapType.valuesAreTypeOf(wrappingClass)) {
-        TypeElement wrappingElement = elements.getTypeElement(wrappingClass);
-        if (wrappingElement == null) {
-          // This target might not be compiled with Producers, so wrappingClass might not have an
-          // associated element.
-          return Optional.empty();
-        }
-        DeclaredType wrappedValueType = types.getDeclaredType(wrappingElement, mapType.valueType());
-        return Optional.of(
-            possibleMapKey.toBuilder().type(mapOf(mapType.keyType(), wrappedValueType)).build());
-      }
-    }
-    return Optional.empty();
-  }
-
-  /**
-   * If {@code key}'s type is {@code Set<WrappingClass<Bar>>}, returns a key with type {@code Set
-   * <Bar>} with the same qualifier. Otherwise returns {@link Optional#empty()}.
-   */
-  Optional<Key> unwrapSetKey(Key key, Class<?> wrappingClass) {
-    if (SetType.isSet(key)) {
-      SetType setType = SetType.from(key);
-      if (!setType.isRawType() && setType.elementsAreTypeOf(wrappingClass)) {
-        return Optional.of(
-            key.toBuilder().type(setOf(setType.unwrappedElementType(wrappingClass))).build());
-      }
-    }
-    return Optional.empty();
-  }
-
-  /**
-   * If {@code key}'s type is {@code Optional<T>} for some {@code T}, returns a key with the same
-   * qualifier whose type is {@linkplain RequestKinds#extractKeyType(RequestKind, TypeMirror)}
-   * extracted} from {@code T}.
-   */
-  Optional<Key> unwrapOptional(Key key) {
-    if (!OptionalType.isOptional(key)) {
-      return Optional.empty();
-    }
-
-    TypeMirror optionalValueType = OptionalType.from(key).valueType();
-    return Optional.of(key.toBuilder().type(extractKeyType(optionalValueType)).build());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/KeyVariableNamer.java b/java/dagger/internal/codegen/binding/KeyVariableNamer.java
deleted file mode 100644
index 9ac0efa..0000000
--- a/java/dagger/internal/codegen/binding/KeyVariableNamer.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static dagger.internal.codegen.binding.SourceFiles.protectAgainstKeywords;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSet;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import java.util.Iterator;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.PrimitiveType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVisitor;
-import javax.lang.model.util.SimpleTypeVisitor8;
-
-/**
- * Suggests a variable name for a type based on a {@link Key}. Prefer {@link
- * DependencyVariableNamer} for cases where a specific {@link DependencyRequest} is present.
- */
-public final class KeyVariableNamer {
-  /** Simple names that are very common. Inspired by https://errorprone.info/bugpattern/BadImport */
-  private static final ImmutableSet<String> VERY_SIMPLE_NAMES =
-      ImmutableSet.of(
-          "Builder",
-          "Factory",
-          "Component",
-          "Subcomponent",
-          "Injector");
-
-  private static final TypeVisitor<Void, StringBuilder> TYPE_NAMER =
-      new SimpleTypeVisitor8<Void, StringBuilder>() {
-        @Override
-        public Void visitDeclared(DeclaredType declaredType, StringBuilder builder) {
-          TypeElement element = MoreTypes.asTypeElement(declaredType);
-          if (element.getNestingKind().isNested()
-              && VERY_SIMPLE_NAMES.contains(element.getSimpleName().toString())) {
-            builder.append(element.getEnclosingElement().getSimpleName());
-          }
-
-          builder.append(element.getSimpleName());
-          Iterator<? extends TypeMirror> argumentIterator =
-              declaredType.getTypeArguments().iterator();
-          if (argumentIterator.hasNext()) {
-            builder.append("Of");
-            TypeMirror first = argumentIterator.next();
-            first.accept(this, builder);
-            while (argumentIterator.hasNext()) {
-              builder.append("And");
-              argumentIterator.next().accept(this, builder);
-            }
-          }
-          return null;
-        }
-
-        @Override
-        public Void visitPrimitive(PrimitiveType type, StringBuilder builder) {
-          builder.append(LOWER_CAMEL.to(UPPER_CAMEL, type.toString()));
-          return null;
-        }
-
-        @Override
-        public Void visitArray(ArrayType type, StringBuilder builder) {
-          type.getComponentType().accept(this, builder);
-          builder.append("Array");
-          return null;
-        }
-      };
-
-  private KeyVariableNamer() {}
-
-  public static String name(Key key) {
-    if (key.multibindingContributionIdentifier().isPresent()) {
-      return key.multibindingContributionIdentifier().get().bindingElement();
-    }
-
-    StringBuilder builder = new StringBuilder();
-
-    if (key.qualifier().isPresent()) {
-      // TODO(gak): Use a better name for fields with qualifiers with members.
-      builder.append(key.qualifier().get().getAnnotationType().asElement().getSimpleName());
-    }
-
-    key.type().accept(TYPE_NAMER, builder);
-
-    return protectAgainstKeywords(UPPER_CAMEL.to(LOWER_CAMEL, builder.toString()));
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/LegacyBindingGraph.java b/java/dagger/internal/codegen/binding/LegacyBindingGraph.java
deleted file mode 100644
index 7c00401..0000000
--- a/java/dagger/internal/codegen/binding/LegacyBindingGraph.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimaps;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-import java.util.Collection;
-import java.util.Map;
-import javax.lang.model.element.TypeElement;
-
-// TODO(bcorso): Remove the LegacyBindingGraph after we've migrated to the new BindingGraph.
-/** The canonical representation of a full-resolved graph. */
-final class LegacyBindingGraph {
-  private final ComponentDescriptor componentDescriptor;
-  private final ImmutableMap<Key, ResolvedBindings> contributionBindings;
-  private final ImmutableMap<Key, ResolvedBindings> membersInjectionBindings;
-  private final ImmutableList<LegacyBindingGraph> subgraphs;
-
-  LegacyBindingGraph(
-      ComponentDescriptor componentDescriptor,
-      ImmutableMap<Key, ResolvedBindings> contributionBindings,
-      ImmutableMap<Key, ResolvedBindings> membersInjectionBindings,
-      ImmutableList<LegacyBindingGraph> subgraphs) {
-    this.componentDescriptor = componentDescriptor;
-    this.contributionBindings = contributionBindings;
-    this.membersInjectionBindings = membersInjectionBindings;
-    this.subgraphs = checkForDuplicates(subgraphs);
-  }
-
-  ComponentDescriptor componentDescriptor() {
-    return componentDescriptor;
-  }
-
-  ResolvedBindings resolvedBindings(BindingRequest request) {
-    return request.isRequestKind(RequestKind.MEMBERS_INJECTION)
-        ? membersInjectionBindings.get(request.key())
-        : contributionBindings.get(request.key());
-  }
-
-  Iterable<ResolvedBindings> resolvedBindings() {
-    // Don't return an immutable collection - this is only ever used for looping over all bindings
-    // in the graph. Copying is wasteful, especially if is a hashing collection, since the values
-    // should all, by definition, be distinct.
-    return Iterables.concat(membersInjectionBindings.values(), contributionBindings.values());
-  }
-
-  ImmutableList<LegacyBindingGraph> subgraphs() {
-    return subgraphs;
-  }
-
-  private static ImmutableList<LegacyBindingGraph> checkForDuplicates(
-      ImmutableList<LegacyBindingGraph> graphs) {
-    Map<TypeElement, Collection<LegacyBindingGraph>> duplicateGraphs =
-        Maps.filterValues(
-            Multimaps.index(graphs, graph -> graph.componentDescriptor().typeElement()).asMap(),
-            overlapping -> overlapping.size() > 1);
-    if (!duplicateGraphs.isEmpty()) {
-      throw new IllegalArgumentException("Expected no duplicates: " + duplicateGraphs);
-    }
-    return graphs;
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/MapKeys.java b/java/dagger/internal/codegen/binding/MapKeys.java
deleted file mode 100644
index ec7d79d..0000000
--- a/java/dagger/internal/codegen/binding/MapKeys.java
+++ /dev/null
@@ -1,222 +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.binding;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotatedAnnotations;
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static dagger.internal.codegen.base.MapKeyAccessibility.isMapKeyPubliclyAccessible;
-import static dagger.internal.codegen.binding.SourceFiles.elementBasedClassName;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.MapKey;
-import dagger.internal.codegen.base.MapKeyAccessibility;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.util.NoSuchElementException;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.PrimitiveType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleTypeVisitor6;
-
-/** Methods for extracting {@link MapKey} annotations and key code blocks from binding elements. */
-public final class MapKeys {
-
-  /**
-   * If {@code bindingElement} is annotated with a {@link MapKey} annotation, returns it.
-   *
-   * @throws IllegalArgumentException if the element is annotated with more than one {@code MapKey}
-   *     annotation
-   */
-  static Optional<AnnotationMirror> getMapKey(Element bindingElement) {
-    ImmutableSet<? extends AnnotationMirror> mapKeys = getMapKeys(bindingElement);
-    return mapKeys.isEmpty()
-        ? Optional.empty()
-        : Optional.<AnnotationMirror>of(getOnlyElement(mapKeys));
-  }
-
-  /** Returns all of the {@link MapKey} annotations that annotate {@code bindingElement}. */
-  public static ImmutableSet<? extends AnnotationMirror> getMapKeys(Element bindingElement) {
-    return getAnnotatedAnnotations(bindingElement, MapKey.class);
-  }
-
-  /**
-   * Returns the annotation value if {@code mapKey}'s type is annotated with
-   * {@link MapKey @MapKey(unwrapValue = true)}.
-   *
-   * @throws IllegalArgumentException if {@code mapKey}'s type is not annotated with
-   *     {@link MapKey @MapKey} at all.
-   */
-  static Optional<? extends AnnotationValue> unwrapValue(AnnotationMirror mapKey) {
-    MapKey mapKeyAnnotation = mapKey.getAnnotationType().asElement().getAnnotation(MapKey.class);
-    checkArgument(
-        mapKeyAnnotation != null, "%s is not annotated with @MapKey", mapKey.getAnnotationType());
-    return mapKeyAnnotation.unwrapValue()
-        ? Optional.of(getOnlyElement(getAnnotationValuesWithDefaults(mapKey).values()))
-        : Optional.empty();
-  }
-
-  static TypeMirror mapKeyType(AnnotationMirror mapKeyAnnotation, DaggerTypes types) {
-    return unwrapValue(mapKeyAnnotation).isPresent()
-        ? getUnwrappedMapKeyType(mapKeyAnnotation.getAnnotationType(), types)
-        : mapKeyAnnotation.getAnnotationType();
-  }
-
-  /**
-   * Returns the map key type for an unwrapped {@link MapKey} annotation type. If the single member
-   * type is primitive, returns the boxed type.
-   *
-   * @throws IllegalArgumentException if {@code mapKeyAnnotationType} is not an annotation type or
-   *     has more than one member, or if its single member is an array
-   * @throws NoSuchElementException if the annotation has no members
-   */
-  public static DeclaredType getUnwrappedMapKeyType(
-      final DeclaredType mapKeyAnnotationType, final DaggerTypes types) {
-    checkArgument(
-        MoreTypes.asTypeElement(mapKeyAnnotationType).getKind() == ElementKind.ANNOTATION_TYPE,
-        "%s is not an annotation type",
-        mapKeyAnnotationType);
-
-    final ExecutableElement onlyElement =
-        getOnlyElement(methodsIn(mapKeyAnnotationType.asElement().getEnclosedElements()));
-
-    SimpleTypeVisitor6<DeclaredType, Void> keyTypeElementVisitor =
-        new SimpleTypeVisitor6<DeclaredType, Void>() {
-
-          @Override
-          public DeclaredType visitArray(ArrayType t, Void p) {
-            throw new IllegalArgumentException(
-                mapKeyAnnotationType + "." + onlyElement.getSimpleName() + " cannot be an array");
-          }
-
-          @Override
-          public DeclaredType visitPrimitive(PrimitiveType t, Void p) {
-            return MoreTypes.asDeclared(types.boxedClass(t).asType());
-          }
-
-          @Override
-          public DeclaredType visitDeclared(DeclaredType t, Void p) {
-            return t;
-          }
-        };
-    return keyTypeElementVisitor.visit(onlyElement.getReturnType());
-  }
-
-  /**
-   * Returns a code block for {@code binding}'s {@link ContributionBinding#mapKeyAnnotation() map
-   * key}. If for whatever reason the map key is not accessible from within {@code requestingClass}
-   * (i.e. it has a package-private {@code enum} from a different package), this will return an
-   * invocation of a proxy-method giving it access.
-   *
-   * @throws IllegalStateException if {@code binding} is not a {@link dagger.multibindings.IntoMap
-   *     map} contribution.
-   */
-  public static CodeBlock getMapKeyExpression(
-      ContributionBinding binding, ClassName requestingClass, DaggerElements elements) {
-    AnnotationMirror mapKeyAnnotation = binding.mapKeyAnnotation().get();
-    return MapKeyAccessibility.isMapKeyAccessibleFrom(
-            mapKeyAnnotation, requestingClass.packageName())
-        ? directMapKeyExpression(mapKeyAnnotation, elements)
-        : CodeBlock.of("$T.create()", mapKeyProxyClassName(binding));
-  }
-
-  /**
-   * Returns a code block for the map key annotation {@code mapKey}.
-   *
-   * <p>This method assumes the map key will be accessible in the context that the returned {@link
-   * CodeBlock} is used. Use {@link #getMapKeyExpression(ContributionBinding, ClassName,
-   * DaggerElements)} when that assumption is not guaranteed.
-   *
-   * @throws IllegalArgumentException if the element is annotated with more than one {@code MapKey}
-   *     annotation
-   * @throws IllegalStateException if {@code bindingElement} is not annotated with a {@code MapKey}
-   *     annotation
-   */
-  private static CodeBlock directMapKeyExpression(
-      AnnotationMirror mapKey, DaggerElements elements) {
-    Optional<? extends AnnotationValue> unwrappedValue = unwrapValue(mapKey);
-    AnnotationExpression annotationExpression = new AnnotationExpression(mapKey);
-
-    if (MoreTypes.asTypeElement(mapKey.getAnnotationType())
-        .getQualifiedName()
-        .contentEquals("dagger.android.AndroidInjectionKey")) {
-      TypeElement unwrappedType =
-          elements.checkTypePresent((String) unwrappedValue.get().getValue());
-      return CodeBlock.of(
-          "$T.of($S)",
-          ClassName.get("dagger.android.internal", "AndroidInjectionKeys"),
-          ClassName.get(unwrappedType).reflectionName());
-    }
-
-    if (unwrappedValue.isPresent()) {
-      TypeMirror unwrappedValueType =
-          getOnlyElement(getAnnotationValuesWithDefaults(mapKey).keySet()).getReturnType();
-      return annotationExpression.getValueExpression(unwrappedValueType, unwrappedValue.get());
-    } else {
-      return annotationExpression.getAnnotationInstanceExpression();
-    }
-  }
-
-  /**
-   * Returns the {@link ClassName} in which {@link #mapKeyFactoryMethod(ContributionBinding,
-   * DaggerTypes, DaggerElements)} is generated.
-   */
-  public static ClassName mapKeyProxyClassName(ContributionBinding binding) {
-    return elementBasedClassName(
-        MoreElements.asExecutable(binding.bindingElement().get()), "MapKey");
-  }
-
-  /**
-   * A {@code static create()} method to be added to {@link
-   * #mapKeyProxyClassName(ContributionBinding)} when the {@code @MapKey} annotation is not publicly
-   * accessible.
-   */
-  public static Optional<MethodSpec> mapKeyFactoryMethod(
-      ContributionBinding binding, DaggerTypes types, DaggerElements elements) {
-    return binding
-        .mapKeyAnnotation()
-        .filter(mapKey -> !isMapKeyPubliclyAccessible(mapKey))
-        .map(
-            mapKey ->
-                methodBuilder("create")
-                    .addModifiers(PUBLIC, STATIC)
-                    .returns(TypeName.get(mapKeyType(mapKey, types)))
-                    .addStatement("return $L", directMapKeyExpression(mapKey, elements))
-                    .build());
-  }
-
-  private MapKeys() {}
-}
diff --git a/java/dagger/internal/codegen/binding/MembersInjectionBinding.java b/java/dagger/internal/codegen/binding/MembersInjectionBinding.java
deleted file mode 100644
index 3dd1016..0000000
--- a/java/dagger/internal/codegen/binding/MembersInjectionBinding.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static java.util.stream.Collectors.toList;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSortedSet;
-import dagger.model.BindingKind;
-import dagger.model.DependencyRequest;
-import java.util.Optional;
-import javax.inject.Inject;
-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.element.VariableElement;
-
-/** Represents the full members injection of a particular type. */
-@AutoValue
-public abstract class MembersInjectionBinding extends Binding {
-  @Override
-  public final Optional<Element> bindingElement() {
-    return Optional.of(membersInjectedType());
-  }
-
-  public abstract TypeElement membersInjectedType();
-
-  @Override
-  public abstract Optional<MembersInjectionBinding> unresolved();
-
-  @Override
-  public Optional<TypeElement> contributingModule() {
-    return Optional.empty();
-  }
-
-  /** The set of individual sites where {@link Inject} is applied. */
-  public abstract ImmutableSortedSet<InjectionSite> injectionSites();
-
-  @Override
-  public BindingType bindingType() {
-    return BindingType.MEMBERS_INJECTION;
-  }
-
-  @Override
-  public BindingKind kind() {
-    return BindingKind.MEMBERS_INJECTION;
-  }
-
-  @Override
-  public boolean isNullable() {
-    return false;
-  }
-
-  /**
-   * Returns {@code true} if any of this binding's injection sites are directly on the bound type.
-   */
-  public boolean hasLocalInjectionSites() {
-    return injectionSites()
-        .stream()
-        .anyMatch(
-            injectionSite ->
-                injectionSite.element().getEnclosingElement().equals(membersInjectedType()));
-  }
-
-  @Override
-  public boolean requiresModuleInstance() {
-    return false;
-  }
-
-  @Memoized
-  @Override
-  public abstract int hashCode();
-
-  // TODO(ronshapiro,dpb): simplify the equality semantics
-  @Override
-  public abstract boolean equals(Object obj);
-
-  /** Metadata about a field or method injection site. */
-  @AutoValue
-  public abstract static class InjectionSite {
-    /** The type of injection site. */
-    public enum Kind {
-      FIELD,
-      METHOD,
-    }
-
-    public abstract Kind kind();
-
-    public abstract Element element();
-
-    public abstract ImmutableSet<DependencyRequest> dependencies();
-
-    /**
-     * Returns the index of {@link #element()} in its parents {@code @Inject} members that have the
-     * same simple name. This method filters out private elements so that the results will be
-     * consistent independent of whether the build system uses header jars or not.
-     */
-    @Memoized
-    public int indexAmongAtInjectMembersWithSameSimpleName() {
-      return element()
-          .getEnclosingElement()
-          .getEnclosedElements()
-          .stream()
-          .filter(element -> isAnnotationPresent(element, Inject.class))
-          .filter(element -> !element.getModifiers().contains(Modifier.PRIVATE))
-          .filter(element -> element.getSimpleName().equals(this.element().getSimpleName()))
-          .collect(toList())
-          .indexOf(element());
-    }
-
-    public static InjectionSite field(VariableElement element, DependencyRequest dependency) {
-      return new AutoValue_MembersInjectionBinding_InjectionSite(
-          Kind.FIELD, element, ImmutableSet.of(dependency));
-    }
-
-    public static InjectionSite method(
-        ExecutableElement element, Iterable<DependencyRequest> dependencies) {
-      return new AutoValue_MembersInjectionBinding_InjectionSite(
-          Kind.METHOD, element, ImmutableSet.copyOf(dependencies));
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java b/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java
deleted file mode 100644
index 97c680f..0000000
--- a/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.common.base.Preconditions.checkState;
-import static dagger.internal.codegen.base.DiagnosticFormatting.stripCommonTypePrefixes;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import dagger.internal.codegen.base.Formatter;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-
-/** Formats the signature of an {@link ExecutableElement} suitable for use in error messages. */
-public final class MethodSignatureFormatter extends Formatter<ExecutableElement> {
-  private final DaggerTypes types;
-  private final InjectionAnnotations injectionAnnotations;
-
-  @Inject
-  public MethodSignatureFormatter(DaggerTypes types, InjectionAnnotations injectionAnnotations) {
-    this.types = types;
-    this.injectionAnnotations = injectionAnnotations;
-  }
-
-  /**
-   * A formatter that uses the type where the method is declared for the annotations and name of the
-   * method, but the method's resolved type as a member of {@code declaredType} for the key.
-   */
-  public Formatter<ExecutableElement> typedFormatter(DeclaredType declaredType) {
-    return new Formatter<ExecutableElement>() {
-      @Override
-      public String format(ExecutableElement method) {
-        return MethodSignatureFormatter.this.format(
-            method,
-            MoreTypes.asExecutable(types.asMemberOf(declaredType, method)),
-            MoreElements.asType(method.getEnclosingElement()));
-      }
-    };
-  }
-
-  @Override
-  public String format(ExecutableElement method) {
-    return format(method, Optional.empty());
-  }
-
-  /**
-   * Formats an ExecutableElement as if it were contained within the container, if the container is
-   * present.
-   */
-  public String format(ExecutableElement method, Optional<DeclaredType> container) {
-    TypeElement type = MoreElements.asType(method.getEnclosingElement());
-    ExecutableType executableType = MoreTypes.asExecutable(method.asType());
-    if (container.isPresent()) {
-      executableType = MoreTypes.asExecutable(types.asMemberOf(container.get(), method));
-      type = MoreElements.asType(container.get().asElement());
-    }
-    return format(method, executableType, type);
-  }
-
-  private String format(
-      ExecutableElement method, ExecutableType methodType, TypeElement declaringType) {
-    StringBuilder builder = new StringBuilder();
-    // TODO(user): AnnotationMirror formatter.
-    List<? extends AnnotationMirror> annotations = method.getAnnotationMirrors();
-    if (!annotations.isEmpty()) {
-      Iterator<? extends AnnotationMirror> annotationIterator = annotations.iterator();
-      for (int i = 0; annotationIterator.hasNext(); i++) {
-        if (i > 0) {
-          builder.append(' ');
-        }
-        builder.append(formatAnnotation(annotationIterator.next()));
-      }
-      builder.append(' ');
-    }
-    if (method.getSimpleName().contentEquals("<init>")) {
-      builder.append(declaringType.getQualifiedName());
-    } else {
-      builder
-          .append(nameOfType(methodType.getReturnType()))
-          .append(' ')
-          .append(declaringType.getQualifiedName())
-          .append('.')
-          .append(method.getSimpleName());
-    }
-    builder.append('(');
-    checkState(method.getParameters().size() == methodType.getParameterTypes().size());
-    Iterator<? extends VariableElement> parameters = method.getParameters().iterator();
-    Iterator<? extends TypeMirror> parameterTypes = methodType.getParameterTypes().iterator();
-    for (int i = 0; parameters.hasNext(); i++) {
-      if (i > 0) {
-        builder.append(", ");
-      }
-      appendParameter(builder, parameters.next(), parameterTypes.next());
-    }
-    builder.append(')');
-    return builder.toString();
-  }
-
-  private void appendParameter(StringBuilder builder, VariableElement parameter, TypeMirror type) {
-    injectionAnnotations
-        .getQualifier(parameter)
-        .ifPresent(
-            qualifier -> {
-              builder.append(formatAnnotation(qualifier)).append(' ');
-            });
-    builder.append(nameOfType(type));
-  }
-
-  private static String nameOfType(TypeMirror type) {
-    return stripCommonTypePrefixes(type.toString());
-  }
-
-  private static String formatAnnotation(AnnotationMirror annotation) {
-    return stripCommonTypePrefixes(annotation.toString());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ModuleDescriptor.java b/java/dagger/internal/codegen/binding/ModuleDescriptor.java
deleted file mode 100644
index c471f94..0000000
--- a/java/dagger/internal/codegen/binding/ModuleDescriptor.java
+++ /dev/null
@@ -1,267 +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.binding;
-
-import static com.google.auto.common.MoreElements.asExecutable;
-import static com.google.auto.common.MoreElements.getPackage;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Verify.verify;
-import static com.google.common.collect.Iterables.transform;
-import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.binding.SourceFiles.classFileName;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.getMethodDescriptor;
-import static dagger.internal.codegen.langmodel.DaggerElements.isAnnotationPresent;
-import static javax.lang.model.type.TypeKind.DECLARED;
-import static javax.lang.model.type.TypeKind.NONE;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.graph.Traverser;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import com.squareup.javapoet.ClassName;
-import dagger.Binds;
-import dagger.BindsOptionalOf;
-import dagger.Module;
-import dagger.Provides;
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.model.Key;
-import dagger.multibindings.Multibinds;
-import dagger.producers.Produces;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-/** Contains metadata that describes a module. */
-@AutoValue
-public abstract class ModuleDescriptor {
-
-  public abstract TypeElement moduleElement();
-
-  abstract ImmutableSet<TypeElement> includedModules();
-
-  public abstract ImmutableSet<ContributionBinding> bindings();
-
-  /** The multibinding declarations contained in this module. */
-  abstract ImmutableSet<MultibindingDeclaration> multibindingDeclarations();
-
-  /** The {@link Module#subcomponents() subcomponent declarations} contained in this module. */
-  abstract ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations();
-
-  /** The {@link Binds} method declarations that define delegate bindings. */
-  abstract ImmutableSet<DelegateDeclaration> delegateDeclarations();
-
-  /** The {@link BindsOptionalOf} method declarations that define optional bindings. */
-  abstract ImmutableSet<OptionalBindingDeclaration> optionalDeclarations();
-
-  /** The kind of the module. */
-  public abstract ModuleKind kind();
-
-  /** Returns all of the bindings declared in this module. */
-  @Memoized
-  public ImmutableSet<BindingDeclaration> allBindingDeclarations() {
-    return ImmutableSet.<BindingDeclaration>builder()
-        .addAll(bindings())
-        .addAll(delegateDeclarations())
-        .addAll(multibindingDeclarations())
-        .addAll(optionalDeclarations())
-        .addAll(subcomponentDeclarations())
-        .build();
-  }
-
-  /** Returns the keys of all bindings declared by this module. */
-  ImmutableSet<Key> allBindingKeys() {
-    return allBindingDeclarations().stream().map(BindingDeclaration::key).collect(toImmutableSet());
-  }
-
-  /** A {@link ModuleDescriptor} factory. */
-  @Singleton
-  public static final class Factory implements ClearableCache {
-    private final DaggerElements elements;
-    private final KotlinMetadataUtil metadataUtil;
-    private final BindingFactory bindingFactory;
-    private final MultibindingDeclaration.Factory multibindingDeclarationFactory;
-    private final DelegateDeclaration.Factory bindingDelegateDeclarationFactory;
-    private final SubcomponentDeclaration.Factory subcomponentDeclarationFactory;
-    private final OptionalBindingDeclaration.Factory optionalBindingDeclarationFactory;
-    private final Map<TypeElement, ModuleDescriptor> cache = new HashMap<>();
-
-    @Inject
-    Factory(
-        DaggerElements elements,
-        KotlinMetadataUtil metadataUtil,
-        BindingFactory bindingFactory,
-        MultibindingDeclaration.Factory multibindingDeclarationFactory,
-        DelegateDeclaration.Factory bindingDelegateDeclarationFactory,
-        SubcomponentDeclaration.Factory subcomponentDeclarationFactory,
-        OptionalBindingDeclaration.Factory optionalBindingDeclarationFactory) {
-      this.elements = elements;
-      this.metadataUtil = metadataUtil;
-      this.bindingFactory = bindingFactory;
-      this.multibindingDeclarationFactory = multibindingDeclarationFactory;
-      this.bindingDelegateDeclarationFactory = bindingDelegateDeclarationFactory;
-      this.subcomponentDeclarationFactory = subcomponentDeclarationFactory;
-      this.optionalBindingDeclarationFactory = optionalBindingDeclarationFactory;
-    }
-
-    public ModuleDescriptor create(TypeElement moduleElement) {
-      return reentrantComputeIfAbsent(cache, moduleElement, this::createUncached);
-    }
-
-    public ModuleDescriptor createUncached(TypeElement moduleElement) {
-      ImmutableSet.Builder<ContributionBinding> bindings = ImmutableSet.builder();
-      ImmutableSet.Builder<DelegateDeclaration> delegates = ImmutableSet.builder();
-      ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations =
-          ImmutableSet.builder();
-      ImmutableSet.Builder<OptionalBindingDeclaration> optionalDeclarations =
-          ImmutableSet.builder();
-
-      for (ExecutableElement moduleMethod : methodsIn(elements.getAllMembers(moduleElement))) {
-        if (isAnnotationPresent(moduleMethod, Provides.class)) {
-          bindings.add(bindingFactory.providesMethodBinding(moduleMethod, moduleElement));
-        }
-        if (isAnnotationPresent(moduleMethod, Produces.class)) {
-          bindings.add(bindingFactory.producesMethodBinding(moduleMethod, moduleElement));
-        }
-        if (isAnnotationPresent(moduleMethod, Binds.class)) {
-          delegates.add(bindingDelegateDeclarationFactory.create(moduleMethod, moduleElement));
-        }
-        if (isAnnotationPresent(moduleMethod, Multibinds.class)) {
-          multibindingDeclarations.add(
-              multibindingDeclarationFactory.forMultibindsMethod(moduleMethod, moduleElement));
-        }
-        if (isAnnotationPresent(moduleMethod, BindsOptionalOf.class)) {
-          optionalDeclarations.add(
-              optionalBindingDeclarationFactory.forMethod(moduleMethod, moduleElement));
-        }
-      }
-
-      if (metadataUtil.hasEnclosedCompanionObject(moduleElement)) {
-        collectCompanionModuleBindings(moduleElement, bindings);
-      }
-
-      return new AutoValue_ModuleDescriptor(
-          moduleElement,
-          ImmutableSet.copyOf(collectIncludedModules(new LinkedHashSet<>(), moduleElement)),
-          bindings.build(),
-          multibindingDeclarations.build(),
-          subcomponentDeclarationFactory.forModule(moduleElement),
-          delegates.build(),
-          optionalDeclarations.build(),
-          ModuleKind.forAnnotatedElement(moduleElement).get());
-    }
-
-    private void collectCompanionModuleBindings(
-        TypeElement moduleElement, ImmutableSet.Builder<ContributionBinding> bindings) {
-      checkArgument(metadataUtil.hasEnclosedCompanionObject(moduleElement));
-      TypeElement companionModule = metadataUtil.getEnclosedCompanionObject(moduleElement);
-      ImmutableSet<String> bindingElementDescriptors =
-          bindings.build().stream()
-              .map(binding -> getMethodDescriptor(asExecutable(binding.bindingElement().get())))
-              .collect(toImmutableSet());
-      methodsIn(elements.getAllMembers(companionModule)).stream()
-          // Binding methods in companion objects with @JvmStatic are mirrored in the enclosing
-          // class, therefore we should ignore it or else it'll be a duplicate binding.
-          .filter(method -> !KotlinMetadataUtil.isJvmStaticPresent(method))
-          // Fallback strategy for de-duping contributing bindings in the companion module with
-          // @JvmStatic by comparing descriptors. Contributing bindings are the only valid bindings
-          // a companion module can declare. See: https://youtrack.jetbrains.com/issue/KT-35104
-          // TODO(danysantiago): Checks qualifiers too.
-          .filter(method -> !bindingElementDescriptors.contains(getMethodDescriptor(method)))
-          .forEach(
-              method -> {
-                if (isAnnotationPresent(method, Provides.class)) {
-                  bindings.add(bindingFactory.providesMethodBinding(method, companionModule));
-                }
-                if (isAnnotationPresent(method, Produces.class)) {
-                  bindings.add(bindingFactory.producesMethodBinding(method, companionModule));
-                }
-              });
-    }
-
-    /** Returns all the modules transitively included by given modules, including the arguments. */
-    ImmutableSet<ModuleDescriptor> transitiveModules(Iterable<TypeElement> modules) {
-      return ImmutableSet.copyOf(
-          Traverser.forGraph(
-                  (ModuleDescriptor module) -> transform(module.includedModules(), this::create))
-              .depthFirstPreOrder(transform(modules, this::create)));
-    }
-
-    @CanIgnoreReturnValue
-    private Set<TypeElement> collectIncludedModules(
-        Set<TypeElement> includedModules, TypeElement moduleElement) {
-      TypeMirror superclass = moduleElement.getSuperclass();
-      if (!superclass.getKind().equals(NONE)) {
-        verify(superclass.getKind().equals(DECLARED));
-        TypeElement superclassElement = MoreTypes.asTypeElement(superclass);
-        if (!superclassElement.getQualifiedName().contentEquals(Object.class.getCanonicalName())) {
-          collectIncludedModules(includedModules, superclassElement);
-        }
-      }
-      moduleAnnotation(moduleElement)
-          .ifPresent(
-              moduleAnnotation -> {
-                includedModules.addAll(moduleAnnotation.includes());
-                includedModules.addAll(implicitlyIncludedModules(moduleElement));
-              });
-      return includedModules;
-    }
-
-    // @ContributesAndroidInjector generates a module that is implicitly included in the enclosing
-    // module
-    private ImmutableSet<TypeElement> implicitlyIncludedModules(TypeElement moduleElement) {
-      TypeElement contributesAndroidInjector =
-          elements.getTypeElement("dagger.android.ContributesAndroidInjector");
-      if (contributesAndroidInjector == null) {
-        return ImmutableSet.of();
-      }
-      return methodsIn(moduleElement.getEnclosedElements()).stream()
-          .filter(method -> isAnnotationPresent(method, contributesAndroidInjector.asType()))
-          .map(method -> elements.checkTypePresent(implicitlyIncludedModuleName(method)))
-          .collect(toImmutableSet());
-    }
-
-    private String implicitlyIncludedModuleName(ExecutableElement method) {
-      return getPackage(method).getQualifiedName()
-          + "."
-          + classFileName(ClassName.get(MoreElements.asType(method.getEnclosingElement())))
-          + "_"
-          + LOWER_CAMEL.to(UPPER_CAMEL, method.getSimpleName().toString());
-    }
-
-    @Override
-    public void clearCache() {
-      cache.clear();
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ModuleKind.java b/java/dagger/internal/codegen/binding/ModuleKind.java
deleted file mode 100644
index 6b52f04..0000000
--- a/java/dagger/internal/codegen/binding/ModuleKind.java
+++ /dev/null
@@ -1,115 +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.binding;
-
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-import dagger.Module;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.producers.ProducerModule;
-import java.lang.annotation.Annotation;
-import java.util.EnumSet;
-import java.util.Optional;
-import java.util.Set;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.TypeElement;
-
-/** Enumeration of the kinds of modules. */
-public enum ModuleKind {
-  /** {@code @Module} */
-  MODULE(Module.class),
-
-  /** {@code @ProducerModule} */
-  PRODUCER_MODULE(ProducerModule.class);
-
-  /** Returns the annotations for modules of the given kinds. */
-  public static ImmutableSet<Class<? extends Annotation>> annotationsFor(Set<ModuleKind> kinds) {
-    return kinds.stream().map(ModuleKind::annotation).collect(toImmutableSet());
-  }
-
-  /**
-   * Returns the kind of an annotated element if it is annotated with one of the module {@linkplain
-   * #annotation() annotations}.
-   *
-   * @throws IllegalArgumentException if the element is annotated with more than one of the module
-   *     annotations
-   */
-  public static Optional<ModuleKind> forAnnotatedElement(TypeElement element) {
-    Set<ModuleKind> kinds = EnumSet.noneOf(ModuleKind.class);
-    for (ModuleKind kind : values()) {
-      if (MoreElements.isAnnotationPresent(element, kind.annotation())) {
-        kinds.add(kind);
-      }
-    }
-
-    if (kinds.size() > 1) {
-      throw new IllegalArgumentException(
-          element + " cannot be annotated with more than one of " + annotationsFor(kinds));
-    }
-    return kinds.stream().findAny();
-  }
-
-  public static void checkIsModule(TypeElement moduleElement, KotlinMetadataUtil metadataUtil) {
-    // If the type element is a Kotlin companion object, then assert it is a module if its enclosing
-    // type is a module.
-    if (metadataUtil.isCompanionObjectClass(moduleElement)) {
-      checkArgument(forAnnotatedElement(asType(moduleElement.getEnclosingElement())).isPresent());
-    } else {
-      checkArgument(forAnnotatedElement(moduleElement).isPresent());
-    }
-  }
-
-  private final Class<? extends Annotation> moduleAnnotation;
-
-  ModuleKind(Class<? extends Annotation> moduleAnnotation) {
-    this.moduleAnnotation = moduleAnnotation;
-  }
-
-  /**
-   * Returns the annotation mirror for this module kind on the given type.
-   *
-   * @throws IllegalArgumentException if the annotation is not present on the type
-   */
-  public AnnotationMirror getModuleAnnotation(TypeElement element) {
-    Optional<AnnotationMirror> result = getAnnotationMirror(element, moduleAnnotation);
-    checkArgument(
-        result.isPresent(), "annotation %s is not present on type %s", moduleAnnotation, element);
-    return result.get();
-  }
-
-  /** Returns the annotation that marks a module of this kind. */
-  public Class<? extends Annotation> annotation() {
-    return moduleAnnotation;
-  }
-
-  /** Returns the kinds of modules that a module of this kind is allowed to include. */
-  public ImmutableSet<ModuleKind> legalIncludedModuleKinds() {
-    switch (this) {
-      case MODULE:
-        return Sets.immutableEnumSet(MODULE);
-      case PRODUCER_MODULE:
-        return Sets.immutableEnumSet(MODULE, PRODUCER_MODULE);
-    }
-    throw new AssertionError(this);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/MultibindingDeclaration.java b/java/dagger/internal/codegen/binding/MultibindingDeclaration.java
deleted file mode 100644
index f1d3f8d..0000000
--- a/java/dagger/internal/codegen/binding/MultibindingDeclaration.java
+++ /dev/null
@@ -1,120 +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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.ContributionType.HasContributionType;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-import dagger.multibindings.Multibinds;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A declaration that a multibinding with a certain key is available to be injected in a component
- * even if the component has no multibindings for that key. Identified by a map- or set-returning
- * method annotated with {@link Multibinds @Multibinds}.
- */
-@AutoValue
-public abstract class MultibindingDeclaration extends BindingDeclaration
-    implements HasContributionType {
-
-  /**
-   * The map or set key whose availability is declared. For maps, this will be {@code Map<K,
-   * Provider<V>>}. For sets, this will be {@code Set<T>}.
-   */
-  @Override
-  public abstract Key key();
-
-  /**
-   * {@link ContributionType#SET} if the declared type is a {@link Set}, or
-   * {@link ContributionType#MAP} if it is a {@link Map}.
-   */
-  @Override
-  public abstract ContributionType contributionType();
-
-  @Memoized
-  @Override
-  public abstract int hashCode();
-
-  @Override
-  public abstract boolean equals(Object obj);
-
-  /** A factory for {@link MultibindingDeclaration}s. */
-  public static final class Factory {
-    private final DaggerTypes types;
-    private final KeyFactory keyFactory;
-
-    @Inject
-    Factory(DaggerTypes types, KeyFactory keyFactory) {
-      this.types = types;
-      this.keyFactory = keyFactory;
-    }
-
-    /** A multibinding declaration for a {@link Multibinds @Multibinds} method. */
-    MultibindingDeclaration forMultibindsMethod(
-        ExecutableElement moduleMethod, TypeElement moduleElement) {
-      checkArgument(isAnnotationPresent(moduleMethod, Multibinds.class));
-      return forDeclaredMethod(
-          moduleMethod,
-          MoreTypes.asExecutable(
-              types.asMemberOf(MoreTypes.asDeclared(moduleElement.asType()), moduleMethod)),
-          moduleElement);
-    }
-
-    private MultibindingDeclaration forDeclaredMethod(
-        ExecutableElement method,
-        ExecutableType methodType,
-        TypeElement contributingType) {
-      TypeMirror returnType = methodType.getReturnType();
-      checkArgument(
-          SetType.isSet(returnType) || MapType.isMap(returnType),
-          "%s must return a set or map",
-          method);
-      return new AutoValue_MultibindingDeclaration(
-          Optional.<Element>of(method),
-          Optional.of(contributingType),
-          keyFactory.forMultibindsMethod(methodType, method),
-          contributionType(returnType));
-    }
-
-    private ContributionType contributionType(TypeMirror returnType) {
-      if (MapType.isMap(returnType)) {
-        return ContributionType.MAP;
-      } else if (SetType.isSet(returnType)) {
-        return ContributionType.SET;
-      } else {
-        throw new IllegalArgumentException("Must be Map or Set: " + returnType);
-      }
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/OptionalBindingDeclaration.java b/java/dagger/internal/codegen/binding/OptionalBindingDeclaration.java
deleted file mode 100644
index d7ba7bc..0000000
--- a/java/dagger/internal/codegen/binding/OptionalBindingDeclaration.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 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.binding;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import dagger.BindsOptionalOf;
-import dagger.model.Key;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-
-/** A {@link BindsOptionalOf} declaration. */
-@AutoValue
-abstract class OptionalBindingDeclaration extends BindingDeclaration {
-
-  /**
-   * {@inheritDoc}
-   *
-   * <p>The key's type is the method's return type, even though the synthetic bindings will be for
-   * {@code Optional} of derived types.
-   */
-  @Override
-  public abstract Key key();
-
-  @Memoized
-  @Override
-  public abstract int hashCode();
-
-  @Override
-  public abstract boolean equals(Object obj);
-
-  static class Factory {
-    private final KeyFactory keyFactory;
-
-    @Inject
-    Factory(KeyFactory keyFactory) {
-      this.keyFactory = keyFactory;
-    }
-
-    OptionalBindingDeclaration forMethod(ExecutableElement method, TypeElement contributingModule) {
-      checkArgument(isAnnotationPresent(method, BindsOptionalOf.class));
-      return new AutoValue_OptionalBindingDeclaration(
-          Optional.<Element>of(method),
-          Optional.of(contributingModule),
-          keyFactory.forBindsOptionalOfMethod(method, contributingModule));
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ProductionBinding.java b/java/dagger/internal/codegen/binding/ProductionBinding.java
deleted file mode 100644
index ad85a68..0000000
--- a/java/dagger/internal/codegen/binding/ProductionBinding.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.SetType;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import java.util.Optional;
-import java.util.stream.Stream;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.TypeMirror;
-
-/** A value object representing the mechanism by which a {@link Key} can be produced. */
-@AutoValue
-public abstract class ProductionBinding extends ContributionBinding {
-
-  @Override
-  public BindingType bindingType() {
-    return BindingType.PRODUCTION;
-  }
-
-  @Override
-  public abstract Optional<ProductionBinding> unresolved();
-
-  @Override
-  public ImmutableSet<DependencyRequest> implicitDependencies() {
-    return Stream.of(executorRequest(), monitorRequest())
-        .filter(Optional::isPresent)
-        .map(Optional::get)
-        .collect(toImmutableSet());
-  }
-
-  /** What kind of object a {@code @Produces}-annotated method returns. */
-  public enum ProductionKind {
-    /** A value. */
-    IMMEDIATE,
-    /** A {@code ListenableFuture<T>}. */
-    FUTURE,
-    /** A {@code Set<ListenableFuture<T>>}. */
-    SET_OF_FUTURE;
-
-    /** Returns the kind of object a {@code @Produces}-annotated method returns. */
-    public static ProductionKind fromProducesMethod(ExecutableElement producesMethod) {
-      if (isFutureType(producesMethod.getReturnType())) {
-        return FUTURE;
-      } else if (ContributionType.fromBindingElement(producesMethod)
-              .equals(ContributionType.SET_VALUES)
-          && isFutureType(SetType.from(producesMethod.getReturnType()).elementType())) {
-        return SET_OF_FUTURE;
-      } else {
-        return IMMEDIATE;
-      }
-    }
-  }
-
-  /**
-   * Returns the kind of object the produces method returns. All production bindings from
-   * {@code @Produces} methods will have a production kind, but synthetic production bindings may
-   * not.
-   */
-  public abstract Optional<ProductionKind> productionKind();
-
-  /** Returns the list of types in the throws clause of the method. */
-  public abstract ImmutableList<? extends TypeMirror> thrownTypes();
-
-  /**
-   * If this production requires an executor, this will be the corresponding request.  All
-   * production bindings from {@code @Produces} methods will have an executor request, but
-   * synthetic production bindings may not.
-   */
-  abstract Optional<DependencyRequest> executorRequest();
-
-  /** If this production requires a monitor, this will be the corresponding request.  All
-   * production bindings from {@code @Produces} methods will have a monitor request, but synthetic
-   * production bindings may not.
-   */
-  abstract Optional<DependencyRequest> monitorRequest();
-
-  // Profiling determined that this method is called enough times that memoizing it had a measurable
-  // performance improvement for large components.
-  @Memoized
-  @Override
-  public boolean requiresModuleInstance() {
-    return super.requiresModuleInstance();
-  }
-
-  public static Builder builder() {
-    return new AutoValue_ProductionBinding.Builder()
-        .explicitDependencies(ImmutableList.<DependencyRequest>of())
-        .thrownTypes(ImmutableList.<TypeMirror>of());
-  }
-
-  @Override
-  public abstract Builder toBuilder();
-
-  @Memoized
-  @Override
-  public abstract int hashCode();
-
-  // TODO(ronshapiro,dpb): simplify the equality semantics
-  @Override
-  public abstract boolean equals(Object obj);
-
-  /** A {@link ProductionBinding} builder. */
-  @AutoValue.Builder
-  @CanIgnoreReturnValue
-  public abstract static class Builder
-      extends ContributionBinding.Builder<ProductionBinding, Builder> {
-
-    @Override
-    public Builder dependencies(Iterable<DependencyRequest> dependencies) {
-      return explicitDependencies(dependencies);
-    }
-
-    abstract Builder explicitDependencies(Iterable<DependencyRequest> dependencies);
-
-    abstract Builder productionKind(ProductionKind productionKind);
-
-    @Override
-    public abstract Builder unresolved(ProductionBinding unresolved);
-
-    abstract Builder thrownTypes(Iterable<? extends TypeMirror> thrownTypes);
-
-    abstract Builder executorRequest(DependencyRequest executorRequest);
-
-    abstract Builder monitorRequest(DependencyRequest monitorRequest);
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ProvisionBinding.java b/java/dagger/internal/codegen/binding/ProvisionBinding.java
deleted file mode 100644
index c917dd6..0000000
--- a/java/dagger/internal/codegen/binding/ProvisionBinding.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.model.BindingKind.COMPONENT_PROVISION;
-import static dagger.model.BindingKind.PROVISION;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import dagger.internal.codegen.binding.MembersInjectionBinding.InjectionSite;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.model.BindingKind;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.model.Scope;
-import java.util.Optional;
-
-/** A value object representing the mechanism by which a {@link Key} can be provided. */
-@AutoValue
-public abstract class ProvisionBinding extends ContributionBinding {
-
-  @Override
-  @Memoized
-  public ImmutableSet<DependencyRequest> explicitDependencies() {
-    return ImmutableSet.<DependencyRequest>builder()
-        .addAll(provisionDependencies())
-        .addAll(membersInjectionDependencies())
-        .build();
-  }
-
-  /**
-   * Dependencies necessary to invoke an {@code @Inject} constructor or {@code @Provides} method.
-   */
-  public abstract ImmutableSet<DependencyRequest> provisionDependencies();
-
-  @Memoized
-  ImmutableSet<DependencyRequest> membersInjectionDependencies() {
-    return injectionSites()
-        .stream()
-        .flatMap(i -> i.dependencies().stream())
-        .collect(toImmutableSet());
-  }
-
-  /**
-   * {@link InjectionSite}s for all {@code @Inject} members if {@link #kind()} is {@link
-   * BindingKind#INJECTION}, otherwise empty.
-   */
-  public abstract ImmutableSortedSet<InjectionSite> injectionSites();
-
-  @Override
-  public BindingType bindingType() {
-    return BindingType.PROVISION;
-  }
-
-  @Override
-  public abstract Optional<ProvisionBinding> unresolved();
-
-  // TODO(ronshapiro): we should be able to remove this, but AutoValue barks on the Builder's scope
-  // method, saying that the method doesn't correspond to a property of ProvisionBinding
-  @Override
-  public abstract Optional<Scope> scope();
-
-  public static Builder builder() {
-    return new AutoValue_ProvisionBinding.Builder()
-        .provisionDependencies(ImmutableSet.of())
-        .injectionSites(ImmutableSortedSet.of());
-  }
-
-  @Override
-  public abstract Builder toBuilder();
-
-  private static final ImmutableSet<BindingKind> KINDS_TO_CHECK_FOR_NULL =
-      ImmutableSet.of(PROVISION, COMPONENT_PROVISION);
-
-  public boolean shouldCheckForNull(CompilerOptions compilerOptions) {
-    return KINDS_TO_CHECK_FOR_NULL.contains(kind())
-        && !contributedPrimitiveType().isPresent()
-        && !nullableType().isPresent()
-        && compilerOptions.doCheckForNulls();
-  }
-
-  // Profiling determined that this method is called enough times that memoizing it had a measurable
-  // performance improvement for large components.
-  @Memoized
-  @Override
-  public boolean requiresModuleInstance() {
-    return super.requiresModuleInstance();
-  }
-
-  @Memoized
-  @Override
-  public abstract int hashCode();
-
-  // TODO(ronshapiro,dpb): simplify the equality semantics
-  @Override
-  public abstract boolean equals(Object obj);
-
-  /** A {@link ProvisionBinding} builder. */
-  @AutoValue.Builder
-  @CanIgnoreReturnValue
-  public abstract static class Builder
-      extends ContributionBinding.Builder<ProvisionBinding, Builder> {
-
-    @Override
-    public Builder dependencies(Iterable<DependencyRequest> dependencies) {
-      return provisionDependencies(dependencies);
-    }
-
-    abstract Builder provisionDependencies(Iterable<DependencyRequest> provisionDependencies);
-
-    public abstract Builder injectionSites(ImmutableSortedSet<InjectionSite> injectionSites);
-
-    @Override
-    public abstract Builder unresolved(ProvisionBinding unresolved);
-
-    public abstract Builder scope(Optional<Scope> scope);
-  }
-
-}
diff --git a/java/dagger/internal/codegen/binding/ResolvedBindings.java b/java/dagger/internal/codegen/binding/ResolvedBindings.java
deleted file mode 100644
index 74301fe..0000000
--- a/java/dagger/internal/codegen/binding/ResolvedBindings.java
+++ /dev/null
@@ -1,172 +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.binding;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Multimap;
-import dagger.model.Key;
-import javax.lang.model.element.TypeElement;
-
-/**
- * The collection of bindings that have been resolved for a key. For valid graphs, contains exactly
- * one binding.
- *
- * <p>Separate {@link ResolvedBindings} instances should be used if a {@link
- * MembersInjectionBinding} and a {@link ProvisionBinding} for the same key exist in the same
- * component. (This will only happen if a type has an {@code @Inject} constructor and members, the
- * component has a members injection method, and the type is also requested normally.)
- */
-@AutoValue
-abstract class ResolvedBindings {
-  /** The binding key for which the {@link #bindings()} have been resolved. */
-  abstract Key key();
-
-  /**
-   * The {@link ContributionBinding}s for {@link #key()} indexed by the component that owns the
-   * binding. Each key in the multimap is a part of the same component ancestry.
-   */
-  abstract ImmutableSetMultimap<TypeElement, ContributionBinding> allContributionBindings();
-
-  /**
-   * The {@link MembersInjectionBinding}s for {@link #key()} indexed by the component that owns the
-   * binding.  Each key in the map is a part of the same component ancestry.
-   */
-  abstract ImmutableMap<TypeElement, MembersInjectionBinding> allMembersInjectionBindings();
-
-  /** The multibinding declarations for {@link #key()}. */
-  abstract ImmutableSet<MultibindingDeclaration> multibindingDeclarations();
-
-  /** The subcomponent declarations for {@link #key()}. */
-  abstract ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations();
-
-  /** The optional binding declarations for {@link #key()}. */
-  abstract ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations();
-
-  // Computing the hash code is an expensive operation.
-  @Memoized
-  @Override
-  public abstract int hashCode();
-
-  // Suppresses ErrorProne warning that hashCode was overridden w/o equals
-  @Override
-  public abstract boolean equals(Object other);
-
-  /** All bindings for {@link #key()}, indexed by the component that owns the binding. */
-  final ImmutableSetMultimap<TypeElement, ? extends Binding> allBindings() {
-    return !allMembersInjectionBindings().isEmpty()
-        ? allMembersInjectionBindings().asMultimap()
-        : allContributionBindings();
-  }
-
-  /** All bindings for {@link #key()}, regardless of which component owns them. */
-  final ImmutableCollection<? extends Binding> bindings() {
-    return allBindings().values();
-  }
-
-  /**
-   * {@code true} if there are no {@link #bindings()}, {@link #multibindingDeclarations()}, {@link
-   * #optionalBindingDeclarations()}, or {@link #subcomponentDeclarations()}.
-   */
-  final boolean isEmpty() {
-    return allMembersInjectionBindings().isEmpty()
-        && allContributionBindings().isEmpty()
-        && multibindingDeclarations().isEmpty()
-        && optionalBindingDeclarations().isEmpty()
-        && subcomponentDeclarations().isEmpty();
-  }
-
-  /** All bindings for {@link #key()} that are owned by a component. */
-  ImmutableSet<? extends Binding> bindingsOwnedBy(ComponentDescriptor component) {
-    return allBindings().get(component.typeElement());
-  }
-
-  /**
-   * All contribution bindings, regardless of owning component. Empty if this is a members-injection
-   * binding.
-   */
-  @Memoized
-  ImmutableSet<ContributionBinding> contributionBindings() {
-    // TODO(ronshapiro): consider optimizing ImmutableSet.copyOf(Collection) for small immutable
-    // collections so that it doesn't need to call toArray(). Even though this method is memoized,
-    // toArray() can take ~150ms for large components, and there are surely other places in the
-    // processor that can benefit from this.
-    return ImmutableSet.copyOf(allContributionBindings().values());
-  }
-
-  /** The component that owns {@code binding}. */
-  final TypeElement owningComponent(ContributionBinding binding) {
-    checkArgument(
-        contributionBindings().contains(binding),
-        "binding is not resolved for %s: %s",
-        key(),
-        binding);
-    return getOnlyElement(allContributionBindings().inverse().get(binding));
-  }
-
-  /** Creates a {@link ResolvedBindings} for contribution bindings. */
-  static ResolvedBindings forContributionBindings(
-      Key key,
-      Multimap<TypeElement, ContributionBinding> contributionBindings,
-      Iterable<MultibindingDeclaration> multibindings,
-      Iterable<SubcomponentDeclaration> subcomponentDeclarations,
-      Iterable<OptionalBindingDeclaration> optionalBindingDeclarations) {
-    return new AutoValue_ResolvedBindings(
-        key,
-        ImmutableSetMultimap.copyOf(contributionBindings),
-        ImmutableMap.of(),
-        ImmutableSet.copyOf(multibindings),
-        ImmutableSet.copyOf(subcomponentDeclarations),
-        ImmutableSet.copyOf(optionalBindingDeclarations));
-  }
-
-  /**
-   * Creates a {@link ResolvedBindings} for members injection bindings.
-   */
-  static ResolvedBindings forMembersInjectionBinding(
-      Key key,
-      ComponentDescriptor owningComponent,
-      MembersInjectionBinding ownedMembersInjectionBinding) {
-    return new AutoValue_ResolvedBindings(
-        key,
-        ImmutableSetMultimap.of(),
-        ImmutableMap.of(owningComponent.typeElement(), ownedMembersInjectionBinding),
-        ImmutableSet.of(),
-        ImmutableSet.of(),
-        ImmutableSet.of());
-  }
-
-  /**
-   * Creates a {@link ResolvedBindings} appropriate for when there are no bindings for the key.
-   */
-  static ResolvedBindings noBindings(Key key) {
-    return new AutoValue_ResolvedBindings(
-        key,
-        ImmutableSetMultimap.of(),
-        ImmutableMap.of(),
-        ImmutableSet.of(),
-        ImmutableSet.of(),
-        ImmutableSet.of());
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/SourceFiles.java b/java/dagger/internal/codegen/binding/SourceFiles.java
deleted file mode 100644
index 3b6d9d9..0000000
--- a/java/dagger/internal/codegen/binding/SourceFiles.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Verify.verify;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.javapoet.TypeNames.DOUBLE_CHECK;
-import static dagger.internal.codegen.javapoet.TypeNames.MAP_FACTORY;
-import static dagger.internal.codegen.javapoet.TypeNames.MAP_OF_PRODUCED_PRODUCER;
-import static dagger.internal.codegen.javapoet.TypeNames.MAP_OF_PRODUCER_PRODUCER;
-import static dagger.internal.codegen.javapoet.TypeNames.MAP_PRODUCER;
-import static dagger.internal.codegen.javapoet.TypeNames.MAP_PROVIDER_FACTORY;
-import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER_OF_LAZY;
-import static dagger.internal.codegen.javapoet.TypeNames.SET_FACTORY;
-import static dagger.internal.codegen.javapoet.TypeNames.SET_OF_PRODUCED_PRODUCER;
-import static dagger.internal.codegen.javapoet.TypeNames.SET_PRODUCER;
-import static dagger.model.BindingKind.ASSISTED_INJECTION;
-import static dagger.model.BindingKind.INJECTION;
-import static dagger.model.BindingKind.MULTIBOUND_MAP;
-import static dagger.model.BindingKind.MULTIBOUND_SET;
-import static javax.lang.model.SourceVersion.isName;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.internal.SetFactory;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.SetType;
-import dagger.model.DependencyRequest;
-import dagger.model.RequestKind;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import dagger.producers.internal.SetOfProducedProducer;
-import dagger.producers.internal.SetProducer;
-import java.util.List;
-import javax.inject.Provider;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.TypeParameterElement;
-import javax.lang.model.element.VariableElement;
-
-/** Utilities for generating files. */
-public class SourceFiles {
-
-  private static final Joiner CLASS_FILE_NAME_JOINER = Joiner.on('_');
-
-  /**
-   * Generates names and keys for the factory class fields needed to hold the framework classes for
-   * all of the dependencies of {@code binding}. It is responsible for choosing a name that
-   *
-   * <ul>
-   *   <li>represents all of the dependency requests for this key
-   *   <li>is <i>probably</i> associated with the type being bound
-   *   <li>is unique within the class
-   * </ul>
-   *
-   * @param binding must be an unresolved binding (type parameters must match its type element's)
-   */
-  public static ImmutableMap<DependencyRequest, FrameworkField>
-      generateBindingFieldsForDependencies(Binding binding) {
-    checkArgument(!binding.unresolved().isPresent(), "binding must be unresolved: %s", binding);
-
-    FrameworkTypeMapper frameworkTypeMapper =
-        FrameworkTypeMapper.forBindingType(binding.bindingType());
-
-    return Maps.toMap(
-        binding.dependencies(),
-        dependency ->
-            FrameworkField.create(
-                ClassName.get(
-                    frameworkTypeMapper.getFrameworkType(dependency.kind()).frameworkClass()),
-                TypeName.get(dependency.key().type()),
-                DependencyVariableNamer.name(dependency)));
-  }
-
-  public static CodeBlock frameworkTypeUsageStatement(
-      CodeBlock frameworkTypeMemberSelect, RequestKind dependencyKind) {
-    switch (dependencyKind) {
-      case LAZY:
-        return CodeBlock.of("$T.lazy($L)", DOUBLE_CHECK, frameworkTypeMemberSelect);
-      case INSTANCE:
-      case FUTURE:
-        return CodeBlock.of("$L.get()", frameworkTypeMemberSelect);
-      case PROVIDER:
-      case PRODUCER:
-        return frameworkTypeMemberSelect;
-      case PROVIDER_OF_LAZY:
-        return CodeBlock.of("$T.create($L)", PROVIDER_OF_LAZY, frameworkTypeMemberSelect);
-      default: // including PRODUCED
-        throw new AssertionError(dependencyKind);
-    }
-  }
-
-  /**
-   * Returns a mapping of {@link DependencyRequest}s to {@link CodeBlock}s that {@linkplain
-   * #frameworkTypeUsageStatement(CodeBlock, RequestKind) use them}.
-   */
-  public static ImmutableMap<DependencyRequest, CodeBlock> frameworkFieldUsages(
-      ImmutableSet<DependencyRequest> dependencies,
-      ImmutableMap<DependencyRequest, FieldSpec> fields) {
-    return Maps.toMap(
-        dependencies,
-        dep -> frameworkTypeUsageStatement(CodeBlock.of("$N", fields.get(dep)), dep.kind()));
-  }
-
-  /** Returns the generated factory or members injector name for a binding. */
-  public static ClassName generatedClassNameForBinding(Binding binding) {
-    switch (binding.bindingType()) {
-      case PROVISION:
-      case PRODUCTION:
-        ContributionBinding contribution = (ContributionBinding) binding;
-        switch (contribution.kind()) {
-          case ASSISTED_INJECTION:
-          case INJECTION:
-          case PROVISION:
-          case PRODUCTION:
-            return elementBasedClassName(
-                MoreElements.asExecutable(binding.bindingElement().get()), "Factory");
-
-          case ASSISTED_FACTORY:
-            return siblingClassName(MoreElements.asType(binding.bindingElement().get()), "_Impl");
-
-          default:
-            throw new AssertionError();
-        }
-
-      case MEMBERS_INJECTION:
-        return membersInjectorNameForType(
-            ((MembersInjectionBinding) binding).membersInjectedType());
-    }
-    throw new AssertionError();
-  }
-
-  /**
-   * Calculates an appropriate {@link ClassName} for a generated class that is based on {@code
-   * element}, appending {@code suffix} at the end.
-   *
-   * <p>This will always return a {@linkplain ClassName#topLevelClassName() top level class name},
-   * even if {@code element}'s enclosing class is a nested type.
-   */
-  public static ClassName elementBasedClassName(ExecutableElement element, String suffix) {
-    ClassName enclosingClassName =
-        ClassName.get(MoreElements.asType(element.getEnclosingElement()));
-    String methodName =
-        element.getKind().equals(ElementKind.CONSTRUCTOR)
-            ? ""
-            : LOWER_CAMEL.to(UPPER_CAMEL, element.getSimpleName().toString());
-    return ClassName.get(
-        enclosingClassName.packageName(),
-        classFileName(enclosingClassName) + "_" + methodName + suffix);
-  }
-
-  public static TypeName parameterizedGeneratedTypeNameForBinding(Binding binding) {
-    ClassName className = generatedClassNameForBinding(binding);
-    ImmutableList<TypeVariableName> typeParameters = bindingTypeElementTypeVariableNames(binding);
-    return typeParameters.isEmpty()
-        ? className
-        : ParameterizedTypeName.get(className, Iterables.toArray(typeParameters, TypeName.class));
-  }
-
-  public static ClassName membersInjectorNameForType(TypeElement typeElement) {
-    return siblingClassName(typeElement,  "_MembersInjector");
-  }
-
-  public static String memberInjectedFieldSignatureForVariable(VariableElement variableElement) {
-    return MoreElements.asType(variableElement.getEnclosingElement()).getQualifiedName()
-        + "."
-        + variableElement.getSimpleName();
-  }
-
-  public static String classFileName(ClassName className) {
-    return CLASS_FILE_NAME_JOINER.join(className.simpleNames());
-  }
-
-  public static ClassName generatedMonitoringModuleName(TypeElement componentElement) {
-    return siblingClassName(componentElement, "_MonitoringModule");
-  }
-
-  // TODO(ronshapiro): when JavaPoet migration is complete, replace the duplicated code
-  // which could use this.
-  private static ClassName siblingClassName(TypeElement typeElement, String suffix) {
-    ClassName className = ClassName.get(typeElement);
-    return className.topLevelClassName().peerClass(classFileName(className) + suffix);
-  }
-
-  /**
-   * The {@link java.util.Set} factory class name appropriate for set bindings.
-   *
-   * <ul>
-   *   <li>{@link SetFactory} for provision bindings.
-   *   <li>{@link SetProducer} for production bindings for {@code Set<T>}.
-   *   <li>{@link SetOfProducedProducer} for production bindings for {@code Set<Produced<T>>}.
-   * </ul>
-   */
-  public static ClassName setFactoryClassName(ContributionBinding binding) {
-    checkArgument(binding.kind().equals(MULTIBOUND_SET));
-    if (binding.bindingType().equals(BindingType.PROVISION)) {
-      return SET_FACTORY;
-    } else {
-      SetType setType = SetType.from(binding.key());
-      return setType.elementsAreTypeOf(Produced.class) ? SET_OF_PRODUCED_PRODUCER : SET_PRODUCER;
-    }
-  }
-
-  /** The {@link java.util.Map} factory class name appropriate for map bindings. */
-  public static ClassName mapFactoryClassName(ContributionBinding binding) {
-    checkState(binding.kind().equals(MULTIBOUND_MAP), binding.kind());
-    MapType mapType = MapType.from(binding.key());
-    switch (binding.bindingType()) {
-      case PROVISION:
-        return mapType.valuesAreTypeOf(Provider.class) ? MAP_PROVIDER_FACTORY : MAP_FACTORY;
-      case PRODUCTION:
-        return mapType.valuesAreFrameworkType()
-            ? mapType.valuesAreTypeOf(Producer.class)
-                ? MAP_OF_PRODUCER_PRODUCER
-                : MAP_OF_PRODUCED_PRODUCER
-            : MAP_PRODUCER;
-      default:
-        throw new IllegalArgumentException(binding.bindingType().toString());
-    }
-  }
-
-  public static ImmutableList<TypeVariableName> bindingTypeElementTypeVariableNames(
-      Binding binding) {
-    if (binding instanceof ContributionBinding) {
-      ContributionBinding contributionBinding = (ContributionBinding) binding;
-      if (!(contributionBinding.kind() == INJECTION
-              || contributionBinding.kind() == ASSISTED_INJECTION)
-          && !contributionBinding.requiresModuleInstance()) {
-        return ImmutableList.of();
-      }
-    }
-    List<? extends TypeParameterElement> typeParameters =
-        binding.bindingTypeElement().get().getTypeParameters();
-    return typeParameters.stream().map(TypeVariableName::get).collect(toImmutableList());
-  }
-
-  /**
-   * Returns a name to be used for variables of the given {@linkplain TypeElement type}. Prefer
-   * semantically meaningful variable names, but if none can be derived, this will produce something
-   * readable.
-   */
-  // TODO(gak): maybe this should be a function of TypeMirrors instead of Elements?
-  public static String simpleVariableName(TypeElement typeElement) {
-    String candidateName = UPPER_CAMEL.to(LOWER_CAMEL, typeElement.getSimpleName().toString());
-    String variableName = protectAgainstKeywords(candidateName);
-    verify(isName(variableName), "'%s' was expected to be a valid variable name");
-    return variableName;
-  }
-
-  public static String protectAgainstKeywords(String candidateName) {
-    switch (candidateName) {
-      case "package":
-        return "pkg";
-      case "boolean":
-        return "b";
-      case "double":
-        return "d";
-      case "byte":
-        return "b";
-      case "int":
-        return "i";
-      case "short":
-        return "s";
-      case "char":
-        return "c";
-      case "void":
-        return "v";
-      case "class":
-        return "clazz";
-      case "float":
-        return "f";
-      case "long":
-        return "l";
-      default:
-        return SourceVersion.isKeyword(candidateName) ? candidateName + '_' : candidateName;
-    }
-  }
-
-  private SourceFiles() {}
-}
diff --git a/java/dagger/internal/codegen/binding/SubcomponentCreatorBindingEdgeImpl.java b/java/dagger/internal/codegen/binding/SubcomponentCreatorBindingEdgeImpl.java
deleted file mode 100644
index 93e79b5..0000000
--- a/java/dagger/internal/codegen/binding/SubcomponentCreatorBindingEdgeImpl.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.binding;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.extension.DaggerStreams.presentValues;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static java.util.stream.Collectors.joining;
-
-import com.google.common.collect.ImmutableSet;
-import dagger.model.BindingGraph.SubcomponentCreatorBindingEdge;
-import javax.lang.model.element.TypeElement;
-
-/** An implementation of {@link SubcomponentCreatorBindingEdge}. */
-public final class SubcomponentCreatorBindingEdgeImpl implements SubcomponentCreatorBindingEdge {
-
-  private final ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations;
-
-  SubcomponentCreatorBindingEdgeImpl(
-      ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
-    this.subcomponentDeclarations = subcomponentDeclarations;
-  }
-
-  @Override
-  public ImmutableSet<TypeElement> declaringModules() {
-    return subcomponentDeclarations.stream()
-        .map(SubcomponentDeclaration::contributingModule)
-        .flatMap(presentValues())
-        .collect(toImmutableSet());
-  }
-
-  @Override
-  public String toString() {
-    return "subcomponent declared by "
-        + (subcomponentDeclarations.size() == 1
-            ? getOnlyElement(declaringModules()).getQualifiedName()
-            : declaringModules().stream()
-                .map(TypeElement::getQualifiedName)
-                .collect(joining(", ", "{", "}")));
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/SubcomponentDeclaration.java b/java/dagger/internal/codegen/binding/SubcomponentDeclaration.java
deleted file mode 100644
index 4f1f3ef..0000000
--- a/java/dagger/internal/codegen/binding/SubcomponentDeclaration.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2016 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.binding;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotationElementAndValue;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.getSubcomponentCreator;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.base.ModuleAnnotation;
-import dagger.model.Key;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-/**
- * A declaration for a subcomponent that is included in a module via {@link
- * dagger.Module#subcomponents()}.
- */
-@AutoValue
-public abstract class SubcomponentDeclaration extends BindingDeclaration {
-  /**
-   * Key for the {@link dagger.Subcomponent.Builder} or {@link
-   * dagger.producers.ProductionSubcomponent.Builder} of {@link #subcomponentType()}.
-   */
-  @Override
-  public abstract Key key();
-
-  /**
-   * The type element that defines the {@link dagger.Subcomponent} or {@link
-   * dagger.producers.ProductionSubcomponent} for this declaration.
-   */
-  abstract TypeElement subcomponentType();
-
-  /** The module annotation. */
-  public abstract ModuleAnnotation moduleAnnotation();
-
-  @Memoized
-  @Override
-  public abstract int hashCode();
-
-  @Override
-  public abstract boolean equals(Object obj);
-
-  /** A {@link SubcomponentDeclaration} factory. */
-  public static class Factory {
-    private final KeyFactory keyFactory;
-
-    @Inject
-    Factory(KeyFactory keyFactory) {
-      this.keyFactory = keyFactory;
-    }
-
-    ImmutableSet<SubcomponentDeclaration> forModule(TypeElement module) {
-      ImmutableSet.Builder<SubcomponentDeclaration> declarations = ImmutableSet.builder();
-      ModuleAnnotation moduleAnnotation = ModuleAnnotation.moduleAnnotation(module).get();
-      Element subcomponentAttribute =
-          getAnnotationElementAndValue(moduleAnnotation.annotation(), "subcomponents").getKey();
-      for (TypeElement subcomponent : moduleAnnotation.subcomponents()) {
-        declarations.add(
-            new AutoValue_SubcomponentDeclaration(
-                Optional.of(subcomponentAttribute),
-                Optional.of(module),
-                keyFactory.forSubcomponentCreator(
-                    getSubcomponentCreator(subcomponent).get().asType()),
-                subcomponent,
-                moduleAnnotation));
-      }
-      return declarations.build();
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/BUILD b/java/dagger/internal/codegen/bindinggraphvalidation/BUILD
deleted file mode 100644
index da35b51..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/BUILD
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Classes related to BindingGraph validation.
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "bindinggraphvalidation",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    tags = ["maven:merged"],
-    deps = [
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/codegen/validation",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:graph",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/BindingGraphValidationModule.java b/java/dagger/internal/codegen/bindinggraphvalidation/BindingGraphValidationModule.java
deleted file mode 100644
index a1f1848..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/BindingGraphValidationModule.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import com.google.common.collect.ImmutableSet;
-import dagger.Module;
-import dagger.Provides;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.validation.CompositeBindingGraphPlugin;
-import dagger.internal.codegen.validation.Validation;
-import dagger.spi.BindingGraphPlugin;
-
-/** Binds the set of {@link BindingGraphPlugin}s used to implement Dagger validation. */
-@Module
-public interface BindingGraphValidationModule {
-
-  @Provides
-  @Validation
-  static ImmutableSet<BindingGraphPlugin> providePlugins(
-      CompositeBindingGraphPlugin.Factory factory,
-      CompilerOptions compilerOptions,
-      DependencyCycleValidator validation1,
-      DependsOnProductionExecutorValidator validation2,
-      DuplicateBindingsValidator validation3,
-      IncompatiblyScopedBindingsValidator validation4,
-      InjectBindingValidator validation5,
-      MapMultibindingValidator validation6,
-      MissingBindingValidator validation7,
-      NullableBindingValidator validation8,
-      ProvisionDependencyOnProducerBindingValidator validation9,
-      SubcomponentFactoryMethodValidator validation10) {
-    ImmutableSet<BindingGraphPlugin> plugins = ImmutableSet.of(
-        validation1,
-        validation2,
-        validation3,
-        validation4,
-        validation5,
-        validation6,
-        validation7,
-        validation8,
-        validation9,
-        validation10);
-    if (compilerOptions.experimentalDaggerErrorMessages()) {
-      return ImmutableSet.of(factory.create(plugins, "Dagger/Validation"));
-    } else {
-      return plugins;
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/DependencyCycleValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/DependencyCycleValidator.java
deleted file mode 100644
index bc89ebb..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/DependencyCycleValidator.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getLast;
-import static com.google.common.collect.Iterables.limit;
-import static com.google.common.collect.Iterables.skip;
-import static com.google.common.collect.Sets.newHashSetWithExpectedSize;
-import static dagger.internal.codegen.base.RequestKinds.extractKeyType;
-import static dagger.internal.codegen.base.RequestKinds.getRequestKind;
-import static dagger.internal.codegen.extension.DaggerGraphs.shortestPath;
-import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.graph.EndpointPair;
-import com.google.common.graph.Graphs;
-import com.google.common.graph.ImmutableNetwork;
-import com.google.common.graph.MutableNetwork;
-import com.google.common.graph.NetworkBuilder;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.OptionalType;
-import dagger.internal.codegen.binding.DependencyRequestFormatter;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.ComponentNode;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.BindingGraph.Node;
-import dagger.model.BindingKind;
-import dagger.model.DependencyRequest;
-import dagger.model.RequestKind;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Stream;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.lang.model.type.TypeMirror;
-
-/** Reports errors for dependency cycles. */
-final class DependencyCycleValidator implements BindingGraphPlugin {
-
-  private final DependencyRequestFormatter dependencyRequestFormatter;
-
-  @Inject
-  DependencyCycleValidator(DependencyRequestFormatter dependencyRequestFormatter) {
-    this.dependencyRequestFormatter = dependencyRequestFormatter;
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/DependencyCycle";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    ImmutableNetwork<Node, DependencyEdge> dependencyGraph =
-        nonCycleBreakingDependencyGraph(bindingGraph);
-    // First check the graph for a cycle. If there is one, then we'll do more work to report where.
-    if (!Graphs.hasCycle(dependencyGraph)) {
-      return;
-    }
-    // Check each endpoint pair only once, no matter how many parallel edges connect them.
-    Set<EndpointPair<Node>> dependencyEndpointPairs = dependencyGraph.asGraph().edges();
-    Set<EndpointPair<Node>> visited = newHashSetWithExpectedSize(dependencyEndpointPairs.size());
-    for (EndpointPair<Node> endpointPair : dependencyEndpointPairs) {
-      cycleContainingEndpointPair(endpointPair, dependencyGraph, visited)
-          .ifPresent(cycle -> reportCycle(cycle, bindingGraph, diagnosticReporter));
-    }
-  }
-
-  private Optional<Cycle<Node>> cycleContainingEndpointPair(
-      EndpointPair<Node> endpoints,
-      ImmutableNetwork<Node, DependencyEdge> dependencyGraph,
-      Set<EndpointPair<Node>> visited) {
-    if (!visited.add(endpoints)) {
-      // don't recheck endpoints we already know are part of a cycle
-      return Optional.empty();
-    }
-
-    // If there's a path from the target back to the source, there's a cycle.
-    ImmutableList<Node> cycleNodes =
-        shortestPath(dependencyGraph, endpoints.target(), endpoints.source());
-    if (cycleNodes.isEmpty()) {
-      return Optional.empty();
-    }
-
-    Cycle<Node> cycle = Cycle.fromPath(cycleNodes);
-    visited.addAll(cycle.endpointPairs()); // no need to check any edge in this cycle again
-    return Optional.of(cycle);
-  }
-
-  /**
-   * Reports a dependency cycle at the dependency into the cycle that is closest to an entry point.
-   *
-   * <p>For cycles found in reachable binding graphs, looks for the shortest path from the component
-   * that contains the cycle (all bindings in a cycle must be in the same component; see below) to
-   * some binding in the cycle. Then looks for the last dependency in that path that is not in the
-   * cycle; that is the dependency that will be reported, so that the dependency trace will end just
-   * before the cycle.
-   *
-   * <p>For cycles found during full binding graph validation, just reports the component that
-   * contains the cycle.
-   *
-   * <p>Proof (by counterexample) that all bindings in a cycle must be in the same component: Assume
-   * one binding in the cycle is in a parent component. Bindings cannot depend on bindings in child
-   * components, so that binding cannot depend on the next binding in the cycle.
-   */
-  private void reportCycle(
-      Cycle<Node> cycle, BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    if (bindingGraph.isFullBindingGraph()) {
-      diagnosticReporter.reportComponent(
-          ERROR,
-          bindingGraph.componentNode(cycle.nodes().asList().get(0).componentPath()).get(),
-          errorMessage(cycle, bindingGraph));
-      return;
-    }
-
-    ImmutableList<Node> path = shortestPathToCycleFromAnEntryPoint(cycle, bindingGraph);
-    Node cycleStartNode = path.get(path.size() - 1);
-    Node previousNode = path.get(path.size() - 2);
-    DependencyEdge dependencyToReport =
-        chooseDependencyEdgeConnecting(previousNode, cycleStartNode, bindingGraph);
-    diagnosticReporter.reportDependency(
-        ERROR, dependencyToReport, errorMessage(cycle.shift(cycleStartNode), bindingGraph));
-  }
-
-  private ImmutableList<Node> shortestPathToCycleFromAnEntryPoint(
-      Cycle<Node> cycle, BindingGraph bindingGraph) {
-    Node someCycleNode = cycle.nodes().asList().get(0);
-    ComponentNode componentContainingCycle =
-        bindingGraph.componentNode(someCycleNode.componentPath()).get();
-    ImmutableList<Node> pathToCycle =
-        shortestPath(bindingGraph.network(), componentContainingCycle, someCycleNode);
-    return subpathToCycle(pathToCycle, cycle);
-  }
-
-  /**
-   * Returns the subpath from the head of {@code path} to the first node in {@code path} that's in
-   * the cycle.
-   */
-  private ImmutableList<Node> subpathToCycle(ImmutableList<Node> path, Cycle<Node> cycle) {
-    ImmutableList.Builder<Node> subpath = ImmutableList.builder();
-    for (Node node : path) {
-      subpath.add(node);
-      if (cycle.nodes().contains(node)) {
-        return subpath.build();
-      }
-    }
-    throw new IllegalArgumentException(
-        "path " + path + " doesn't contain any nodes in cycle " + cycle);
-  }
-
-  private String errorMessage(Cycle<Node> cycle, BindingGraph graph) {
-    StringBuilder message = new StringBuilder("Found a dependency cycle:");
-    ImmutableList<DependencyRequest> cycleRequests =
-        cycle.endpointPairs().stream()
-            // TODO(dpb): Would be nice to take the dependency graph here.
-            .map(endpointPair -> nonCycleBreakingEdge(endpointPair, graph))
-            .map(DependencyEdge::dependencyRequest)
-            .collect(toImmutableList())
-            .reverse();
-    dependencyRequestFormatter.formatIndentedList(message, cycleRequests, 0);
-    return message.toString();
-  }
-
-  /**
-   * Returns one of the edges between two nodes that doesn't {@linkplain
-   * #breaksCycle(DependencyEdge, BindingGraph) break} a cycle.
-   */
-  private DependencyEdge nonCycleBreakingEdge(EndpointPair<Node> endpointPair, BindingGraph graph) {
-    return graph.network().edgesConnecting(endpointPair.source(), endpointPair.target()).stream()
-        .flatMap(instancesOf(DependencyEdge.class))
-        .filter(edge -> !breaksCycle(edge, graph))
-        .findFirst()
-        .get();
-  }
-
-  private boolean breaksCycle(DependencyEdge edge, BindingGraph graph) {
-    // Map<K, V> multibindings depend on Map<K, Provider<V>> entries, but those don't break any
-    // cycles, so ignore them.
-    if (edge.dependencyRequest().key().multibindingContributionIdentifier().isPresent()) {
-      return false;
-    }
-    if (breaksCycle(edge.dependencyRequest().key().type(), edge.dependencyRequest().kind())) {
-      return true;
-    }
-    Node target = graph.network().incidentNodes(edge).target();
-    if (target instanceof dagger.model.Binding
-        && ((dagger.model.Binding) target).kind().equals(BindingKind.OPTIONAL)) {
-      /* For @BindsOptionalOf bindings, unwrap the type inside the Optional. If the unwrapped type
-       * breaks the cycle, so does the optional binding. */
-      TypeMirror optionalValueType = OptionalType.from(edge.dependencyRequest().key()).valueType();
-      RequestKind requestKind = getRequestKind(optionalValueType);
-      return breaksCycle(extractKeyType(optionalValueType), requestKind);
-    }
-    return false;
-  }
-
-  private boolean breaksCycle(TypeMirror requestedType, RequestKind requestKind) {
-    switch (requestKind) {
-      case PROVIDER:
-      case LAZY:
-      case PROVIDER_OF_LAZY:
-        return true;
-
-      case INSTANCE:
-        if (MapType.isMap(requestedType)) {
-          MapType mapType = MapType.from(requestedType);
-          return !mapType.isRawType() && mapType.valuesAreTypeOf(Provider.class);
-        }
-        // fall through
-
-      default:
-        return false;
-    }
-  }
-
-  private DependencyEdge chooseDependencyEdgeConnecting(
-      Node source, Node target, BindingGraph bindingGraph) {
-    return bindingGraph.network().edgesConnecting(source, target).stream()
-        .flatMap(instancesOf(DependencyEdge.class))
-        .findFirst()
-        .get();
-  }
-
-  /** Returns the subgraph containing only {@link DependencyEdge}s that would not break a cycle. */
-  // TODO(dpb): Return a network containing only Binding nodes.
-  private ImmutableNetwork<Node, DependencyEdge> nonCycleBreakingDependencyGraph(
-      BindingGraph bindingGraph) {
-    MutableNetwork<Node, DependencyEdge> dependencyNetwork =
-        NetworkBuilder.from(bindingGraph.network())
-            .expectedNodeCount(bindingGraph.network().nodes().size())
-            .expectedEdgeCount(bindingGraph.dependencyEdges().size())
-            .build();
-    bindingGraph.dependencyEdges().stream()
-        .filter(edge -> !breaksCycle(edge, bindingGraph))
-        .forEach(
-            edge -> {
-              EndpointPair<Node> endpoints = bindingGraph.network().incidentNodes(edge);
-              dependencyNetwork.addEdge(endpoints.source(), endpoints.target(), edge);
-            });
-    return ImmutableNetwork.copyOf(dependencyNetwork);
-  }
-
-  /**
-   * An ordered set of endpoint pairs representing the edges in the cycle. The target of each pair
-   * is the source of the next pair. The target of the last pair is the source of the first pair.
-   */
-  @AutoValue
-  abstract static class Cycle<N> {
-    /**
-     * The ordered set of endpoint pairs representing the edges in the cycle. The target of each
-     * pair is the source of the next pair. The target of the last pair is the source of the first
-     * pair.
-     */
-    abstract ImmutableSet<EndpointPair<N>> endpointPairs();
-
-    /** Returns the nodes that participate in the cycle. */
-    ImmutableSet<N> nodes() {
-      return endpointPairs().stream()
-          .flatMap(pair -> Stream.of(pair.source(), pair.target()))
-          .collect(toImmutableSet());
-    }
-
-    /** Returns the number of edges in the cycle. */
-    int size() {
-      return endpointPairs().size();
-    }
-
-    /**
-     * Shifts this cycle so that it starts with a specific node.
-     *
-     * @return a cycle equivalent to this one but whose first pair starts with {@code startNode}
-     */
-    Cycle<N> shift(N startNode) {
-      int startIndex = Iterables.indexOf(endpointPairs(), pair -> pair.source().equals(startNode));
-      checkArgument(
-          startIndex >= 0, "startNode (%s) is not part of this cycle: %s", startNode, this);
-      if (startIndex == 0) {
-        return this;
-      }
-      ImmutableSet.Builder<EndpointPair<N>> shifted = ImmutableSet.builder();
-      shifted.addAll(skip(endpointPairs(), startIndex));
-      shifted.addAll(limit(endpointPairs(), size() - startIndex));
-      return new AutoValue_DependencyCycleValidator_Cycle<>(shifted.build());
-    }
-
-    @Override
-    public final String toString() {
-      return endpointPairs().toString();
-    }
-
-    /**
-     * Creates a {@link Cycle} from a nonempty list of nodes, assuming there is an edge between each
-     * pair of nodes as well as an edge from the last node to the first.
-     */
-    static <N> Cycle<N> fromPath(List<N> nodes) {
-      checkArgument(!nodes.isEmpty());
-      ImmutableSet.Builder<EndpointPair<N>> cycle = ImmutableSet.builder();
-      cycle.add(EndpointPair.ordered(getLast(nodes), nodes.get(0)));
-      for (int i = 0; i < nodes.size() - 1; i++) {
-        cycle.add(EndpointPair.ordered(nodes.get(i), nodes.get(i + 1)));
-      }
-      return new AutoValue_DependencyCycleValidator_Cycle<>(cycle.build());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/DependsOnProductionExecutorValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/DependsOnProductionExecutorValidator.java
deleted file mode 100644
index 08e2c3e..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/DependsOnProductionExecutorValidator.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import dagger.internal.codegen.binding.KeyFactory;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.MaybeBinding;
-import dagger.model.Key;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import javax.inject.Inject;
-
-/**
- * Reports an error on all bindings that depend explicitly on the {@code @Production Executor} key.
- */
-// TODO(dpb,beder): Validate this during @Inject/@Provides/@Produces validation.
-final class DependsOnProductionExecutorValidator implements BindingGraphPlugin {
-  private final CompilerOptions compilerOptions;
-  private final KeyFactory keyFactory;
-
-  @Inject
-  DependsOnProductionExecutorValidator(CompilerOptions compilerOptions, KeyFactory keyFactory) {
-    this.compilerOptions = compilerOptions;
-    this.keyFactory = keyFactory;
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/DependsOnProductionExecutor";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    if (!compilerOptions.usesProducers()) {
-      return;
-    }
-
-    Key productionImplementationExecutorKey = keyFactory.forProductionImplementationExecutor();
-    Key productionExecutorKey = keyFactory.forProductionExecutor();
-
-    bindingGraph.network().nodes().stream()
-        .flatMap(instancesOf(MaybeBinding.class))
-        .filter(node -> node.key().equals(productionExecutorKey))
-        .flatMap(productionExecutor -> bindingGraph.requestingBindings(productionExecutor).stream())
-        .filter(binding -> !binding.key().equals(productionImplementationExecutorKey))
-        .forEach(binding -> reportError(diagnosticReporter, binding));
-  }
-
-  private void reportError(DiagnosticReporter diagnosticReporter, dagger.model.Binding binding) {
-    diagnosticReporter.reportBinding(
-        ERROR, binding, "%s may not depend on the production executor", binding.key());
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/DuplicateBindingsValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/DuplicateBindingsValidator.java
deleted file mode 100644
index 5c4da51..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/DuplicateBindingsValidator.java
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static com.google.common.base.Verify.verify;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.Formatter.INDENT;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSetMultimap;
-import static dagger.model.BindingKind.INJECTION;
-import static dagger.model.BindingKind.MEMBERS_INJECTION;
-import static java.util.Comparator.comparing;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.ImmutableMultiset;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.Sets;
-import dagger.internal.codegen.base.Formatter;
-import dagger.internal.codegen.binding.BindingDeclaration;
-import dagger.internal.codegen.binding.BindingDeclarationFormatter;
-import dagger.internal.codegen.binding.BindingNode;
-import dagger.internal.codegen.binding.MultibindingDeclaration;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.model.Binding;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.ComponentNode;
-import dagger.model.BindingKind;
-import dagger.model.ComponentPath;
-import dagger.model.Key;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Predicate;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic.Kind;
-
-/** Reports errors for conflicting bindings with the same key. */
-final class DuplicateBindingsValidator implements BindingGraphPlugin {
-
-  private static final Comparator<Binding> BY_LENGTH_OF_COMPONENT_PATH =
-      comparing(binding -> binding.componentPath().components().size());
-
-  private final BindingDeclarationFormatter bindingDeclarationFormatter;
-  private final CompilerOptions compilerOptions;
-
-  @Inject
-  DuplicateBindingsValidator(
-      BindingDeclarationFormatter bindingDeclarationFormatter, CompilerOptions compilerOptions) {
-    this.bindingDeclarationFormatter = bindingDeclarationFormatter;
-    this.compilerOptions = compilerOptions;
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/DuplicateBindings";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    // If two unrelated subcomponents have the same duplicate bindings only because they install the
-    // same two modules, then fixing the error in one subcomponent will uncover the second
-    // subcomponent to fix.
-    // TODO(ronshapiro): Explore ways to address such underreporting without overreporting.
-    Set<ImmutableSet<BindingElement>> reportedDuplicateBindingSets = new HashSet<>();
-    duplicateBindingSets(bindingGraph)
-        .forEach(
-            duplicateBindings -> {
-              // Only report each set of duplicate bindings once, ignoring the installed component.
-              if (reportedDuplicateBindingSets.add(duplicateBindings.keySet())) {
-                reportDuplicateBindings(duplicateBindings, bindingGraph, diagnosticReporter);
-              }
-            });
-  }
-
-  /**
-   * Returns sets of duplicate bindings. Bindings are duplicates if they bind the same key and are
-   * visible from the same component. Two bindings that differ only in the component that owns them
-   * are not considered to be duplicates, because that means the same binding was "copied" down to a
-   * descendant component because it depends on local multibindings or optional bindings. Hence each
-   * "set" is represented as a multimap from binding element (ignoring component path) to binding.
-   */
-  private ImmutableSet<ImmutableSetMultimap<BindingElement, Binding>> duplicateBindingSets(
-      BindingGraph bindingGraph) {
-    return groupBindingsByKey(bindingGraph).stream()
-        .flatMap(bindings -> mutuallyVisibleSubsets(bindings).stream())
-        .map(BindingElement::index)
-        .filter(duplicates -> duplicates.keySet().size() > 1)
-        .collect(toImmutableSet());
-  }
-
-  private static ImmutableSet<ImmutableSet<Binding>> groupBindingsByKey(BindingGraph bindingGraph) {
-    return valueSetsForEachKey(
-        bindingGraph.bindings().stream()
-            .filter(binding -> !binding.kind().equals(MEMBERS_INJECTION))
-            .collect(toImmutableSetMultimap(Binding::key, binding -> binding)));
-  }
-
-  /**
-   * Returns the subsets of the input set that contain bindings that are all visible from the same
-   * component. A binding is visible from its component and all its descendants.
-   */
-  private static ImmutableSet<ImmutableSet<Binding>> mutuallyVisibleSubsets(
-      Set<Binding> duplicateBindings) {
-    ImmutableListMultimap<ComponentPath, Binding> bindingsByComponentPath =
-        Multimaps.index(duplicateBindings, Binding::componentPath);
-    ImmutableSetMultimap.Builder<ComponentPath, Binding> mutuallyVisibleBindings =
-        ImmutableSetMultimap.builder();
-    bindingsByComponentPath
-        .asMap()
-        .forEach(
-            (componentPath, bindings) -> {
-              mutuallyVisibleBindings.putAll(componentPath, bindings);
-              for (ComponentPath ancestor = componentPath; !ancestor.atRoot(); ) {
-                ancestor = ancestor.parent();
-                ImmutableList<Binding> bindingsInAncestor = bindingsByComponentPath.get(ancestor);
-                mutuallyVisibleBindings.putAll(componentPath, bindingsInAncestor);
-              }
-            });
-    return valueSetsForEachKey(mutuallyVisibleBindings.build());
-  }
-
-  private void reportDuplicateBindings(
-      ImmutableSetMultimap<BindingElement, Binding> duplicateBindings,
-      BindingGraph bindingGraph,
-      DiagnosticReporter diagnosticReporter) {
-    if (explicitBindingConfictsWithInject(duplicateBindings.keySet())) {
-      compilerOptions
-          .explicitBindingConflictsWithInjectValidationType()
-          .diagnosticKind()
-          .ifPresent(
-              diagnosticKind ->
-                  reportExplicitBindingConflictsWithInject(
-                      duplicateBindings,
-                      diagnosticReporter,
-                      diagnosticKind,
-                      bindingGraph.rootComponentNode()));
-      return;
-    }
-    ImmutableSet<Binding> bindings = ImmutableSet.copyOf(duplicateBindings.values());
-    Binding oneBinding = bindings.asList().get(0);
-    String message = bindings.stream().anyMatch(binding -> binding.kind().isMultibinding())
-        ? incompatibleBindingsMessage(oneBinding, bindings, bindingGraph)
-        : duplicateBindingMessage(oneBinding, bindings, bindingGraph);
-    if (compilerOptions.experimentalDaggerErrorMessages()) {
-      diagnosticReporter.reportComponent(
-          ERROR,
-          bindingGraph.rootComponentNode(),
-          message);
-    } else {
-      diagnosticReporter.reportBinding(
-          ERROR,
-          oneBinding,
-          message);
-    }
-  }
-
-  /**
-   * Returns {@code true} if the bindings contain one {@code @Inject} binding and one that isn't.
-   */
-  private static boolean explicitBindingConfictsWithInject(
-      ImmutableSet<BindingElement> duplicateBindings) {
-    ImmutableMultiset<BindingKind> bindingKinds =
-        Multimaps.index(duplicateBindings, BindingElement::bindingKind).keys();
-    return bindingKinds.count(INJECTION) == 1 && bindingKinds.size() == 2;
-  }
-
-  private void reportExplicitBindingConflictsWithInject(
-      ImmutableSetMultimap<BindingElement, Binding> duplicateBindings,
-      DiagnosticReporter diagnosticReporter,
-      Kind diagnosticKind,
-      ComponentNode rootComponent) {
-    Binding injectBinding =
-        rootmostBindingWithKind(k -> k.equals(INJECTION), duplicateBindings.values());
-    Binding explicitBinding =
-        rootmostBindingWithKind(k -> !k.equals(INJECTION), duplicateBindings.values());
-    StringBuilder message =
-        new StringBuilder()
-            .append(explicitBinding.key())
-            .append(" is bound multiple times:")
-            .append(formatWithComponentPath(injectBinding))
-            .append(formatWithComponentPath(explicitBinding))
-            .append(
-                "\nThis condition was never validated before, and will soon be an error. "
-                    + "See https://dagger.dev/conflicting-inject.");
-
-    if (compilerOptions.experimentalDaggerErrorMessages()) {
-      diagnosticReporter.reportComponent(diagnosticKind, rootComponent, message.toString());
-    } else {
-      diagnosticReporter.reportBinding(diagnosticKind, explicitBinding, message.toString());
-    }
-  }
-
-  private String formatWithComponentPath(Binding binding) {
-    return String.format(
-        "\n%s%s [%s]",
-        Formatter.INDENT,
-        bindingDeclarationFormatter.format(((BindingNode) binding).delegate()),
-        binding.componentPath());
-  }
-
-  private String duplicateBindingMessage(
-      Binding oneBinding, ImmutableSet<Binding> duplicateBindings, BindingGraph graph) {
-    StringBuilder message =
-        new StringBuilder().append(oneBinding.key()).append(" is bound multiple times:");
-    formatDeclarations(message, 1, declarations(graph, duplicateBindings));
-    if (compilerOptions.experimentalDaggerErrorMessages()) {
-      message.append(String.format("\n%sin component: [%s]", INDENT, oneBinding.componentPath()));
-    }
-    return message.toString();
-  }
-
-  private String incompatibleBindingsMessage(
-      Binding oneBinding, ImmutableSet<Binding> duplicateBindings, BindingGraph graph) {
-    Key key = oneBinding.key();
-    ImmutableSet<dagger.model.Binding> multibindings =
-        duplicateBindings.stream()
-            .filter(binding -> binding.kind().isMultibinding())
-            .collect(toImmutableSet());
-    verify(
-        multibindings.size() == 1, "expected only one multibinding for %s: %s", key, multibindings);
-    StringBuilder message = new StringBuilder();
-    java.util.Formatter messageFormatter = new java.util.Formatter(message);
-    messageFormatter.format("%s has incompatible bindings or declarations:\n", key);
-    message.append(INDENT);
-    dagger.model.Binding multibinding = getOnlyElement(multibindings);
-    messageFormatter.format("%s bindings and declarations:", multibindingTypeString(multibinding));
-    formatDeclarations(message, 2, declarations(graph, multibindings));
-
-    Set<dagger.model.Binding> uniqueBindings =
-        Sets.filter(duplicateBindings, binding -> !binding.equals(multibinding));
-    message.append('\n').append(INDENT).append("Unique bindings and declarations:");
-    formatDeclarations(
-        message,
-        2,
-        Sets.filter(
-            declarations(graph, uniqueBindings),
-            declaration -> !(declaration instanceof MultibindingDeclaration)));
-    if (compilerOptions.experimentalDaggerErrorMessages()) {
-      message.append(String.format("\n%sin component: [%s]", INDENT, oneBinding.componentPath()));
-    }
-    return message.toString();
-  }
-
-  private void formatDeclarations(
-      StringBuilder builder,
-      int indentLevel,
-      Iterable<? extends BindingDeclaration> bindingDeclarations) {
-    bindingDeclarationFormatter.formatIndentedList(
-        builder, ImmutableList.copyOf(bindingDeclarations), indentLevel);
-  }
-
-  private ImmutableSet<BindingDeclaration> declarations(
-      BindingGraph graph, Set<dagger.model.Binding> bindings) {
-    return bindings.stream()
-        .flatMap(binding -> declarations(graph, binding).stream())
-        .distinct()
-        .sorted(BindingDeclaration.COMPARATOR)
-        .collect(toImmutableSet());
-  }
-
-  private ImmutableSet<BindingDeclaration> declarations(
-      BindingGraph graph, dagger.model.Binding binding) {
-    ImmutableSet.Builder<BindingDeclaration> declarations = ImmutableSet.builder();
-    BindingNode bindingNode = (BindingNode) binding;
-    bindingNode.associatedDeclarations().forEach(declarations::add);
-    if (bindingDeclarationFormatter.canFormat(bindingNode.delegate())) {
-      declarations.add(bindingNode.delegate());
-    } else {
-      graph.requestedBindings(binding).stream()
-          .flatMap(requestedBinding -> declarations(graph, requestedBinding).stream())
-          .forEach(declarations::add);
-    }
-    return declarations.build();
-  }
-
-  private String multibindingTypeString(dagger.model.Binding multibinding) {
-    switch (multibinding.kind()) {
-      case MULTIBOUND_MAP:
-        return "Map";
-      case MULTIBOUND_SET:
-        return "Set";
-      default:
-        throw new AssertionError(multibinding);
-    }
-  }
-
-  private static <E> ImmutableSet<ImmutableSet<E>> valueSetsForEachKey(Multimap<?, E> multimap) {
-    return multimap.asMap().values().stream().map(ImmutableSet::copyOf).collect(toImmutableSet());
-  }
-
-  /** Returns the binding of the given kind that is closest to the root component. */
-  private static Binding rootmostBindingWithKind(
-      Predicate<BindingKind> bindingKindPredicate, ImmutableCollection<Binding> bindings) {
-    return bindings.stream()
-        .filter(b -> bindingKindPredicate.test(b.kind()))
-        .min(BY_LENGTH_OF_COMPONENT_PATH)
-        .get();
-  }
-
-  /** The identifying information about a binding, excluding its {@link Binding#componentPath()}. */
-  @AutoValue
-  abstract static class BindingElement {
-
-    abstract BindingKind bindingKind();
-
-    abstract Optional<Element> bindingElement();
-
-    abstract Optional<TypeElement> contributingModule();
-
-    static ImmutableSetMultimap<BindingElement, Binding> index(Set<Binding> bindings) {
-      return bindings.stream().collect(toImmutableSetMultimap(BindingElement::forBinding, b -> b));
-    }
-
-    private static BindingElement forBinding(Binding binding) {
-      return new AutoValue_DuplicateBindingsValidator_BindingElement(
-          binding.kind(), binding.bindingElement(), binding.contributingModule());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/IncompatiblyScopedBindingsValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/IncompatiblyScopedBindingsValidator.java
deleted file mode 100644
index a01dbaf..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/IncompatiblyScopedBindingsValidator.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static dagger.internal.codegen.base.Formatter.INDENT;
-import static dagger.internal.codegen.base.Scopes.getReadableSource;
-import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
-import static dagger.model.BindingKind.INJECTION;
-import static java.util.stream.Collectors.joining;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Multimaps;
-import dagger.internal.codegen.base.Scopes;
-import dagger.internal.codegen.binding.MethodSignatureFormatter;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.model.Binding;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.ComponentNode;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import java.util.Optional;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.tools.Diagnostic;
-
-/**
- * Reports an error for any component that uses bindings with scopes that are not assigned to the
- * component.
- */
-final class IncompatiblyScopedBindingsValidator implements BindingGraphPlugin {
-
-  private final MethodSignatureFormatter methodSignatureFormatter;
-  private final CompilerOptions compilerOptions;
-
-  @Inject
-  IncompatiblyScopedBindingsValidator(
-      MethodSignatureFormatter methodSignatureFormatter, CompilerOptions compilerOptions) {
-    this.methodSignatureFormatter = methodSignatureFormatter;
-    this.compilerOptions = compilerOptions;
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/IncompatiblyScopedBindings";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    ImmutableSetMultimap.Builder<ComponentNode, dagger.model.Binding> incompatibleBindings =
-        ImmutableSetMultimap.builder();
-    for (dagger.model.Binding binding : bindingGraph.bindings()) {
-      binding
-          .scope()
-          .filter(scope -> !scope.isReusable())
-          .ifPresent(
-              scope -> {
-                ComponentNode componentNode =
-                    bindingGraph.componentNode(binding.componentPath()).get();
-                if (!componentNode.scopes().contains(scope)) {
-                  // @Inject bindings in module or subcomponent binding graphs will appear at the
-                  // properly scoped ancestor component, so ignore them here.
-                  if (binding.kind().equals(INJECTION)
-                      && (bindingGraph.rootComponentNode().isSubcomponent()
-                          || !bindingGraph.rootComponentNode().isRealComponent())) {
-                    return;
-                  }
-                  incompatibleBindings.put(componentNode, binding);
-                }
-              });
-    }
-    Multimaps.asMap(incompatibleBindings.build())
-        .forEach((componentNode, bindings) -> report(componentNode, bindings, diagnosticReporter));
-  }
-
-  private void report(
-      ComponentNode componentNode,
-      Set<Binding> bindings,
-      DiagnosticReporter diagnosticReporter) {
-    Diagnostic.Kind diagnosticKind = ERROR;
-    StringBuilder message =
-        new StringBuilder(componentNode.componentPath().currentComponent().getQualifiedName());
-
-    if (!componentNode.isRealComponent()) {
-      // If the "component" is really a module, it will have no scopes attached. We want to report
-      // if there is more than one scope in that component.
-      if (bindings.stream().map(Binding::scope).map(Optional::get).distinct().count() <= 1) {
-        return;
-      }
-      message.append(" contains bindings with different scopes:");
-      diagnosticKind = compilerOptions.moduleHasDifferentScopesDiagnosticKind();
-    } else if (componentNode.scopes().isEmpty()) {
-      message.append(" (unscoped) may not reference scoped bindings:");
-    } else {
-      message
-          .append(" scoped with ")
-          .append(
-              componentNode.scopes().stream().map(Scopes::getReadableSource).collect(joining(" ")))
-          .append(" may not reference bindings with different scopes:");
-    }
-
-    // TODO(ronshapiro): Should we group by scope?
-    for (Binding binding : bindings) {
-      message.append('\n').append(INDENT);
-
-      // TODO(dpb): Use BindingDeclarationFormatter.
-      // But that doesn't print scopes for @Inject-constructed types.
-      switch (binding.kind()) {
-        case DELEGATE:
-        case PROVISION:
-          message.append(
-              methodSignatureFormatter.format(
-                  MoreElements.asExecutable(binding.bindingElement().get())));
-          break;
-
-        case INJECTION:
-          message
-              .append(getReadableSource(binding.scope().get()))
-              .append(" class ")
-              .append(
-                  closestEnclosingTypeElement(binding.bindingElement().get()).getQualifiedName());
-          break;
-
-        default:
-          throw new AssertionError(binding);
-      }
-    }
-    diagnosticReporter.reportComponent(diagnosticKind, componentNode, message.toString());
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/InjectBindingValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/InjectBindingValidator.java
deleted file mode 100644
index fe1c3e0..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/InjectBindingValidator.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static dagger.model.BindingKind.INJECTION;
-
-import com.google.auto.common.MoreTypes;
-import dagger.internal.codegen.validation.InjectValidator;
-import dagger.internal.codegen.validation.ValidationReport;
-import dagger.internal.codegen.validation.ValidationReport.Item;
-import dagger.model.BindingGraph;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import javax.inject.Inject;
-import javax.lang.model.element.TypeElement;
-
-/** Validates bindings from {@code @Inject}-annotated constructors. */
-final class InjectBindingValidator implements BindingGraphPlugin {
-
-  private final InjectValidator injectValidator;
-
-  @Inject
-  InjectBindingValidator(InjectValidator injectValidator) {
-    this.injectValidator = injectValidator.whenGeneratingCode();
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/InjectBinding";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    bindingGraph.bindings().stream()
-        .filter(binding -> binding.kind().equals(INJECTION)) // TODO(dpb): Move to BindingGraph
-        .forEach(binding -> validateInjectionBinding(binding, diagnosticReporter));
-  }
-
-  private void validateInjectionBinding(
-      dagger.model.Binding node, DiagnosticReporter diagnosticReporter) {
-    ValidationReport<TypeElement> typeReport =
-        injectValidator.validateType(MoreTypes.asTypeElement(node.key().type()));
-    for (Item item : typeReport.allItems()) {
-      diagnosticReporter.reportBinding(item.kind(), node, item.message());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/MapMultibindingValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/MapMultibindingValidator.java
deleted file mode 100644
index 481c6d8..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/MapMultibindingValidator.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Multimaps.filterKeys;
-import static dagger.internal.codegen.base.Formatter.INDENT;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSetMultimap;
-import static dagger.model.BindingKind.MULTIBOUND_MAP;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.base.Equivalence;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.binding.BindingDeclaration;
-import dagger.internal.codegen.binding.BindingDeclarationFormatter;
-import dagger.internal.codegen.binding.BindingNode;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.KeyFactory;
-import dagger.model.BindingGraph;
-import dagger.model.Key;
-import dagger.producers.Producer;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.lang.model.type.DeclaredType;
-
-/**
- * Reports an error for any map binding with either more than one contribution with the same map key
- * or contributions with inconsistent map key annotation types.
- */
-final class MapMultibindingValidator implements BindingGraphPlugin {
-
-  private final BindingDeclarationFormatter bindingDeclarationFormatter;
-  private final KeyFactory keyFactory;
-
-  @Inject
-  MapMultibindingValidator(
-      BindingDeclarationFormatter bindingDeclarationFormatter, KeyFactory keyFactory) {
-    this.bindingDeclarationFormatter = bindingDeclarationFormatter;
-    this.keyFactory = keyFactory;
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/MapKeys";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    mapMultibindings(bindingGraph)
-        .forEach(
-            binding -> {
-              ImmutableSet<ContributionBinding> contributions =
-                  mapBindingContributions(binding, bindingGraph);
-              checkForDuplicateMapKeys(binding, contributions, diagnosticReporter);
-              checkForInconsistentMapKeyAnnotationTypes(binding, contributions, diagnosticReporter);
-            });
-  }
-
-  /**
-   * Returns the map multibindings in the binding graph. If a graph contains bindings for more than
-   * one of the following for the same {@code K} and {@code V}, then only the first one found will
-   * be returned so we don't report the same map contribution problem more than once.
-   *
-   * <ol>
-   *   <li>{@code Map<K, V>}
-   *   <li>{@code Map<K, Provider<V>>}
-   *   <li>{@code Map<K, Producer<V>>}
-   * </ol>
-   */
-  private ImmutableSet<dagger.model.Binding> mapMultibindings(BindingGraph bindingGraph) {
-    ImmutableSetMultimap<Key, dagger.model.Binding> mapMultibindings =
-        bindingGraph.bindings().stream()
-            .filter(node -> node.kind().equals(MULTIBOUND_MAP))
-            .collect(toImmutableSetMultimap(dagger.model.Binding::key, node -> node));
-
-    // Mutlbindings for Map<K, V>
-    SetMultimap<Key, dagger.model.Binding> plainValueMapMultibindings =
-        filterKeys(mapMultibindings, key -> !MapType.from(key).valuesAreFrameworkType());
-
-    // Multibindings for Map<K, Provider<V>> where Map<K, V> isn't in plainValueMapMultibindings
-    SetMultimap<Key, dagger.model.Binding> providerValueMapMultibindings =
-        filterKeys(
-            mapMultibindings,
-            key ->
-                MapType.from(key).valuesAreTypeOf(Provider.class)
-                    && !plainValueMapMultibindings.containsKey(keyFactory.unwrapMapValueType(key)));
-
-    // Multibindings for Map<K, Producer<V>> where Map<K, V> isn't in plainValueMapMultibindings and
-    // Map<K, Provider<V>> isn't in providerValueMapMultibindings
-    SetMultimap<Key, dagger.model.Binding> producerValueMapMultibindings =
-        filterKeys(
-            mapMultibindings,
-            key ->
-                MapType.from(key).valuesAreTypeOf(Producer.class)
-                    && !plainValueMapMultibindings.containsKey(keyFactory.unwrapMapValueType(key))
-                    && !providerValueMapMultibindings.containsKey(
-                        keyFactory.rewrapMapKey(key, Producer.class, Provider.class).get()));
-
-    return new ImmutableSet.Builder<dagger.model.Binding>()
-        .addAll(plainValueMapMultibindings.values())
-        .addAll(providerValueMapMultibindings.values())
-        .addAll(producerValueMapMultibindings.values())
-        .build();
-  }
-
-  private ImmutableSet<ContributionBinding> mapBindingContributions(
-      dagger.model.Binding binding, BindingGraph bindingGraph) {
-    checkArgument(binding.kind().equals(MULTIBOUND_MAP));
-    return bindingGraph.requestedBindings(binding).stream()
-        .map(b -> (BindingNode) b)
-        .map(b -> (ContributionBinding) b.delegate())
-        .collect(toImmutableSet());
-  }
-
-  private void checkForDuplicateMapKeys(
-      dagger.model.Binding multiboundMapBinding,
-      ImmutableSet<ContributionBinding> contributions,
-      DiagnosticReporter diagnosticReporter) {
-    ImmutableSetMultimap<?, ContributionBinding> contributionsByMapKey =
-        ImmutableSetMultimap.copyOf(
-            Multimaps.index(contributions, ContributionBinding::wrappedMapKeyAnnotation));
-
-    for (Set<ContributionBinding> contributionsForOneMapKey :
-        Multimaps.asMap(contributionsByMapKey).values()) {
-      if (contributionsForOneMapKey.size() > 1) {
-        diagnosticReporter.reportBinding(
-            ERROR,
-            multiboundMapBinding,
-            duplicateMapKeyErrorMessage(contributionsForOneMapKey, multiboundMapBinding.key()));
-      }
-    }
-  }
-
-  private void checkForInconsistentMapKeyAnnotationTypes(
-      dagger.model.Binding multiboundMapBinding,
-      ImmutableSet<ContributionBinding> contributions,
-      DiagnosticReporter diagnosticReporter) {
-    ImmutableSetMultimap<Equivalence.Wrapper<DeclaredType>, ContributionBinding>
-        contributionsByMapKeyAnnotationType = indexByMapKeyAnnotationType(contributions);
-
-    if (contributionsByMapKeyAnnotationType.keySet().size() > 1) {
-      diagnosticReporter.reportBinding(
-          ERROR,
-          multiboundMapBinding,
-          inconsistentMapKeyAnnotationTypesErrorMessage(
-              contributionsByMapKeyAnnotationType, multiboundMapBinding.key()));
-    }
-  }
-
-  private static ImmutableSetMultimap<Equivalence.Wrapper<DeclaredType>, ContributionBinding>
-      indexByMapKeyAnnotationType(ImmutableSet<ContributionBinding> contributions) {
-    return ImmutableSetMultimap.copyOf(
-        Multimaps.index(
-            contributions,
-            mapBinding ->
-                MoreTypes.equivalence()
-                    .wrap(mapBinding.mapKeyAnnotation().get().getAnnotationType())));
-  }
-
-  private String inconsistentMapKeyAnnotationTypesErrorMessage(
-      ImmutableSetMultimap<Equivalence.Wrapper<DeclaredType>, ContributionBinding>
-          contributionsByMapKeyAnnotationType,
-      Key mapBindingKey) {
-    StringBuilder message =
-        new StringBuilder(mapBindingKey.toString())
-            .append(" uses more than one @MapKey annotation type");
-    Multimaps.asMap(contributionsByMapKeyAnnotationType)
-        .forEach(
-            (annotationType, contributions) -> {
-              message.append('\n').append(INDENT).append(annotationType.get()).append(':');
-              bindingDeclarationFormatter.formatIndentedList(message, contributions, 2);
-            });
-    return message.toString();
-  }
-
-  private String duplicateMapKeyErrorMessage(
-      Set<ContributionBinding> contributionsForOneMapKey, Key mapBindingKey) {
-    StringBuilder message =
-        new StringBuilder("The same map key is bound more than once for ").append(mapBindingKey);
-
-    bindingDeclarationFormatter.formatIndentedList(
-        message,
-        ImmutableList.sortedCopyOf(BindingDeclaration.COMPARATOR, contributionsForOneMapKey),
-        1);
-    return message.toString();
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/MissingBindingValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/MissingBindingValidator.java
deleted file mode 100644
index 7334cd9..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/MissingBindingValidator.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static com.google.common.base.Verify.verify;
-import static dagger.internal.codegen.base.Keys.isValidImplicitProvisionKey;
-import static dagger.internal.codegen.base.Keys.isValidMembersInjectionKey;
-import static dagger.internal.codegen.base.RequestKinds.canBeSatisfiedByProductionBinding;
-import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import dagger.internal.codegen.binding.InjectBindingRegistry;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.ComponentNode;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.BindingGraph.MissingBinding;
-import dagger.model.BindingGraph.Node;
-import dagger.model.Key;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import javax.inject.Inject;
-import javax.lang.model.type.TypeKind;
-
-/** Reports errors for missing bindings. */
-final class MissingBindingValidator implements BindingGraphPlugin {
-
-  private final DaggerTypes types;
-  private final InjectBindingRegistry injectBindingRegistry;
-
-  @Inject
-  MissingBindingValidator(
-      DaggerTypes types, InjectBindingRegistry injectBindingRegistry) {
-    this.types = types;
-    this.injectBindingRegistry = injectBindingRegistry;
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/MissingBinding";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph graph, DiagnosticReporter diagnosticReporter) {
-    // Don't report missing bindings when validating a full binding graph or a graph built from a
-    // subcomponent.
-    if (graph.isFullBindingGraph() || graph.rootComponentNode().isSubcomponent()) {
-      return;
-    }
-    graph
-        .missingBindings()
-        .forEach(missingBinding -> reportMissingBinding(missingBinding, graph, diagnosticReporter));
-  }
-
-  private void reportMissingBinding(
-      MissingBinding missingBinding, BindingGraph graph, DiagnosticReporter diagnosticReporter) {
-    diagnosticReporter.reportBinding(
-        ERROR, missingBinding, missingBindingErrorMessage(missingBinding, graph));
-  }
-
-  private String missingBindingErrorMessage(MissingBinding missingBinding, BindingGraph graph) {
-    Key key = missingBinding.key();
-    StringBuilder errorMessage = new StringBuilder();
-    // Wildcards should have already been checked by DependencyRequestValidator.
-    verify(!key.type().getKind().equals(TypeKind.WILDCARD), "unexpected wildcard request: %s", key);
-    // TODO(ronshapiro): replace "provided" with "satisfied"?
-    errorMessage.append(key).append(" cannot be provided without ");
-    if (isValidImplicitProvisionKey(key, types)) {
-      errorMessage.append("an @Inject constructor or ");
-    }
-    errorMessage.append("an @Provides-"); // TODO(dpb): s/an/a
-    if (allIncomingDependenciesCanUseProduction(missingBinding, graph)) {
-      errorMessage.append(" or @Produces-");
-    }
-    errorMessage.append("annotated method.");
-    if (isValidMembersInjectionKey(key) && typeHasInjectionSites(key)) {
-      errorMessage.append(
-          " This type supports members injection but cannot be implicitly provided.");
-    }
-    graph.bindings(key).stream()
-        .map(binding -> binding.componentPath().currentComponent())
-        .distinct()
-        .forEach(
-            component ->
-                errorMessage
-                    .append("\nA binding with matching key exists in component: ")
-                    .append(component.getQualifiedName()));
-    return errorMessage.toString();
-  }
-
-  private boolean allIncomingDependenciesCanUseProduction(
-      MissingBinding missingBinding, BindingGraph graph) {
-    return graph.network().inEdges(missingBinding).stream()
-        .flatMap(instancesOf(DependencyEdge.class))
-        .allMatch(edge -> dependencyCanBeProduction(edge, graph));
-  }
-
-  // TODO(ronshapiro): merge with
-  // ProvisionDependencyOnProduerBindingValidator.dependencyCanUseProduction
-  private boolean dependencyCanBeProduction(DependencyEdge edge, BindingGraph graph) {
-    Node source = graph.network().incidentNodes(edge).source();
-    if (source instanceof ComponentNode) {
-      return canBeSatisfiedByProductionBinding(edge.dependencyRequest().kind());
-    }
-    if (source instanceof dagger.model.Binding) {
-      return ((dagger.model.Binding) source).isProduction();
-    }
-    throw new IllegalArgumentException(
-        "expected a dagger.model.Binding or ComponentNode: " + source);
-  }
-
-  private boolean typeHasInjectionSites(Key key) {
-    return injectBindingRegistry
-        .getOrFindMembersInjectionBinding(key)
-        .map(binding -> !binding.injectionSites().isEmpty())
-        .orElse(false);
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/NullableBindingValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/NullableBindingValidator.java
deleted file mode 100644
index 9800b15..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/NullableBindingValidator.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import javax.inject.Inject;
-
-/**
- * Reports errors or warnings (depending on the {@code -Adagger.nullableValidation} value) for each
- * non-nullable dependency request that is satisfied by a nullable binding.
- */
-final class NullableBindingValidator implements BindingGraphPlugin {
-
-  private final CompilerOptions compilerOptions;
-
-  @Inject
-  NullableBindingValidator(CompilerOptions compilerOptions) {
-    this.compilerOptions = compilerOptions;
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    for (dagger.model.Binding binding : nullableBindings(bindingGraph)) {
-      for (DependencyEdge dependencyEdge : nonNullableDependencies(bindingGraph, binding)) {
-        diagnosticReporter.reportDependency(
-            compilerOptions.nullableValidationKind(),
-            dependencyEdge,
-            nullableToNonNullable(
-                binding.key().toString(),
-                binding.toString())); // binding.toString() will include the @Nullable
-      }
-    }
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/Nullable";
-  }
-
-  private ImmutableList<dagger.model.Binding> nullableBindings(BindingGraph bindingGraph) {
-    return bindingGraph.bindings().stream()
-        .filter(binding -> binding.isNullable())
-        .collect(toImmutableList());
-  }
-
-  private ImmutableSet<DependencyEdge> nonNullableDependencies(
-      BindingGraph bindingGraph, dagger.model.Binding binding) {
-    return bindingGraph.network().inEdges(binding).stream()
-        .flatMap(instancesOf(DependencyEdge.class))
-        .filter(edge -> !edge.dependencyRequest().isNullable())
-        .collect(toImmutableSet());
-  }
-
-  @VisibleForTesting
-  static String nullableToNonNullable(String key, String binding) {
-    return String.format("%s is not nullable, but is being provided by %s", key, binding);
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/ProvisionDependencyOnProducerBindingValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/ProvisionDependencyOnProducerBindingValidator.java
deleted file mode 100644
index 7d742f9..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/ProvisionDependencyOnProducerBindingValidator.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Verify.verify;
-import static dagger.internal.codegen.base.RequestKinds.canBeSatisfiedByProductionBinding;
-import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.BindingGraph.Node;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import java.util.stream.Stream;
-import javax.inject.Inject;
-
-/**
- * Reports an error for each provision-only dependency request that is satisfied by a production
- * binding.
- */
-// TODO(b/29509141): Clarify the error.
-final class ProvisionDependencyOnProducerBindingValidator implements BindingGraphPlugin {
-
-  @Inject
-  ProvisionDependencyOnProducerBindingValidator() {}
-
-  @Override
-  public String pluginName() {
-    return "Dagger/ProviderDependsOnProducer";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    provisionDependenciesOnProductionBindings(bindingGraph)
-        .forEach(
-            provisionDependent ->
-                diagnosticReporter.reportDependency(
-                    ERROR,
-                    provisionDependent,
-                    provisionDependent.isEntryPoint()
-                        ? entryPointErrorMessage(provisionDependent)
-                        : dependencyErrorMessage(provisionDependent, bindingGraph)));
-  }
-
-  private Stream<DependencyEdge> provisionDependenciesOnProductionBindings(
-      BindingGraph bindingGraph) {
-    return bindingGraph.bindings().stream()
-        .filter(binding -> binding.isProduction())
-        .flatMap(binding -> incomingDependencies(binding, bindingGraph))
-        .filter(edge -> !dependencyCanUseProduction(edge, bindingGraph));
-  }
-
-  /** Returns the dependencies on {@code binding}. */
-  // TODO(dpb): Move to BindingGraph.
-  private Stream<DependencyEdge> incomingDependencies(
-      dagger.model.Binding binding, BindingGraph bindingGraph) {
-    return bindingGraph.network().inEdges(binding).stream()
-        .flatMap(instancesOf(DependencyEdge.class));
-  }
-
-  // TODO(ronshapiro): merge with MissingBindingValidator.dependencyCanUseProduction
-  private boolean dependencyCanUseProduction(DependencyEdge edge, BindingGraph bindingGraph) {
-    return edge.isEntryPoint()
-        ? canBeSatisfiedByProductionBinding(edge.dependencyRequest().kind())
-        : bindingRequestingDependency(edge, bindingGraph).isProduction();
-  }
-
-  /**
-   * Returns the binding that requests a dependency.
-   *
-   * @throws IllegalArgumentException if {@code dependency} is an {@linkplain
-   *     DependencyEdge#isEntryPoint() entry point}.
-   */
-  // TODO(dpb): Move to BindingGraph.
-  private dagger.model.Binding bindingRequestingDependency(
-      DependencyEdge dependency, BindingGraph bindingGraph) {
-    checkArgument(!dependency.isEntryPoint());
-    Node source = bindingGraph.network().incidentNodes(dependency).source();
-    verify(
-        source instanceof dagger.model.Binding,
-        "expected source of %s to be a binding, but was: %s",
-        dependency,
-        source);
-    return (dagger.model.Binding) source;
-  }
-
-  private String entryPointErrorMessage(DependencyEdge entryPoint) {
-    return String.format(
-        "%s is a provision entry-point, which cannot depend on a production.",
-        entryPoint.dependencyRequest().key());
-  }
-
-  private String dependencyErrorMessage(
-      DependencyEdge dependencyOnProduction, BindingGraph bindingGraph) {
-    return String.format(
-        "%s is a provision, which cannot depend on a production.",
-        bindingRequestingDependency(dependencyOnProduction, bindingGraph).key());
-  }
-}
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/SubcomponentFactoryMethodValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/SubcomponentFactoryMethodValidator.java
deleted file mode 100644
index bf83a69..0000000
--- a/java/dagger/internal/codegen/bindinggraphvalidation/SubcomponentFactoryMethodValidator.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.bindinggraphvalidation;
-
-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.binding.ComponentRequirement.componentCanMakeNewInstances;
-import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-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.internal.codegen.base.Util;
-import dagger.internal.codegen.binding.ComponentNodeImpl;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-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 SubcomponentFactoryMethodValidator implements BindingGraphPlugin {
-
-  private final DaggerTypes types;
-  private final KotlinMetadataUtil metadataUtil;
-  private final Map<ComponentNode, Set<TypeElement>> inheritedModulesCache = new HashMap<>();
-
-  @Inject
-  SubcomponentFactoryMethodValidator(DaggerTypes types, KotlinMetadataUtil metadataUtil) {
-    this.types = types;
-    this.metadataUtil = metadataUtil;
-  }
-
-  @Override
-  public String pluginName() {
-    return "Dagger/SubcomponentFactoryMethodMissingModule";
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    if (!bindingGraph.rootComponentNode().isRealComponent()
-        || bindingGraph.rootComponentNode().isSubcomponent()) {
-      // We don't know all the modules that might be owned by the child until we know the real root
-      // component, which we don't if the root component node is really a module or a subcomponent.
-      return;
-    }
-    bindingGraph.network().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.network().incidentNodes(edge).target();
-    SetView<TypeElement> modulesOwnedByChild = ownedModules(child, graph);
-    return graph.bindings().stream()
-        // bindings owned by child
-        .filter(binding -> binding.componentPath().equals(child.componentPath()))
-        // that require a module instance
-        .filter(binding -> binding.requiresModuleInstance())
-        .map(binding -> 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, metadataUtil))
-        .collect(toImmutableSet());
-  }
-
-  private ImmutableSet<TypeElement> subgraphFactoryMethodParameters(
-      ChildFactoryMethodEdge edge, BindingGraph bindingGraph) {
-    ComponentNode parent = (ComponentNode) bindingGraph.network().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().moduleTypes(),
-        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
-            .network()
-            .incidentNodes(edge)
-            .target()
-            .componentPath()
-            .currentComponent()
-            .getQualifiedName(),
-        Joiner.on(", ").join(missingModules));
-  }
-}
diff --git a/java/dagger/internal/codegen/bootstrap/BUILD b/java/dagger/internal/codegen/bootstrap/BUILD
deleted file mode 100644
index 2527d3c..0000000
--- a/java/dagger/internal/codegen/bootstrap/BUILD
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Bootstrap libraries for building Dagger with Dagger.
-
-load("@rules_java//java:defs.bzl", "java_import", "java_plugin")
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "bootstrap",
-    generates_api = 1,
-    processor_class = "dagger.internal.codegen.ComponentProcessor",
-    deps = [":bootstrap_compiler"],
-)
-
-java_import(
-    name = "bootstrap_compiler",
-    jars = ["bootstrap_compiler_deploy.jar"],
-    visibility = ["//visibility:private"],
-)
diff --git a/java/dagger/internal/codegen/bootstrap/bootstrap_compiler_deploy.jar b/java/dagger/internal/codegen/bootstrap/bootstrap_compiler_deploy.jar
deleted file mode 100644
index b69dc65..0000000
--- a/java/dagger/internal/codegen/bootstrap/bootstrap_compiler_deploy.jar
+++ /dev/null
Binary files differ
diff --git a/java/dagger/internal/codegen/bootstrap_compiler_deploy.jar b/java/dagger/internal/codegen/bootstrap_compiler_deploy.jar
new file mode 100644
index 0000000..ad9761d
--- /dev/null
+++ b/java/dagger/internal/codegen/bootstrap_compiler_deploy.jar
Binary files differ
diff --git a/java/dagger/internal/codegen/compileroption/BUILD b/java/dagger/internal/codegen/compileroption/BUILD
deleted file mode 100644
index ef39b34..0000000
--- a/java/dagger/internal/codegen/compileroption/BUILD
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Sources related to compiler options.
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "compileroption",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    tags = ["maven:merged"],
-    deps = [
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/producers",
-        "@google_bazel_common//third_party/java/google_java_format",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
diff --git a/java/dagger/internal/codegen/compileroption/CompilerOptions.java b/java/dagger/internal/codegen/compileroption/CompilerOptions.java
deleted file mode 100644
index a0d1cda..0000000
--- a/java/dagger/internal/codegen/compileroption/CompilerOptions.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2016 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.compileroption;
-
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic;
-
-/** A collection of options that dictate how the compiler will run. */
-public abstract class CompilerOptions {
-  public abstract boolean usesProducers();
-
-  /**
-   * Returns true if the fast initialization flag, {@code fastInit}, is enabled.
-   *
-   * <p>If enabled, the generated code will attempt to optimize for fast component initialization.
-   * This is done by reducing the number of factory classes loaded during initialization and the
-   * number of eagerly initialized fields at the cost of potential memory leaks and higher
-   * per-provision instantiation time.
-   */
-  public abstract boolean fastInit(TypeElement element);
-
-  public abstract boolean formatGeneratedSource();
-
-  public abstract boolean writeProducerNameInToken();
-
-  public abstract Diagnostic.Kind nullableValidationKind();
-
-  public final boolean doCheckForNulls() {
-    return nullableValidationKind().equals(Diagnostic.Kind.ERROR);
-  }
-
-  public abstract Diagnostic.Kind privateMemberValidationKind();
-
-  public abstract Diagnostic.Kind staticMemberValidationKind();
-
-  /**
-   * If {@code true}, Dagger will generate factories and components even if some members-injected
-   * types have {@code private} or {@code static} {@code @Inject}-annotated members.
-   *
-   * <p>This should only ever be enabled by the TCK tests. Disabling this validation could lead to
-   * generating code that does not compile.
-   */
-  public abstract boolean ignorePrivateAndStaticInjectionForComponent();
-
-  public abstract ValidationType scopeCycleValidationType();
-
-  /**
-   * If {@code true}, Dagger will validate all transitive component dependencies of a component.
-   * Otherwise, Dagger will only validate the direct component dependencies.
-   *
-   * <p>Note: this is different from scopeCycleValidationType, which lets you silence errors of
-   * transitive component dependencies, but still requires the full transitive dependencies in the
-   * classpath.
-   *
-   * <p>The main motivation for this flag is to prevent requiring the transitive component
-   * dependencies in the classpath to speed up builds. See
-   * https://github.com/google/dagger/issues/970.
-   */
-  public abstract boolean validateTransitiveComponentDependencies();
-
-  public abstract boolean warnIfInjectionFactoryNotGeneratedUpstream();
-
-  public abstract boolean headerCompilation();
-
-  public abstract ValidationType fullBindingGraphValidationType();
-
-  /**
-   * If {@code true}, each plugin will visit the full binding graph for the given element.
-   *
-   * @throws IllegalArgumentException if {@code element} is not a module or (sub)component
-   */
-  public abstract boolean pluginsVisitFullBindingGraphs(TypeElement element);
-
-  public abstract Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind();
-
-  public abstract ValidationType explicitBindingConflictsWithInjectValidationType();
-
-  public abstract boolean experimentalDaggerErrorMessages();
-
-  /** Returns the number of bindings allowed per shard. */
-  public int keysPerComponentShard(TypeElement component) {
-    return 3500;
-  }
-
-  /**
-   * This option enables a fix to an issue where Dagger previously would erroneously allow
-   * multibinding contributions in a component to have dependencies on child components. This will
-   * eventually become the default and enforced.
-   */
-  public abstract boolean strictMultibindingValidation();
-}
diff --git a/java/dagger/internal/codegen/compileroption/FeatureStatus.java b/java/dagger/internal/codegen/compileroption/FeatureStatus.java
deleted file mode 100644
index d989679..0000000
--- a/java/dagger/internal/codegen/compileroption/FeatureStatus.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2016 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.compileroption;
-
-/** Allows options to control how features in component processing are enabled. */
-public enum FeatureStatus {
-  ENABLED,
-  DISABLED;
-}
diff --git a/java/dagger/internal/codegen/compileroption/JavacPluginCompilerOptions.java b/java/dagger/internal/codegen/compileroption/JavacPluginCompilerOptions.java
deleted file mode 100644
index a86cc1b..0000000
--- a/java/dagger/internal/codegen/compileroption/JavacPluginCompilerOptions.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2019 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.compileroption;
-
-import static dagger.internal.codegen.compileroption.ValidationType.NONE;
-import static javax.tools.Diagnostic.Kind.NOTE;
-
-import javax.inject.Inject;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic;
-
-/** {@link CompilerOptions} for Javac plugins (e.g. for Dagger statistics or Kythe). */
-public final class JavacPluginCompilerOptions extends CompilerOptions {
-
-  @Inject
-  JavacPluginCompilerOptions() {}
-
-  @Override
-  public boolean usesProducers() {
-    return true;
-  }
-
-  @Override
-  public boolean fastInit(TypeElement element) {
-    return false;
-  }
-
-  @Override
-  public boolean formatGeneratedSource() {
-    return false;
-  }
-
-  @Override
-  public boolean writeProducerNameInToken() {
-    return true;
-  }
-
-  @Override
-  public Diagnostic.Kind nullableValidationKind() {
-    return NOTE;
-  }
-
-  @Override
-  public Diagnostic.Kind privateMemberValidationKind() {
-    return NOTE;
-  }
-
-  @Override
-  public Diagnostic.Kind staticMemberValidationKind() {
-    return NOTE;
-  }
-
-  @Override
-  public boolean ignorePrivateAndStaticInjectionForComponent() {
-    return false;
-  }
-
-  @Override
-  public ValidationType scopeCycleValidationType() {
-    return NONE;
-  }
-
-  @Override
-  public boolean validateTransitiveComponentDependencies() {
-    return true;
-  }
-
-  @Override
-  public boolean warnIfInjectionFactoryNotGeneratedUpstream() {
-    return false;
-  }
-
-  @Override
-  public boolean headerCompilation() {
-    return false;
-  }
-
-  @Override
-  public ValidationType fullBindingGraphValidationType() {
-    return NONE;
-  }
-
-  @Override
-  public boolean pluginsVisitFullBindingGraphs(TypeElement element) {
-    return false;
-  }
-
-  @Override
-  public Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind() {
-    return NOTE;
-  }
-
-  @Override
-  public ValidationType explicitBindingConflictsWithInjectValidationType() {
-    return NONE;
-  }
-
-  @Override
-  public boolean experimentalDaggerErrorMessages() {
-    return false;
-  }
-
-  @Override
-  public boolean strictMultibindingValidation() {
-    return false;
-  }
-}
diff --git a/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java b/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java
deleted file mode 100644
index 06d15a2..0000000
--- a/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright (C) 2019 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.compileroption;
-
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Sets.immutableEnumSet;
-import static dagger.internal.codegen.compileroption.FeatureStatus.DISABLED;
-import static dagger.internal.codegen.compileroption.FeatureStatus.ENABLED;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.EXPERIMENTAL_ANDROID_MODE;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.EXPERIMENTAL_DAGGER_ERROR_MESSAGES;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.FAST_INIT;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.FLOATING_BINDS_METHODS;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.FORMAT_GENERATED_SOURCE;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.PLUGINS_VISIT_FULL_BINDING_GRAPHS;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.STRICT_MULTIBINDING_VALIDATION;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.VALIDATE_TRANSITIVE_COMPONENT_DEPENDENCIES;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.WRITE_PRODUCER_NAME_IN_TOKEN;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.KeyOnlyOption.HEADER_COMPILATION;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.KeyOnlyOption.USE_GRADLE_INCREMENTAL_PROCESSING;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Validation.DISABLE_INTER_COMPONENT_SCOPE_VALIDATION;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Validation.EXPLICIT_BINDING_CONFLICTS_WITH_INJECT;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Validation.FULL_BINDING_GRAPH_VALIDATION;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Validation.MODULE_HAS_DIFFERENT_SCOPES_VALIDATION;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Validation.NULLABLE_VALIDATION;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Validation.PRIVATE_MEMBER_VALIDATION;
-import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Validation.STATIC_MEMBER_VALIDATION;
-import static dagger.internal.codegen.compileroption.ValidationType.ERROR;
-import static dagger.internal.codegen.compileroption.ValidationType.NONE;
-import static dagger.internal.codegen.compileroption.ValidationType.WARNING;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Stream.concat;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.base.Ascii;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.producers.Produces;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Stream;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.inject.Inject;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic;
-
-/** {@link CompilerOptions} for the given {@link ProcessingEnvironment}. */
-public final class ProcessingEnvironmentCompilerOptions extends CompilerOptions {
-  // EnumOption<T> doesn't support integer inputs so just doing this as a 1-off for now.
-  private static final String KEYS_PER_COMPONENT_SHARD = "dagger.keysPerComponentShard";
-
-  private final ProcessingEnvironment processingEnvironment;
-  private final DaggerElements daggerElements;
-  private final Map<EnumOption<?>, Object> enumOptions = new HashMap<>();
-  private final Map<EnumOption<?>, ImmutableMap<String, ? extends Enum<?>>> allCommandLineOptions =
-      new HashMap<>();
-
-  @Inject
-  ProcessingEnvironmentCompilerOptions(
-      ProcessingEnvironment processingEnvironment, DaggerElements daggerElements) {
-    this.processingEnvironment = processingEnvironment;
-    this.daggerElements = daggerElements;
-    checkValid();
-  }
-
-  @Override
-  public boolean usesProducers() {
-    return processingEnvironment.getElementUtils().getTypeElement(Produces.class.getCanonicalName())
-        != null;
-  }
-
-  @Override
-  public boolean headerCompilation() {
-    return isEnabled(HEADER_COMPILATION);
-  }
-
-  @Override
-  public boolean fastInit(TypeElement component) {
-    return isEnabled(FAST_INIT);
-  }
-
-  @Override
-  public boolean formatGeneratedSource() {
-    return isEnabled(FORMAT_GENERATED_SOURCE);
-  }
-
-  @Override
-  public boolean writeProducerNameInToken() {
-    return isEnabled(WRITE_PRODUCER_NAME_IN_TOKEN);
-  }
-
-  @Override
-  public Diagnostic.Kind nullableValidationKind() {
-    return diagnosticKind(NULLABLE_VALIDATION);
-  }
-
-  @Override
-  public Diagnostic.Kind privateMemberValidationKind() {
-    return diagnosticKind(PRIVATE_MEMBER_VALIDATION);
-  }
-
-  @Override
-  public Diagnostic.Kind staticMemberValidationKind() {
-    return diagnosticKind(STATIC_MEMBER_VALIDATION);
-  }
-
-  @Override
-  public boolean ignorePrivateAndStaticInjectionForComponent() {
-    return isEnabled(IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT);
-  }
-
-  @Override
-  public ValidationType scopeCycleValidationType() {
-    return parseOption(DISABLE_INTER_COMPONENT_SCOPE_VALIDATION);
-  }
-
-  @Override
-  public boolean validateTransitiveComponentDependencies() {
-    return isEnabled(VALIDATE_TRANSITIVE_COMPONENT_DEPENDENCIES);
-  }
-
-  @Override
-  public boolean warnIfInjectionFactoryNotGeneratedUpstream() {
-    return isEnabled(WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM);
-  }
-
-  @Override
-  public ValidationType fullBindingGraphValidationType() {
-    return parseOption(FULL_BINDING_GRAPH_VALIDATION);
-  }
-
-  @Override
-  public boolean pluginsVisitFullBindingGraphs(TypeElement component) {
-    return isEnabled(PLUGINS_VISIT_FULL_BINDING_GRAPHS);
-  }
-
-  @Override
-  public Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind() {
-    return diagnosticKind(MODULE_HAS_DIFFERENT_SCOPES_VALIDATION);
-  }
-
-  @Override
-  public ValidationType explicitBindingConflictsWithInjectValidationType() {
-    return parseOption(EXPLICIT_BINDING_CONFLICTS_WITH_INJECT);
-  }
-
-  @Override
-  public boolean experimentalDaggerErrorMessages() {
-    return isEnabled(EXPERIMENTAL_DAGGER_ERROR_MESSAGES);
-  }
-
-  @Override
-  public boolean strictMultibindingValidation() {
-    return isEnabled(STRICT_MULTIBINDING_VALIDATION);
-  }
-
-  @Override
-  public int keysPerComponentShard(TypeElement component) {
-    if (processingEnvironment.getOptions().containsKey(KEYS_PER_COMPONENT_SHARD)) {
-      checkArgument(
-          "dagger.internal.codegen".contentEquals(
-              MoreElements.getPackage(component).getQualifiedName()),
-          "Cannot set %s. It is only meant for internal testing.", KEYS_PER_COMPONENT_SHARD);
-      return Integer.parseInt(
-          processingEnvironment.getOptions().get(KEYS_PER_COMPONENT_SHARD));
-    }
-    return super.keysPerComponentShard(component);
-  }
-
-  private boolean isEnabled(KeyOnlyOption keyOnlyOption) {
-    return processingEnvironment.getOptions().containsKey(keyOnlyOption.toString());
-  }
-
-  private boolean isEnabled(Feature feature) {
-    return parseOption(feature).equals(ENABLED);
-  }
-
-  private Diagnostic.Kind diagnosticKind(Validation validation) {
-    return parseOption(validation).diagnosticKind().get();
-  }
-
-  @SuppressWarnings("CheckReturnValue")
-  private ProcessingEnvironmentCompilerOptions checkValid() {
-    for (KeyOnlyOption keyOnlyOption : KeyOnlyOption.values()) {
-      isEnabled(keyOnlyOption);
-    }
-    for (Feature feature : Feature.values()) {
-      parseOption(feature);
-    }
-    for (Validation validation : Validation.values()) {
-      parseOption(validation);
-    }
-    noLongerRecognized(EXPERIMENTAL_ANDROID_MODE);
-    noLongerRecognized(FLOATING_BINDS_METHODS);
-    noLongerRecognized(EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS);
-    noLongerRecognized(USE_GRADLE_INCREMENTAL_PROCESSING);
-    return this;
-  }
-
-  private void noLongerRecognized(CommandLineOption commandLineOption) {
-    if (processingEnvironment.getOptions().containsKey(commandLineOption.toString())) {
-      processingEnvironment
-          .getMessager()
-          .printMessage(
-              Diagnostic.Kind.WARNING, commandLineOption + " is no longer recognized by Dagger");
-    }
-  }
-
-  private interface CommandLineOption {
-    /** The key of the option (appears after "-A"). */
-    @Override
-    String toString();
-
-    /**
-     * Returns all aliases besides {@link #toString()}, such as old names for an option, in order of
-     * precedence.
-     */
-    default ImmutableList<String> aliases() {
-      return ImmutableList.of();
-    }
-
-    /** All the command-line names for this option, in order of precedence. */
-    default Stream<String> allNames() {
-      return concat(Stream.of(toString()), aliases().stream());
-    }
-  }
-
-  /** An option that can be set on the command line. */
-  private interface EnumOption<E extends Enum<E>> extends CommandLineOption {
-    /** The default value for this option. */
-    E defaultValue();
-
-    /** The valid values for this option. */
-    Set<E> validValues();
-  }
-
-  enum KeyOnlyOption implements CommandLineOption {
-    HEADER_COMPILATION {
-      @Override
-      public String toString() {
-        return "experimental_turbine_hjar";
-      }
-    },
-
-    USE_GRADLE_INCREMENTAL_PROCESSING {
-      @Override
-      public String toString() {
-        return "dagger.gradle.incremental";
-      }
-    },
-  }
-
-  /**
-   * A feature that can be enabled or disabled on the command line by setting {@code -Akey=ENABLED}
-   * or {@code -Akey=DISABLED}.
-   */
-  enum Feature implements EnumOption<FeatureStatus> {
-    FAST_INIT,
-
-    EXPERIMENTAL_ANDROID_MODE,
-
-    FORMAT_GENERATED_SOURCE,
-
-    WRITE_PRODUCER_NAME_IN_TOKEN,
-
-    WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM,
-
-    IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT,
-
-    EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS,
-
-    FORCE_USE_SERIALIZED_COMPONENT_IMPLEMENTATIONS,
-
-    EMIT_MODIFIABLE_METADATA_ANNOTATIONS(ENABLED),
-
-    PLUGINS_VISIT_FULL_BINDING_GRAPHS,
-
-    FLOATING_BINDS_METHODS,
-
-    EXPERIMENTAL_DAGGER_ERROR_MESSAGES,
-
-    STRICT_MULTIBINDING_VALIDATION,
-
-    VALIDATE_TRANSITIVE_COMPONENT_DEPENDENCIES(ENABLED)
-    ;
-
-    final FeatureStatus defaultValue;
-
-    Feature() {
-      this(DISABLED);
-    }
-
-    Feature(FeatureStatus defaultValue) {
-      this.defaultValue = defaultValue;
-    }
-
-    @Override
-    public FeatureStatus defaultValue() {
-      return defaultValue;
-    }
-
-    @Override
-    public Set<FeatureStatus> validValues() {
-      return EnumSet.allOf(FeatureStatus.class);
-    }
-
-    @Override
-    public String toString() {
-      return optionName(this);
-    }
-  }
-
-  /** The diagnostic kind or validation type for a kind of validation. */
-  enum Validation implements EnumOption<ValidationType> {
-    DISABLE_INTER_COMPONENT_SCOPE_VALIDATION(),
-
-    NULLABLE_VALIDATION(ERROR, WARNING),
-
-    PRIVATE_MEMBER_VALIDATION(ERROR, WARNING),
-
-    STATIC_MEMBER_VALIDATION(ERROR, WARNING),
-
-    /** Whether to validate full binding graphs for components, subcomponents, and modules. */
-    FULL_BINDING_GRAPH_VALIDATION(NONE, ERROR, WARNING) {
-      @Override
-      public ImmutableList<String> aliases() {
-        return ImmutableList.of("dagger.moduleBindingValidation");
-      }
-    },
-
-    /**
-     * How to report conflicting scoped bindings when validating partial binding graphs associated
-     * with modules.
-     */
-    MODULE_HAS_DIFFERENT_SCOPES_VALIDATION(ERROR, WARNING),
-
-    /**
-     * How to report that an explicit binding in a subcomponent conflicts with an {@code @Inject}
-     * constructor used in an ancestor component.
-     */
-    EXPLICIT_BINDING_CONFLICTS_WITH_INJECT(WARNING, ERROR, NONE),
-    ;
-
-    final ValidationType defaultType;
-    final ImmutableSet<ValidationType> validTypes;
-
-    Validation() {
-      this(ERROR, WARNING, NONE);
-    }
-
-    Validation(ValidationType defaultType, ValidationType... moreValidTypes) {
-      this.defaultType = defaultType;
-      this.validTypes = immutableEnumSet(defaultType, moreValidTypes);
-    }
-
-    @Override
-    public ValidationType defaultValue() {
-      return defaultType;
-    }
-
-    @Override
-    public Set<ValidationType> validValues() {
-      return validTypes;
-    }
-
-    @Override
-    public String toString() {
-      return optionName(this);
-    }
-  }
-
-  private static String optionName(Enum<? extends EnumOption<?>> option) {
-    return "dagger." + UPPER_UNDERSCORE.to(LOWER_CAMEL, option.name());
-  }
-
-  /** The supported command-line options. */
-  public static ImmutableSet<String> supportedOptions() {
-    // need explicit type parameter to avoid a runtime stream error
-    return ImmutableSet.<String>builder()
-        .addAll(
-            Stream.<CommandLineOption[]>of(
-                KeyOnlyOption.values(), Feature.values(), Validation.values())
-            .flatMap(Arrays::stream)
-            .flatMap(CommandLineOption::allNames)
-            .collect(toImmutableSet()))
-        .add(KEYS_PER_COMPONENT_SHARD)
-        .build();
-  }
-
-  /**
-   * Returns the value for the option as set on the command line by any name, or the default value
-   * if not set.
-   *
-   * <p>If more than one name is used to set the value, but all names specify the same value,
-   * reports a warning and returns that value.
-   *
-   * <p>If more than one name is used to set the value, and not all names specify the same value,
-   * reports an error and returns the default value.
-   */
-  private <T extends Enum<T>> T parseOption(EnumOption<T> option) {
-    @SuppressWarnings("unchecked") // we only put covariant values into the map
-    T value = (T) enumOptions.computeIfAbsent(option, this::parseOptionUncached);
-    return value;
-  }
-
-  private boolean isSetOnCommandLine(Feature feature) {
-    return getUsedNames(feature).count() > 0;
-  }
-
-  private <T extends Enum<T>> T parseOptionUncached(EnumOption<T> option) {
-    ImmutableMap<String, T> values = parseOptionWithAllNames(option);
-
-    // If no value is specified, return the default value.
-    if (values.isEmpty()) {
-      return option.defaultValue();
-    }
-
-    // If all names have the same value, return that.
-    if (values.asMultimap().inverse().keySet().size() == 1) {
-      // Warn if an option was set with more than one name. That would be an error if the values
-      // differed.
-      if (values.size() > 1) {
-        reportUseOfDifferentNamesForOption(Diagnostic.Kind.WARNING, option, values.keySet());
-      }
-      return values.values().asList().get(0);
-    }
-
-    // If different names have different values, report an error and return the default
-    // value.
-    reportUseOfDifferentNamesForOption(Diagnostic.Kind.ERROR, option, values.keySet());
-    return option.defaultValue();
-  }
-
-  private void reportUseOfDifferentNamesForOption(
-      Diagnostic.Kind diagnosticKind, EnumOption<?> option, ImmutableSet<String> usedNames) {
-    processingEnvironment
-        .getMessager()
-        .printMessage(
-            diagnosticKind,
-            String.format(
-                "Only one of the equivalent options (%s) should be used; prefer -A%s",
-                usedNames.stream().map(name -> "-A" + name).collect(joining(", ")), option));
-  }
-
-  private <T extends Enum<T>> ImmutableMap<String, T> parseOptionWithAllNames(
-      EnumOption<T> option) {
-    @SuppressWarnings("unchecked") // map is covariant
-    ImmutableMap<String, T> aliasValues =
-        (ImmutableMap<String, T>)
-            allCommandLineOptions.computeIfAbsent(option, this::parseOptionWithAllNamesUncached);
-    return aliasValues;
-  }
-
-  private <T extends Enum<T>> ImmutableMap<String, T> parseOptionWithAllNamesUncached(
-      EnumOption<T> option) {
-    ImmutableMap.Builder<String, T> values = ImmutableMap.builder();
-    getUsedNames(option)
-        .forEach(
-            name -> parseOptionWithName(option, name).ifPresent(value -> values.put(name, value)));
-    return values.build();
-  }
-
-  private <T extends Enum<T>> Optional<T> parseOptionWithName(EnumOption<T> option, String key) {
-    checkArgument(processingEnvironment.getOptions().containsKey(key), "key %s not found", key);
-    String stringValue = processingEnvironment.getOptions().get(key);
-    if (stringValue == null) {
-      processingEnvironment
-          .getMessager()
-          .printMessage(Diagnostic.Kind.ERROR, "Processor option -A" + key + " needs a value");
-    } else {
-      try {
-        T value =
-            Enum.valueOf(option.defaultValue().getDeclaringClass(), Ascii.toUpperCase(stringValue));
-        if (option.validValues().contains(value)) {
-          return Optional.of(value);
-        }
-      } catch (IllegalArgumentException e) {
-        // handled below
-      }
-      processingEnvironment
-          .getMessager()
-          .printMessage(
-              Diagnostic.Kind.ERROR,
-              String.format(
-                  "Processor option -A%s may only have the values %s "
-                      + "(case insensitive), found: %s",
-                  key, option.validValues(), stringValue));
-    }
-    return Optional.empty();
-  }
-
-  private Stream<String> getUsedNames(CommandLineOption option) {
-    return option.allNames().filter(name -> processingEnvironment.getOptions().containsKey(name));
-  }
-}
diff --git a/java/dagger/internal/codegen/compileroption/ProcessingOptions.java b/java/dagger/internal/codegen/compileroption/ProcessingOptions.java
deleted file mode 100644
index 39c4728..0000000
--- a/java/dagger/internal/codegen/compileroption/ProcessingOptions.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.compileroption;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/**
- * A qualifier for the {@link javax.annotation.processing.ProcessingEnvironment#getOptions()
- * processing options} passed to the current invocation of {@code javac}.
- */
-@Retention(RUNTIME)
-@Qualifier
-public @interface ProcessingOptions {}
diff --git a/java/dagger/internal/codegen/compileroption/ValidationType.java b/java/dagger/internal/codegen/compileroption/ValidationType.java
deleted file mode 100644
index d7be4ca..0000000
--- a/java/dagger/internal/codegen/compileroption/ValidationType.java
+++ /dev/null
@@ -1,41 +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.compileroption;
-
-import java.util.Optional;
-import javax.tools.Diagnostic;
-
-/**
- * Allows options to control how component process validates things such as scope cycles or
- * nullability.
- */
-public enum ValidationType {
-  ERROR,
-  WARNING,
-  NONE;
-
-  public Optional<Diagnostic.Kind> diagnosticKind() {
-    switch (this) {
-      case ERROR:
-        return Optional.of(Diagnostic.Kind.ERROR);
-      case WARNING:
-        return Optional.of(Diagnostic.Kind.WARNING);
-      default:
-        return Optional.empty();
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/BUILD b/java/dagger/internal/codegen/componentgenerator/BUILD
deleted file mode 100644
index d898d4d..0000000
--- a/java/dagger/internal/codegen/componentgenerator/BUILD
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   A JSR-330 compliant dependency injection system for android and java
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "componentgenerator",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    deps = [
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/codegen/writing",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentCreatorImplementationFactory.java b/java/dagger/internal/codegen/componentgenerator/ComponentCreatorImplementationFactory.java
deleted file mode 100644
index e1b35da..0000000
--- a/java/dagger/internal/codegen/componentgenerator/ComponentCreatorImplementationFactory.java
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * Copyright (C) 2017 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.componentgenerator;
-
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.binding.SourceFiles.simpleVariableName;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeSpecs.addSupertype;
-import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.Preconditions;
-import dagger.internal.codegen.base.UniqueNameSet;
-import dagger.internal.codegen.binding.ComponentCreatorDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.ComponentRequirement.NullPolicy;
-import dagger.internal.codegen.javapoet.TypeNames;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.writing.ComponentCreatorImplementation;
-import dagger.internal.codegen.writing.ComponentImplementation;
-import dagger.internal.codegen.writing.ModuleProxies;
-import java.util.Optional;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeKind;
-
-/** Factory for creating {@link ComponentCreatorImplementation} instances. */
-final class ComponentCreatorImplementationFactory {
-
-  private final ComponentImplementation componentImplementation;
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final KotlinMetadataUtil metadataUtil;
-  private final ModuleProxies moduleProxies;
-
-  @Inject
-  ComponentCreatorImplementationFactory(
-      ComponentImplementation componentImplementation,
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil metadataUtil,
-      ModuleProxies moduleProxies) {
-    this.componentImplementation = componentImplementation;
-    this.elements = elements;
-    this.types = types;
-    this.metadataUtil = metadataUtil;
-    this.moduleProxies = moduleProxies;
-  }
-
-  /** Returns a new creator implementation for the given component, if necessary. */
-  Optional<ComponentCreatorImplementation> create() {
-    if (!componentImplementation.componentDescriptor().hasCreator()) {
-      return Optional.empty();
-    }
-
-    Optional<ComponentCreatorDescriptor> creatorDescriptor =
-        componentImplementation.componentDescriptor().creatorDescriptor();
-
-    Builder builder =
-        creatorDescriptor.isPresent()
-            ? new BuilderForCreatorDescriptor(componentImplementation, creatorDescriptor.get())
-            : new BuilderForGeneratedRootComponentBuilder(componentImplementation);
-    return Optional.of(builder.build());
-  }
-
-  /** Base class for building a creator implementation. */
-  private abstract class Builder {
-    final ComponentImplementation componentImplementation;
-    final ClassName className;
-    final TypeSpec.Builder classBuilder;
-
-    private ImmutableMap<ComponentRequirement, FieldSpec> fields;
-
-    Builder(ComponentImplementation componentImplementation) {
-      this.componentImplementation = componentImplementation;
-      this.className = componentImplementation.getCreatorName();
-      this.classBuilder = classBuilder(className);
-    }
-
-    /** Builds the {@link ComponentCreatorImplementation}. */
-    ComponentCreatorImplementation build() {
-      setModifiers();
-      setSupertype();
-      this.fields = addFields();
-      addConstructor();
-      addSetterMethods();
-      addFactoryMethod();
-      return ComponentCreatorImplementation.create(classBuilder.build(), className, fields);
-    }
-
-    /** Returns the descriptor for the component. */
-    final ComponentDescriptor componentDescriptor() {
-      return componentImplementation.componentDescriptor();
-    }
-
-    /**
-     * The set of requirements that must be passed to the component's constructor in the order
-     * they must be passed.
-     */
-    final ImmutableSet<ComponentRequirement> componentConstructorRequirements() {
-      return componentImplementation.graph().componentRequirements();
-    }
-
-    /** Returns the requirements that have setter methods on the creator type. */
-    abstract ImmutableSet<ComponentRequirement> setterMethods();
-
-    /**
-     * Returns the component requirements that have factory method parameters, mapped to the name
-     * for that parameter.
-     */
-    abstract ImmutableMap<ComponentRequirement, String> factoryMethodParameters();
-
-    /**
-     * The {@link ComponentRequirement}s that this creator allows users to set. Values are a status
-     * for each requirement indicating what's needed for that requirement in the implementation
-     * class currently being generated.
-     */
-    abstract ImmutableMap<ComponentRequirement, RequirementStatus> userSettableRequirements();
-
-    /**
-     * Component requirements that are both settable by the creator and needed to construct the
-     * component.
-     */
-    private Set<ComponentRequirement> neededUserSettableRequirements() {
-      return Sets.intersection(
-          userSettableRequirements().keySet(), componentConstructorRequirements());
-    }
-
-    private void setModifiers() {
-      visibility().ifPresent(classBuilder::addModifiers);
-      if (!componentImplementation.isNested()) {
-        classBuilder.addModifiers(STATIC);
-      }
-      classBuilder.addModifiers(FINAL);
-    }
-
-    /** Returns the visibility modifier the generated class should have, if any. */
-    protected abstract Optional<Modifier> visibility();
-
-    /** Sets the superclass being extended or interface being implemented for this creator. */
-    protected abstract void setSupertype();
-
-    /** Adds a constructor for the creator type, if needed. */
-    protected abstract void addConstructor();
-
-    private ImmutableMap<ComponentRequirement, FieldSpec> addFields() {
-      // Fields in an abstract creator class need to be visible from subclasses.
-      UniqueNameSet fieldNames = new UniqueNameSet();
-      ImmutableMap<ComponentRequirement, FieldSpec> result =
-          Maps.toMap(
-              Sets.intersection(neededUserSettableRequirements(), setterMethods()),
-              requirement ->
-                  FieldSpec.builder(
-                          TypeName.get(requirement.type()),
-                          fieldNames.getUniqueName(requirement.variableName()),
-                          PRIVATE)
-                      .build());
-      classBuilder.addFields(result.values());
-      return result;
-    }
-
-    private void addSetterMethods() {
-      Maps.filterKeys(userSettableRequirements(), setterMethods()::contains)
-          .forEach(
-              (requirement, status) ->
-                  createSetterMethod(requirement, status).ifPresent(classBuilder::addMethod));
-    }
-
-    /** Creates a new setter method builder, with no method body, for the given requirement. */
-    protected abstract MethodSpec.Builder setterMethodBuilder(ComponentRequirement requirement);
-
-    private Optional<MethodSpec> createSetterMethod(
-        ComponentRequirement requirement, RequirementStatus status) {
-      switch (status) {
-        case NEEDED:
-          return Optional.of(normalSetterMethod(requirement));
-        case UNNEEDED:
-          // TODO(bcorso): Don't generate noop setters for any unneeded requirements.
-          // However, since this is a breaking change we can at least avoid trying
-          // to generate noop setters for impossible cases like when the requirement type
-          // is in another package. This avoids unnecessary breakages in Dagger's generated
-          // due to the noop setters.
-          if (isElementAccessibleFrom(requirement.typeElement(), className.packageName())) {
-            return Optional.of(noopSetterMethod(requirement));
-          } else {
-            return Optional.empty();
-          }
-        case UNSETTABLE_REPEATED_MODULE:
-          return Optional.of(repeatedModuleSetterMethod(requirement));
-      }
-      throw new AssertionError();
-    }
-
-    private MethodSpec normalSetterMethod(ComponentRequirement requirement) {
-      MethodSpec.Builder method = setterMethodBuilder(requirement);
-      ParameterSpec parameter = parameter(method.build());
-      method.addStatement(
-          "this.$N = $L",
-          fields.get(requirement),
-          requirement.nullPolicy(elements, types, metadataUtil).equals(NullPolicy.ALLOW)
-              ? CodeBlock.of("$N", parameter)
-              : CodeBlock.of("$T.checkNotNull($N)", Preconditions.class, parameter));
-      return maybeReturnThis(method);
-    }
-
-    private MethodSpec noopSetterMethod(ComponentRequirement requirement) {
-      MethodSpec.Builder method = setterMethodBuilder(requirement);
-      ParameterSpec parameter = parameter(method.build());
-      method
-          .addAnnotation(Deprecated.class)
-          .addJavadoc(
-              "@deprecated This module is declared, but an instance is not used in the component. "
-                  + "This method is a no-op. For more, see https://dagger.dev/unused-modules.\n")
-          .addStatement("$T.checkNotNull($N)", Preconditions.class, parameter);
-      return maybeReturnThis(method);
-    }
-
-    private MethodSpec repeatedModuleSetterMethod(ComponentRequirement requirement) {
-      return setterMethodBuilder(requirement)
-          .addStatement(
-              "throw new $T($T.format($S, $T.class.getCanonicalName()))",
-              UnsupportedOperationException.class,
-              String.class,
-              "%s cannot be set because it is inherited from the enclosing component",
-              TypeNames.rawTypeName(TypeName.get(requirement.type())))
-          .build();
-    }
-
-    private ParameterSpec parameter(MethodSpec method) {
-      return getOnlyElement(method.parameters);
-    }
-
-    private MethodSpec maybeReturnThis(MethodSpec.Builder method) {
-      MethodSpec built = method.build();
-      return built.returnType.equals(TypeName.VOID)
-          ? built
-          : method.addStatement("return this").build();
-    }
-
-    private void addFactoryMethod() {
-      classBuilder.addMethod(factoryMethod());
-    }
-
-    MethodSpec factoryMethod() {
-      MethodSpec.Builder factoryMethod = factoryMethodBuilder();
-      factoryMethod
-          .returns(ClassName.get(componentDescriptor().typeElement()))
-          .addModifiers(PUBLIC);
-
-      ImmutableMap<ComponentRequirement, String> factoryMethodParameters =
-          factoryMethodParameters();
-      userSettableRequirements()
-          .keySet()
-          .forEach(
-              requirement -> {
-                if (fields.containsKey(requirement)) {
-                  FieldSpec field = fields.get(requirement);
-                  addNullHandlingForField(requirement, field, factoryMethod);
-                } else if (factoryMethodParameters.containsKey(requirement)) {
-                  String parameterName = factoryMethodParameters.get(requirement);
-                  addNullHandlingForParameter(requirement, parameterName, factoryMethod);
-                }
-              });
-      factoryMethod.addStatement(
-          "return new $T($L)",
-          componentImplementation.name(),
-          componentConstructorArgs(factoryMethodParameters));
-      return factoryMethod.build();
-    }
-
-    private void addNullHandlingForField(
-        ComponentRequirement requirement, FieldSpec field, MethodSpec.Builder factoryMethod) {
-      switch (requirement.nullPolicy(elements, types, metadataUtil)) {
-        case NEW:
-          checkState(requirement.kind().isModule());
-          factoryMethod
-              .beginControlFlow("if ($N == null)", field)
-              .addStatement("this.$N = $L", field, newModuleInstance(requirement))
-              .endControlFlow();
-          break;
-        case THROW:
-          // TODO(cgdecker,ronshapiro): ideally this should use the key instead of a class for
-          // @BindsInstance requirements, but that's not easily proguardable.
-          factoryMethod.addStatement(
-              "$T.checkBuilderRequirement($N, $T.class)",
-              Preconditions.class,
-              field,
-              TypeNames.rawTypeName(field.type));
-          break;
-        case ALLOW:
-          break;
-      }
-    }
-
-    private void addNullHandlingForParameter(
-        ComponentRequirement requirement, String parameter, MethodSpec.Builder factoryMethod) {
-      if (!requirement.nullPolicy(elements, types, metadataUtil).equals(NullPolicy.ALLOW)) {
-        // Factory method parameters are always required unless they are a nullable
-        // binds-instance (i.e. ALLOW)
-        factoryMethod.addStatement("$T.checkNotNull($L)", Preconditions.class, parameter);
-      }
-    }
-
-    /** Returns a builder for the creator's factory method. */
-    protected abstract MethodSpec.Builder factoryMethodBuilder();
-
-    private CodeBlock componentConstructorArgs(
-        ImmutableMap<ComponentRequirement, String> factoryMethodParameters) {
-      return componentConstructorRequirements().stream()
-          .map(
-              requirement -> {
-                if (fields.containsKey(requirement)) {
-                  return CodeBlock.of("$N", fields.get(requirement));
-                } else if (factoryMethodParameters.containsKey(requirement)) {
-                  return CodeBlock.of("$L", factoryMethodParameters.get(requirement));
-                } else {
-                  return newModuleInstance(requirement);
-                }
-              })
-          .collect(toParametersCodeBlock());
-    }
-
-    private CodeBlock newModuleInstance(ComponentRequirement requirement) {
-      checkArgument(requirement.kind().isModule()); // this should be guaranteed to be true here
-      return moduleProxies.newModuleInstance(requirement.typeElement(), className);
-    }
-  }
-
-  /** Builder for a creator type defined by a {@code ComponentCreatorDescriptor}. */
-  private final class BuilderForCreatorDescriptor extends Builder {
-    final ComponentCreatorDescriptor creatorDescriptor;
-
-    BuilderForCreatorDescriptor(
-        ComponentImplementation componentImplementation,
-        ComponentCreatorDescriptor creatorDescriptor) {
-      super(componentImplementation);
-      this.creatorDescriptor = creatorDescriptor;
-    }
-
-    @Override
-    protected ImmutableMap<ComponentRequirement, RequirementStatus> userSettableRequirements() {
-      return Maps.toMap(creatorDescriptor.userSettableRequirements(), this::requirementStatus);
-    }
-
-    @Override
-    protected Optional<Modifier> visibility() {
-      return Optional.of(PRIVATE);
-    }
-
-    @Override
-    protected void setSupertype() {
-      addSupertype(classBuilder, creatorDescriptor.typeElement());
-    }
-
-    @Override
-    protected void addConstructor() {
-      // Just use the implicit no-arg public constructor.
-    }
-
-    @Override
-    protected ImmutableSet<ComponentRequirement> setterMethods() {
-      return ImmutableSet.copyOf(creatorDescriptor.setterMethods().keySet());
-    }
-
-    @Override
-    protected ImmutableMap<ComponentRequirement, String> factoryMethodParameters() {
-      return ImmutableMap.copyOf(
-          Maps.transformValues(
-              creatorDescriptor.factoryParameters(),
-              element -> element.getSimpleName().toString()));
-    }
-
-    private DeclaredType creatorType() {
-      return asDeclared(creatorDescriptor.typeElement().asType());
-    }
-
-    @Override
-    protected MethodSpec.Builder factoryMethodBuilder() {
-      return MethodSpec.overriding(creatorDescriptor.factoryMethod(), creatorType(), types);
-    }
-
-    private RequirementStatus requirementStatus(ComponentRequirement requirement) {
-      if (isRepeatedModule(requirement)) {
-        return RequirementStatus.UNSETTABLE_REPEATED_MODULE;
-      }
-
-      return componentConstructorRequirements().contains(requirement)
-          ? RequirementStatus.NEEDED
-          : RequirementStatus.UNNEEDED;
-    }
-
-    /**
-     * Returns whether the given requirement is for a repeat of a module inherited from an ancestor
-     * component. This creator is not allowed to set such a module.
-     */
-    final boolean isRepeatedModule(ComponentRequirement requirement) {
-      return !componentConstructorRequirements().contains(requirement)
-          && !isOwnedModule(requirement);
-    }
-
-    /**
-     * Returns whether the given {@code requirement} is for a module type owned by the component.
-     */
-    private boolean isOwnedModule(ComponentRequirement requirement) {
-      return componentImplementation.graph().ownedModuleTypes().contains(requirement.typeElement());
-    }
-
-    @Override
-    protected MethodSpec.Builder setterMethodBuilder(ComponentRequirement requirement) {
-      ExecutableElement supertypeMethod = creatorDescriptor.setterMethods().get(requirement);
-      MethodSpec.Builder method = MethodSpec.overriding(supertypeMethod, creatorType(), types);
-      if (!supertypeMethod.getReturnType().getKind().equals(TypeKind.VOID)) {
-        // Take advantage of covariant returns so that we don't have to worry about type variables
-        method.returns(className);
-      }
-      return method;
-    }
-  }
-
-  /**
-   * Builder for a component builder class that is automatically generated for a root component that
-   * does not have its own user-defined creator type (i.e. a {@code ComponentCreatorDescriptor}).
-   */
-  private final class BuilderForGeneratedRootComponentBuilder extends Builder {
-    BuilderForGeneratedRootComponentBuilder(ComponentImplementation componentImplementation) {
-      super(componentImplementation);
-    }
-
-    @Override
-    protected ImmutableMap<ComponentRequirement, RequirementStatus> userSettableRequirements() {
-      return Maps.toMap(
-          setterMethods(),
-          requirement ->
-              componentConstructorRequirements().contains(requirement)
-                  ? RequirementStatus.NEEDED
-                  : RequirementStatus.UNNEEDED);
-    }
-
-    @Override
-    protected Optional<Modifier> visibility() {
-      return componentImplementation
-          .componentDescriptor()
-          .typeElement()
-          .getModifiers()
-          .contains(PUBLIC) ? Optional.of(PUBLIC) : Optional.empty();
-    }
-
-    @Override
-    protected void setSupertype() {
-      // There's never a supertype for a root component auto-generated builder type.
-    }
-
-    @Override
-    protected void addConstructor() {
-      classBuilder.addMethod(constructorBuilder().addModifiers(PRIVATE).build());
-    }
-
-    @Override
-    protected ImmutableSet<ComponentRequirement> setterMethods() {
-      return componentDescriptor().dependenciesAndConcreteModules();
-    }
-
-    @Override
-    protected ImmutableMap<ComponentRequirement, String> factoryMethodParameters() {
-      return ImmutableMap.of();
-    }
-
-    @Override
-    protected MethodSpec.Builder factoryMethodBuilder() {
-      return methodBuilder("build");
-    }
-
-    @Override
-    protected MethodSpec.Builder setterMethodBuilder(ComponentRequirement requirement) {
-      String name = simpleVariableName(requirement.typeElement());
-      return methodBuilder(name)
-          .addModifiers(PUBLIC)
-          .addParameter(TypeName.get(requirement.type()), name)
-          .returns(className);
-    }
-  }
-
-  /** Enumeration of statuses a component requirement may have in a creator. */
-  enum RequirementStatus {
-    /** An instance is needed to create the component. */
-    NEEDED,
-
-    /**
-     * An instance is not needed to create the component, but the requirement is for a module owned
-     * by the component. Setting the requirement is a no-op and any setter method should be marked
-     * deprecated on the generated type as a warning to the user.
-     */
-    UNNEEDED,
-
-    /**
-     * The requirement may not be set in this creator because the module it is for is already
-     * inherited from an ancestor component. Any setter method for it should throw an exception.
-     */
-    UNSETTABLE_REPEATED_MODULE,
-    ;
-  }
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentGenerator.java b/java/dagger/internal/codegen/componentgenerator/ComponentGenerator.java
deleted file mode 100644
index e04ee14..0000000
--- a/java/dagger/internal/codegen/componentgenerator/ComponentGenerator.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2014 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.componentgenerator;
-
-import static com.google.common.base.Verify.verify;
-import static dagger.internal.codegen.binding.SourceFiles.classFileName;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.Component;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.writing.ComponentImplementation;
-import java.util.Optional;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-/** Generates the implementation of the abstract types annotated with {@link Component}. */
-final class ComponentGenerator extends SourceFileGenerator<BindingGraph> {
-  private final ComponentImplementationFactory componentImplementationFactory;
-
-  @Inject
-  ComponentGenerator(
-      Filer filer,
-      DaggerElements elements,
-      SourceVersion sourceVersion,
-      ComponentImplementationFactory componentImplementationFactory) {
-    super(filer, elements, sourceVersion);
-    this.componentImplementationFactory = componentImplementationFactory;
-  }
-
-  @Override
-  public ClassName nameGeneratedType(BindingGraph input) {
-    return componentName(input.componentTypeElement());
-  }
-
-  static ClassName componentName(TypeElement componentDefinitionType) {
-    ClassName componentName = ClassName.get(componentDefinitionType);
-    return ClassName.get(componentName.packageName(), "Dagger" + classFileName(componentName));
-  }
-
-  @Override
-  public Element originatingElement(BindingGraph input) {
-    return input.componentTypeElement();
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(BindingGraph bindingGraph) {
-    ComponentImplementation componentImplementation =
-        componentImplementationFactory.createComponentImplementation(bindingGraph);
-    verify(componentImplementation.name().equals(nameGeneratedType(bindingGraph)));
-    return Optional.of(componentImplementation.generate());
-  }
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentGeneratorModule.java b/java/dagger/internal/codegen/componentgenerator/ComponentGeneratorModule.java
deleted file mode 100644
index 84179d6..0000000
--- a/java/dagger/internal/codegen/componentgenerator/ComponentGeneratorModule.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 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.componentgenerator;
-
-import dagger.Binds;
-import dagger.Module;
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.multibindings.IntoSet;
-
-/** Provides bindings needed to generated the component. */
-@Module(subcomponents = TopLevelImplementationComponent.class)
-public interface ComponentGeneratorModule {
-
-  @Binds
-  abstract SourceFileGenerator<BindingGraph> componentGenerator(ComponentGenerator generator);
-
-  // The HjarSourceFileGenerator wrapper first generates the entire TypeSpec before stripping out
-  // things that aren't needed for the hjar. However, this can be really expensive for the component
-  // because it is usually the most expensive file to generate, and most of its content is not
-  // needed in the hjar. Thus, instead of wrapping the ComponentGenerator in HjarSourceFileGenerator
-  // we provide a completely separate processing step, ComponentHjarProcessingStep, and generator,
-  // ComponentHjarGenerator, for when generating hjars for components, which can avoid generating
-  // the parts of the component that would have been stripped out by the HjarSourceFileGenerator.
-  @Binds
-  abstract SourceFileGenerator<ComponentDescriptor> componentHjarGenerator(
-      ComponentHjarGenerator hjarGenerator);
-
-  @Binds
-  @IntoSet
-  ClearableCache componentImplementationFactory(ComponentImplementationFactory cache);
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java b/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java
deleted file mode 100644
index b386a4f..0000000
--- a/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2020 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.componentgenerator;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static dagger.internal.codegen.binding.ComponentCreatorKind.BUILDER;
-import static dagger.internal.codegen.componentgenerator.ComponentGenerator.componentName;
-import static dagger.internal.codegen.javapoet.TypeSpecs.addSupertype;
-import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.base.Ascii;
-import com.google.common.collect.Sets;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.BindsInstance;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.ComponentCreatorDescriptor;
-import dagger.internal.codegen.binding.ComponentCreatorKind;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.producers.internal.CancellationListener;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Stream;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-
-/**
- * A component generator that emits only API, without any actual implementation.
- *
- * <p>When compiling a header jar (hjar), Bazel needs to run annotation processors that generate
- * API, like Dagger, to see what code they might output. Full binding graph analysis is costly and
- * unnecessary from the perspective of the header compiler; it's sole goal is to pass along a
- * slimmed down version of what will be the jar for a particular compilation, whether or not that
- * compilation succeeds. If it does not, the compilation pipeline will fail, even if header
- * compilation succeeded.
- *
- * <p>The components emitted by this processing step include all of the API elements exposed by the
- * normal step. Method bodies are omitted as Turbine ignores them entirely.
- */
-final class ComponentHjarGenerator extends SourceFileGenerator<ComponentDescriptor> {
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final KotlinMetadataUtil metadataUtil;
-
-  @Inject
-  ComponentHjarGenerator(
-      Filer filer,
-      DaggerElements elements,
-      DaggerTypes types,
-      SourceVersion sourceVersion,
-      KotlinMetadataUtil metadataUtil) {
-    super(filer, elements, sourceVersion);
-    this.elements = elements;
-    this.types = types;
-    this.metadataUtil = metadataUtil;
-  }
-
-  @Override
-  public ClassName nameGeneratedType(ComponentDescriptor input) {
-    return componentName(input.typeElement());
-  }
-
-  @Override
-  public Element originatingElement(ComponentDescriptor input) {
-    return input.typeElement();
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(ComponentDescriptor componentDescriptor) {
-    ClassName generatedTypeName = nameGeneratedType(componentDescriptor);
-    TypeSpec.Builder generatedComponent =
-        TypeSpec.classBuilder(generatedTypeName)
-            .addModifiers(FINAL)
-            .addMethod(privateConstructor());
-    if (componentDescriptor.typeElement().getModifiers().contains(PUBLIC)) {
-      generatedComponent.addModifiers(PUBLIC);
-    }
-
-    TypeElement componentElement = componentDescriptor.typeElement();
-    addSupertype(generatedComponent, componentElement);
-
-    TypeName builderMethodReturnType;
-    ComponentCreatorKind creatorKind;
-    boolean noArgFactoryMethod;
-    if (componentDescriptor.creatorDescriptor().isPresent()) {
-      ComponentCreatorDescriptor creatorDescriptor = componentDescriptor.creatorDescriptor().get();
-      builderMethodReturnType = ClassName.get(creatorDescriptor.typeElement());
-      creatorKind = creatorDescriptor.kind();
-      noArgFactoryMethod = creatorDescriptor.factoryParameters().isEmpty();
-    } else {
-      TypeSpec.Builder builder =
-          TypeSpec.classBuilder("Builder")
-              .addModifiers(STATIC, FINAL)
-              .addMethod(privateConstructor());
-      if (componentDescriptor.typeElement().getModifiers().contains(PUBLIC)) {
-        builder.addModifiers(PUBLIC);
-      }
-
-      ClassName builderClassName = generatedTypeName.nestedClass("Builder");
-      builderMethodReturnType = builderClassName;
-      creatorKind = BUILDER;
-      noArgFactoryMethod = true;
-      componentRequirements(componentDescriptor)
-          .map(requirement -> builderSetterMethod(requirement.typeElement(), builderClassName))
-          .forEach(builder::addMethod);
-      builder.addMethod(builderBuildMethod(componentDescriptor));
-      generatedComponent.addType(builder.build());
-    }
-
-    generatedComponent.addMethod(staticCreatorMethod(builderMethodReturnType, creatorKind));
-
-    if (noArgFactoryMethod
-        && !hasBindsInstanceMethods(componentDescriptor)
-        && componentRequirements(componentDescriptor)
-            .noneMatch(
-                requirement ->
-                    requirement.requiresAPassedInstance(elements, types, metadataUtil))) {
-      generatedComponent.addMethod(createMethod(componentDescriptor));
-    }
-
-    DeclaredType componentType = MoreTypes.asDeclared(componentElement.asType());
-    // TODO(ronshapiro): unify with ComponentImplementationBuilder
-    Set<MethodSignature> methodSignatures =
-        Sets.newHashSetWithExpectedSize(componentDescriptor.componentMethods().size());
-    componentDescriptor.componentMethods().stream()
-        .filter(
-            method -> {
-              return methodSignatures.add(
-                  MethodSignature.forComponentMethod(method, componentType, types));
-            })
-        .forEach(
-            method ->
-                generatedComponent.addMethod(
-                    emptyComponentMethod(componentElement, method.methodElement())));
-
-    if (componentDescriptor.isProduction()) {
-      generatedComponent
-          .addSuperinterface(ClassName.get(CancellationListener.class))
-          .addMethod(onProducerFutureCancelledMethod());
-    }
-
-    return Optional.of(generatedComponent);
-  }
-
-  private MethodSpec emptyComponentMethod(TypeElement typeElement, ExecutableElement baseMethod) {
-    return MethodSpec.overriding(baseMethod, MoreTypes.asDeclared(typeElement.asType()), types)
-        .build();
-  }
-
-  private static MethodSpec privateConstructor() {
-    return constructorBuilder().addModifiers(PRIVATE).build();
-  }
-
-  /**
-   * Returns the {@link ComponentRequirement}s for a component that does not have a {@link
-   * ComponentDescriptor#creatorDescriptor()}.
-   */
-  private static Stream<ComponentRequirement> componentRequirements(ComponentDescriptor component) {
-    // TODO(b/152802759): See if you can merge logics that normal component processing and hjar
-    // component processing use. So that there would't be a duplicated logic (like the lines below)
-    // everytime we modify the generated code for the component.
-    checkArgument(!component.isSubcomponent());
-    return Stream.concat(
-        component.dependencies().stream(),
-        component.modules().stream()
-            .filter(
-                module ->
-                    !module.moduleElement().getModifiers().contains(ABSTRACT)
-                        && isElementAccessibleFrom(
-                            module.moduleElement(),
-                            ClassName.get(component.typeElement()).packageName()))
-            .map(module -> ComponentRequirement.forModule(module.moduleElement().asType())));
-  }
-
-  private boolean hasBindsInstanceMethods(ComponentDescriptor componentDescriptor) {
-    return componentDescriptor.creatorDescriptor().isPresent()
-        && elements
-            .getUnimplementedMethods(componentDescriptor.creatorDescriptor().get().typeElement())
-            .stream()
-            .anyMatch(method -> isBindsInstance(method));
-  }
-
-  private static boolean isBindsInstance(ExecutableElement method) {
-    if (isAnnotationPresent(method, BindsInstance.class)) {
-      return true;
-    }
-
-    if (method.getParameters().size() == 1) {
-      return isAnnotationPresent(method.getParameters().get(0), BindsInstance.class);
-    }
-
-    return false;
-  }
-
-  private static MethodSpec builderSetterMethod(
-      TypeElement componentRequirement, ClassName builderClass) {
-    String simpleName =
-        UPPER_CAMEL.to(LOWER_CAMEL, componentRequirement.getSimpleName().toString());
-    return MethodSpec.methodBuilder(simpleName)
-        .addModifiers(PUBLIC)
-        .addParameter(ClassName.get(componentRequirement), simpleName)
-        .returns(builderClass)
-        .build();
-  }
-
-  private static MethodSpec builderBuildMethod(ComponentDescriptor component) {
-    return MethodSpec.methodBuilder("build")
-        .addModifiers(PUBLIC)
-        .returns(ClassName.get(component.typeElement()))
-        .build();
-  }
-
-  private static MethodSpec staticCreatorMethod(
-      TypeName creatorMethodReturnType, ComponentCreatorKind creatorKind) {
-    return MethodSpec.methodBuilder(Ascii.toLowerCase(creatorKind.typeName()))
-        .addModifiers(PUBLIC, STATIC)
-        .returns(creatorMethodReturnType)
-        .build();
-  }
-
-  private static MethodSpec createMethod(ComponentDescriptor componentDescriptor) {
-    return MethodSpec.methodBuilder("create")
-        .addModifiers(PUBLIC, STATIC)
-        .returns(ClassName.get(componentDescriptor.typeElement()))
-        .build();
-  }
-
-  private static MethodSpec onProducerFutureCancelledMethod() {
-    return MethodSpec.methodBuilder("onProducerFutureCancelled")
-        .addModifiers(PUBLIC)
-        .addParameter(TypeName.BOOLEAN, "mayInterruptIfRunning")
-        .build();
-  }
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentImplementationBuilder.java b/java/dagger/internal/codegen/componentgenerator/ComponentImplementationBuilder.java
deleted file mode 100644
index 04cb80f..0000000
--- a/java/dagger/internal/codegen/componentgenerator/ComponentImplementationBuilder.java
+++ /dev/null
@@ -1,524 +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.componentgenerator;
-
-import static com.google.auto.common.MoreElements.getLocalAndInheritedMethods;
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.common.base.Preconditions.checkState;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.binding.ComponentCreatorKind.BUILDER;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.javapoet.CodeBlocks.parameterNames;
-import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.BUILDER_METHOD;
-import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.CANCELLATION_LISTENER_METHOD;
-import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.COMPONENT_METHOD;
-import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.CONSTRUCTOR;
-import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.INITIALIZE_METHOD;
-import static dagger.internal.codegen.writing.ComponentImplementation.TypeSpecKind.COMPONENT_CREATOR;
-import static dagger.internal.codegen.writing.ComponentImplementation.TypeSpecKind.SUBCOMPONENT;
-import static dagger.producers.CancellationPolicy.Propagation.PROPAGATE;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimaps;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.Preconditions;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ComponentCreatorDescriptor;
-import dagger.internal.codegen.binding.ComponentCreatorKind;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.javapoet.AnnotationSpecs;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.writing.ComponentBindingExpressions;
-import dagger.internal.codegen.writing.ComponentCreatorImplementation;
-import dagger.internal.codegen.writing.ComponentImplementation;
-import dagger.internal.codegen.writing.ComponentRequirementExpressions;
-import dagger.internal.codegen.writing.ParentComponent;
-import dagger.model.Key;
-import dagger.producers.internal.CancellationListener;
-import dagger.producers.internal.Producers;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Function;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.DeclaredType;
-
-/** A builder of {@link ComponentImplementation}s. */
-// This only needs to be public because it's referenced in an entry point.
-public final class ComponentImplementationBuilder {
-  private static final String MAY_INTERRUPT_IF_RUNNING = "mayInterruptIfRunning";
-
-  /**
-   * How many statements per {@code initialize()} or {@code onProducerFutureCancelled()} method
-   * before they get partitioned.
-   */
-  private static final int STATEMENTS_PER_METHOD = 100;
-
-  private static final String CANCELLATION_LISTENER_METHOD_NAME = "onProducerFutureCancelled";
-
-  private final Optional<ComponentImplementationBuilder> parent;
-  private final BindingGraph graph;
-  private final ComponentBindingExpressions bindingExpressions;
-  private final ComponentRequirementExpressions componentRequirementExpressions;
-  private final ComponentImplementation componentImplementation;
-  private final ComponentCreatorImplementationFactory componentCreatorImplementationFactory;
-  private final TopLevelImplementationComponent topLevelImplementationComponent;
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-  private final KotlinMetadataUtil metadataUtil;
-  private boolean done;
-
-  @Inject
-  ComponentImplementationBuilder(
-      @ParentComponent Optional<ComponentImplementationBuilder> parent,
-      BindingGraph graph,
-      ComponentBindingExpressions bindingExpressions,
-      ComponentRequirementExpressions componentRequirementExpressions,
-      ComponentImplementation componentImplementation,
-      ComponentCreatorImplementationFactory componentCreatorImplementationFactory,
-      TopLevelImplementationComponent topLevelImplementationComponent,
-      DaggerTypes types,
-      DaggerElements elements,
-      KotlinMetadataUtil metadataUtil) {
-    this.parent = parent;
-    this.graph = graph;
-    this.bindingExpressions = bindingExpressions;
-    this.componentRequirementExpressions = componentRequirementExpressions;
-    this.componentImplementation = componentImplementation;
-    this.componentCreatorImplementationFactory = componentCreatorImplementationFactory;
-    this.types = types;
-    this.elements = elements;
-    this.topLevelImplementationComponent = topLevelImplementationComponent;
-    this.metadataUtil = metadataUtil;
-  }
-
-  /**
-   * Returns a {@link ComponentImplementation} for this component. This is only intended to be
-   * called once (and will throw on successive invocations). If the component must be regenerated,
-   * use a new instance.
-   */
-  ComponentImplementation build() {
-    checkState(
-        !done,
-        "ComponentImplementationBuilder has already built the ComponentImplementation for [%s].",
-        componentImplementation.name());
-    setSupertype();
-
-    componentCreatorImplementationFactory.create()
-        .map(ComponentCreatorImplementation::spec)
-        .ifPresent(this::addCreatorClass);
-
-    getLocalAndInheritedMethods(graph.componentTypeElement(), types, elements)
-        .forEach(method -> componentImplementation.claimMethodName(method.getSimpleName()));
-
-    addFactoryMethods();
-    addInterfaceMethods();
-    addChildComponents();
-
-    addConstructorAndInitializationMethods();
-
-    if (graph.componentDescriptor().isProduction()) {
-      addCancellationListenerImplementation();
-    }
-
-    done = true;
-    return componentImplementation;
-  }
-
-  /** Set the supertype for this generated class. */
-  private void setSupertype() {
-    componentImplementation.addSupertype(graph.componentTypeElement());
-  }
-
-  private void addCreatorClass(TypeSpec creator) {
-    if (parent.isPresent()) {
-      // In an inner implementation of a subcomponent the creator is a peer class.
-      parent.get().componentImplementation.addType(SUBCOMPONENT, creator);
-    } else {
-      componentImplementation.addType(COMPONENT_CREATOR, creator);
-    }
-  }
-
-  private void addFactoryMethods() {
-    if (parent.isPresent()) {
-      graph.factoryMethod().ifPresent(this::createSubcomponentFactoryMethod);
-    } else {
-      createRootComponentFactoryMethod();
-    }
-  }
-
-  private void addInterfaceMethods() {
-    // Each component method may have been declared by several supertypes. We want to implement
-    // only one method for each distinct signature.
-    ImmutableListMultimap<MethodSignature, ComponentMethodDescriptor> componentMethodsBySignature =
-        Multimaps.index(graph.componentDescriptor().entryPointMethods(), this::getMethodSignature);
-    for (List<ComponentMethodDescriptor> methodsWithSameSignature :
-        Multimaps.asMap(componentMethodsBySignature).values()) {
-      ComponentMethodDescriptor anyOneMethod = methodsWithSameSignature.stream().findAny().get();
-      MethodSpec methodSpec = bindingExpressions.getComponentMethod(anyOneMethod);
-
-      componentImplementation.addMethod(COMPONENT_METHOD, methodSpec);
-    }
-  }
-
-  private void addCancellationListenerImplementation() {
-    componentImplementation.addSupertype(elements.getTypeElement(CancellationListener.class));
-    componentImplementation.claimMethodName(CANCELLATION_LISTENER_METHOD_NAME);
-
-    ImmutableList<ParameterSpec> parameters =
-        ImmutableList.of(ParameterSpec.builder(boolean.class, MAY_INTERRUPT_IF_RUNNING).build());
-
-    MethodSpec.Builder methodBuilder =
-        methodBuilder(CANCELLATION_LISTENER_METHOD_NAME)
-            .addModifiers(PUBLIC)
-            .addAnnotation(Override.class)
-            .addParameters(parameters);
-
-    ImmutableList<CodeBlock> cancellationStatements = cancellationStatements();
-
-    if (cancellationStatements.size() < STATEMENTS_PER_METHOD) {
-      methodBuilder.addCode(CodeBlocks.concat(cancellationStatements)).build();
-    } else {
-      ImmutableList<MethodSpec> cancelProducersMethods =
-          createPartitionedMethods(
-              "cancelProducers",
-              parameters,
-              cancellationStatements,
-              methodName -> methodBuilder(methodName).addModifiers(PRIVATE));
-      for (MethodSpec cancelProducersMethod : cancelProducersMethods) {
-        methodBuilder.addStatement("$N($L)", cancelProducersMethod, MAY_INTERRUPT_IF_RUNNING);
-        componentImplementation.addMethod(CANCELLATION_LISTENER_METHOD, cancelProducersMethod);
-      }
-    }
-
-    cancelParentStatement().ifPresent(methodBuilder::addCode);
-
-    componentImplementation.addMethod(CANCELLATION_LISTENER_METHOD, methodBuilder.build());
-  }
-
-  private ImmutableList<CodeBlock> cancellationStatements() {
-    // Reversing should order cancellations starting from entry points and going down to leaves
-    // rather than the other way around. This shouldn't really matter but seems *slightly*
-    // preferable because:
-    // When a future that another future depends on is cancelled, that cancellation will propagate
-    // up the future graph toward the entry point. Cancelling in reverse order should ensure that
-    // everything that depends on a particular node has already been cancelled when that node is
-    // cancelled, so there's no need to propagate. Otherwise, when we cancel a leaf node, it might
-    // propagate through most of the graph, making most of the cancel calls that follow in the
-    // onProducerFutureCancelled method do nothing.
-    ImmutableList<Key> cancellationKeys =
-        componentImplementation.getCancellableProducerKeys().reverse();
-
-    ImmutableList.Builder<CodeBlock> cancellationStatements = ImmutableList.builder();
-    for (Key cancellationKey : cancellationKeys) {
-      cancellationStatements.add(
-          CodeBlock.of(
-              "$T.cancel($L, $N);",
-              Producers.class,
-              bindingExpressions
-                  .getDependencyExpression(
-                      bindingRequest(cancellationKey, FrameworkType.PRODUCER_NODE),
-                      componentImplementation.name())
-                  .codeBlock(),
-              MAY_INTERRUPT_IF_RUNNING));
-    }
-    return cancellationStatements.build();
-  }
-
-  private Optional<CodeBlock> cancelParentStatement() {
-    if (!shouldPropagateCancellationToParent()) {
-      return Optional.empty();
-    }
-    return Optional.of(
-        CodeBlock.builder()
-            .addStatement(
-                "$T.this.$N($N)",
-                parent.get().componentImplementation.name(),
-                CANCELLATION_LISTENER_METHOD_NAME,
-                MAY_INTERRUPT_IF_RUNNING)
-            .build());
-  }
-
-  private boolean shouldPropagateCancellationToParent() {
-    return parent.isPresent()
-        && parent
-            .get()
-            .componentImplementation
-            .componentDescriptor()
-            .cancellationPolicy()
-            .map(policy -> policy.fromSubcomponents().equals(PROPAGATE))
-            .orElse(false);
-  }
-
-  private MethodSignature getMethodSignature(ComponentMethodDescriptor method) {
-    return MethodSignature.forComponentMethod(
-        method, MoreTypes.asDeclared(graph.componentTypeElement().asType()), types);
-  }
-
-  private void addChildComponents() {
-    for (BindingGraph subgraph : graph.subgraphs()) {
-      componentImplementation.addType(SUBCOMPONENT, childComponent(subgraph));
-    }
-  }
-
-  private TypeSpec childComponent(BindingGraph childGraph) {
-    return topLevelImplementationComponent
-        .currentImplementationSubcomponentBuilder()
-        .componentImplementation(subcomponent(childGraph))
-        .bindingGraph(childGraph)
-        .parentBuilder(Optional.of(this))
-        .parentBindingExpressions(Optional.of(bindingExpressions))
-        .parentRequirementExpressions(Optional.of(componentRequirementExpressions))
-        .build()
-        .componentImplementationBuilder()
-        .build()
-        .generate()
-        .build();
-  }
-
-  /** Creates an inner subcomponent implementation. */
-  private ComponentImplementation subcomponent(BindingGraph childGraph) {
-    return componentImplementation.childComponentImplementation(childGraph);
-  }
-
-  /** Creates and adds the constructor and methods needed for initializing the component. */
-  private void addConstructorAndInitializationMethods() {
-    MethodSpec.Builder constructor = constructorBuilder().addModifiers(PRIVATE);
-    implementInitializationMethod(constructor, initializationParameters());
-    componentImplementation.addMethod(CONSTRUCTOR, constructor.build());
-  }
-
-  /** Adds parameters and code to the given {@code initializationMethod}. */
-  private void implementInitializationMethod(
-      MethodSpec.Builder initializationMethod,
-      ImmutableMap<ComponentRequirement, ParameterSpec> initializationParameters) {
-    initializationMethod.addParameters(initializationParameters.values());
-    initializationMethod.addCode(
-        CodeBlocks.concat(componentImplementation.getComponentRequirementInitializations()));
-    addInitializeMethods(initializationMethod, initializationParameters.values().asList());
-  }
-
-  /**
-   * Adds any necessary {@code initialize} methods to the component and adds calls to them to the
-   * given {@code callingMethod}.
-   */
-  private void addInitializeMethods(
-      MethodSpec.Builder callingMethod, ImmutableList<ParameterSpec> parameters) {
-    // TODO(cgdecker): It's not the case that each initialize() method has need for all of the
-    // given parameters. In some cases, those parameters may have already been assigned to fields
-    // which could be referenced instead. In other cases, an initialize method may just not need
-    // some of the parameters because the set of initializations in that partition does not
-    // include any reference to them. Right now, the Dagger code has no way of getting that
-    // information because, among other things, componentImplementation.getImplementations() just
-    // returns a bunch of CodeBlocks with no semantic information. Additionally, we may not know
-    // yet whether a field will end up needing to be created for a specific requirement, and we
-    // don't want to create a field that ends up only being used during initialization.
-    CodeBlock args = parameterNames(parameters);
-    ImmutableList<MethodSpec> methods =
-        createPartitionedMethods(
-            "initialize",
-            makeFinal(parameters),
-            componentImplementation.getInitializations(),
-            methodName ->
-                methodBuilder(methodName)
-                    .addModifiers(PRIVATE)
-                    /* TODO(gak): Strictly speaking, we only need the suppression here if we are
-                     * also initializing a raw field in this method, but the structure of this
-                     * code makes it awkward to pass that bit through.  This will be cleaned up
-                     * when we no longer separate fields and initialization as we do now. */
-                    .addAnnotation(AnnotationSpecs.suppressWarnings(UNCHECKED)));
-    for (MethodSpec method : methods) {
-      callingMethod.addStatement("$N($L)", method, args);
-      componentImplementation.addMethod(INITIALIZE_METHOD, method);
-    }
-  }
-
-  /**
-   * Creates one or more methods, all taking the given {@code parameters}, which partition the given
-   * list of {@code statements} among themselves such that no method has more than {@code
-   * STATEMENTS_PER_METHOD} statements in it and such that the returned methods, if called in order,
-   * will execute the {@code statements} in the given order.
-   */
-  private ImmutableList<MethodSpec> createPartitionedMethods(
-      String methodName,
-      Iterable<ParameterSpec> parameters,
-      List<CodeBlock> statements,
-      Function<String, MethodSpec.Builder> methodBuilderCreator) {
-    return Lists.partition(statements, STATEMENTS_PER_METHOD).stream()
-        .map(
-            partition ->
-                methodBuilderCreator
-                    .apply(componentImplementation.getUniqueMethodName(methodName))
-                    .addParameters(parameters)
-                    .addCode(CodeBlocks.concat(partition))
-                    .build())
-        .collect(toImmutableList());
-  }
-
-  /** Returns the given parameters with a final modifier added. */
-  private final ImmutableList<ParameterSpec> makeFinal(Collection<ParameterSpec> parameters) {
-    return parameters.stream()
-        .map(param -> param.toBuilder().addModifiers(FINAL).build())
-        .collect(toImmutableList());
-  }
-
-  /**
-   * Returns the parameters for the constructor as a map from the requirement the parameter fulfills
-   * to the spec for the parameter.
-   */
-  private final ImmutableMap<ComponentRequirement, ParameterSpec> initializationParameters() {
-    Map<ComponentRequirement, ParameterSpec> parameters;
-    if (componentImplementation.componentDescriptor().hasCreator()) {
-      parameters = Maps.toMap(graph.componentRequirements(), ComponentRequirement::toParameterSpec);
-    } else if (graph.factoryMethod().isPresent()) {
-      parameters = getFactoryMethodParameters(graph);
-    } else {
-      throw new AssertionError(
-          "Expected either a component creator or factory method but found neither.");
-    }
-
-    return renameParameters(parameters);
-  }
-
-  /**
-   * Renames the given parameters to guarantee their names do not conflict with fields in the
-   * component to ensure that a parameter is never referenced where a reference to a field was
-   * intended.
-   */
-  // TODO(cgdecker): This is a bit kludgy; it would be preferable to either qualify the field
-  // references with "this." or "super." when needed to disambiguate between field and parameter,
-  // but that would require more context than is currently available when the code referencing a
-  // field is generated.
-  private ImmutableMap<ComponentRequirement, ParameterSpec> renameParameters(
-      Map<ComponentRequirement, ParameterSpec> parameters) {
-    return ImmutableMap.copyOf(
-        Maps.transformEntries(
-            parameters,
-            (requirement, parameter) ->
-                renameParameter(
-                    parameter,
-                    componentImplementation.getParameterName(requirement, parameter.name))));
-  }
-
-  private ParameterSpec renameParameter(ParameterSpec parameter, String newName) {
-    return ParameterSpec.builder(parameter.type, newName)
-        .addAnnotations(parameter.annotations)
-        .addModifiers(parameter.modifiers)
-        .build();
-  }
-
-  private void createRootComponentFactoryMethod() {
-    checkState(!parent.isPresent());
-    // Top-level components have a static method that returns a builder or factory for the
-    // component. If the user defined a @Component.Builder or @Component.Factory, an
-    // implementation of their type is returned. Otherwise, an autogenerated Builder type is
-    // returned.
-    // TODO(cgdecker): Replace this abomination with a small class?
-    // Better yet, change things so that an autogenerated builder type has a descriptor of sorts
-    // just like a user-defined creator type.
-    ComponentCreatorKind creatorKind;
-    ClassName creatorType;
-    String factoryMethodName;
-    boolean noArgFactoryMethod;
-    Optional<ComponentCreatorDescriptor> creatorDescriptor =
-        graph.componentDescriptor().creatorDescriptor();
-    if (creatorDescriptor.isPresent()) {
-      ComponentCreatorDescriptor descriptor = creatorDescriptor.get();
-      creatorKind = descriptor.kind();
-      creatorType = ClassName.get(descriptor.typeElement());
-      factoryMethodName = descriptor.factoryMethod().getSimpleName().toString();
-      noArgFactoryMethod = descriptor.factoryParameters().isEmpty();
-    } else {
-      creatorKind = BUILDER;
-      creatorType = componentImplementation.getCreatorName();
-      factoryMethodName = "build";
-      noArgFactoryMethod = true;
-    }
-
-    MethodSpec creatorFactoryMethod =
-        methodBuilder(creatorKind.methodName())
-            .addModifiers(PUBLIC, STATIC)
-            .returns(creatorType)
-            .addStatement("return new $T()", componentImplementation.getCreatorName())
-            .build();
-    componentImplementation.addMethod(BUILDER_METHOD, creatorFactoryMethod);
-    if (noArgFactoryMethod && canInstantiateAllRequirements()) {
-      componentImplementation.addMethod(
-          BUILDER_METHOD,
-          methodBuilder("create")
-              .returns(ClassName.get(graph.componentTypeElement()))
-              .addModifiers(PUBLIC, STATIC)
-              .addStatement("return new $L().$L()", creatorKind.typeName(), factoryMethodName)
-              .build());
-    }
-  }
-
-  /** {@code true} if all of the graph's required dependencies can be automatically constructed */
-  private boolean canInstantiateAllRequirements() {
-    return !Iterables.any(
-        graph.componentRequirements(),
-        dependency -> dependency.requiresAPassedInstance(elements, types, metadataUtil));
-  }
-
-  private void createSubcomponentFactoryMethod(ExecutableElement factoryMethod) {
-    checkState(parent.isPresent());
-    Collection<ParameterSpec> params = getFactoryMethodParameters(graph).values();
-    MethodSpec.Builder method = MethodSpec.overriding(factoryMethod, parentType(), types);
-    params.forEach(
-        param -> method.addStatement("$T.checkNotNull($N)", Preconditions.class, param));
-    method.addStatement(
-        "return new $T($L)", componentImplementation.name(), parameterNames(params));
-
-    parent.get().componentImplementation.addMethod(COMPONENT_METHOD, method.build());
-  }
-
-  private DeclaredType parentType() {
-    return asDeclared(parent.get().graph.componentTypeElement().asType());
-  }
-  /**
-   * Returns the map of {@link ComponentRequirement}s to {@link ParameterSpec}s for the given
-   * graph's factory method.
-   */
-  private static Map<ComponentRequirement, ParameterSpec> getFactoryMethodParameters(
-      BindingGraph graph) {
-    return Maps.transformValues(graph.factoryMethodParameters(), ParameterSpec::get);
-  }
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentImplementationFactory.java b/java/dagger/internal/codegen/componentgenerator/ComponentImplementationFactory.java
deleted file mode 100644
index fdfcc9d..0000000
--- a/java/dagger/internal/codegen/componentgenerator/ComponentImplementationFactory.java
+++ /dev/null
@@ -1,90 +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.componentgenerator;
-
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.componentgenerator.ComponentGenerator.componentName;
-
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.KeyFactory;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.writing.ComponentImplementation;
-import dagger.internal.codegen.writing.SubcomponentNames;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.lang.model.element.TypeElement;
-
-/** Factory for {@link ComponentImplementation}s. */
-@Singleton
-final class ComponentImplementationFactory implements ClearableCache {
-  private final Map<TypeElement, ComponentImplementation> topLevelComponentCache = new HashMap<>();
-  private final KeyFactory keyFactory;
-  private final CompilerOptions compilerOptions;
-  private final TopLevelImplementationComponent.Builder topLevelImplementationComponentBuilder;
-
-  @Inject
-  ComponentImplementationFactory(
-      KeyFactory keyFactory,
-      CompilerOptions compilerOptions,
-      TopLevelImplementationComponent.Builder topLevelImplementationComponentBuilder) {
-    this.keyFactory = keyFactory;
-    this.compilerOptions = compilerOptions;
-    this.topLevelImplementationComponentBuilder = topLevelImplementationComponentBuilder;
-  }
-
-  /**
-   * Returns a top-level (non-nested) component implementation for a binding graph.
-   */
-  ComponentImplementation createComponentImplementation(BindingGraph bindingGraph) {
-    return reentrantComputeIfAbsent(
-        topLevelComponentCache,
-        bindingGraph.componentTypeElement(),
-        component -> createComponentImplementationUncached(bindingGraph));
-  }
-
-  private ComponentImplementation createComponentImplementationUncached(BindingGraph bindingGraph) {
-    ComponentImplementation componentImplementation =
-        ComponentImplementation.topLevelComponentImplementation(
-            bindingGraph,
-            componentName(bindingGraph.componentTypeElement()),
-            new SubcomponentNames(bindingGraph, keyFactory),
-            compilerOptions);
-
-    // TODO(dpb): explore using optional bindings for the "parent" bindings
-    return topLevelImplementationComponentBuilder
-        .topLevelComponent(componentImplementation)
-        .build()
-        .currentImplementationSubcomponentBuilder()
-        .componentImplementation(componentImplementation)
-        .bindingGraph(bindingGraph)
-        .parentBuilder(Optional.empty())
-        .parentBindingExpressions(Optional.empty())
-        .parentRequirementExpressions(Optional.empty())
-        .build()
-        .componentImplementationBuilder()
-        .build();
-  }
-
-  @Override
-  public void clearCache() {
-    topLevelComponentCache.clear();
-  }
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/CurrentImplementationSubcomponent.java b/java/dagger/internal/codegen/componentgenerator/CurrentImplementationSubcomponent.java
deleted file mode 100644
index 5584372..0000000
--- a/java/dagger/internal/codegen/componentgenerator/CurrentImplementationSubcomponent.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.componentgenerator;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.writing.ComponentBindingExpressions;
-import dagger.internal.codegen.writing.ComponentImplementation;
-import dagger.internal.codegen.writing.ComponentRequirementExpressions;
-import dagger.internal.codegen.writing.ParentComponent;
-import dagger.internal.codegen.writing.PerComponentImplementation;
-import java.util.Optional;
-
-/**
- * A subcomponent that injects all objects that are responsible for creating a single {@link
- * ComponentImplementation} instance. Each child {@link ComponentImplementation} will have its own
- * instance of {@link CurrentImplementationSubcomponent}.
- */
-@Subcomponent
-@PerComponentImplementation
-// This only needs to be public because the type is referenced by generated component.
-public interface CurrentImplementationSubcomponent {
-  ComponentImplementationBuilder componentImplementationBuilder();
-
-  /** Returns the builder for {@link CurrentImplementationSubcomponent}. */
-  @Subcomponent.Builder
-  interface Builder {
-    @BindsInstance
-    Builder componentImplementation(ComponentImplementation componentImplementation);
-
-    @BindsInstance
-    Builder bindingGraph(BindingGraph bindingGraph);
-
-    @BindsInstance
-    Builder parentBuilder(@ParentComponent Optional<ComponentImplementationBuilder> parentBuilder);
-
-    @BindsInstance
-    Builder parentBindingExpressions(
-        @ParentComponent Optional<ComponentBindingExpressions> parentBindingExpressions);
-
-    @BindsInstance
-    Builder parentRequirementExpressions(
-        @ParentComponent Optional<ComponentRequirementExpressions> parentRequirementExpressions);
-
-    CurrentImplementationSubcomponent build();
-  }
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/MethodSignature.java b/java/dagger/internal/codegen/componentgenerator/MethodSignature.java
deleted file mode 100644
index 99b05a4..0000000
--- a/java/dagger/internal/codegen/componentgenerator/MethodSignature.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2014 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.componentgenerator;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-
-import com.google.auto.common.MoreTypes;
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Equivalence;
-import com.google.common.collect.ImmutableList;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.util.List;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-
-/** A class that defines proper {@code equals} and {@code hashcode} for a method signature. */
-@AutoValue
-abstract class MethodSignature {
-
-  abstract String name();
-
-  abstract ImmutableList<? extends Equivalence.Wrapper<? extends TypeMirror>> parameterTypes();
-
-  abstract ImmutableList<? extends Equivalence.Wrapper<? extends TypeMirror>> thrownTypes();
-
-  static MethodSignature forComponentMethod(
-      ComponentMethodDescriptor componentMethod, DeclaredType componentType, DaggerTypes types) {
-    ExecutableType methodType =
-        MoreTypes.asExecutable(types.asMemberOf(componentType, componentMethod.methodElement()));
-    return new AutoValue_MethodSignature(
-        componentMethod.methodElement().getSimpleName().toString(),
-        wrapInEquivalence(methodType.getParameterTypes()),
-        wrapInEquivalence(methodType.getThrownTypes()));
-  }
-
-  private static ImmutableList<? extends Equivalence.Wrapper<? extends TypeMirror>>
-      wrapInEquivalence(List<? extends TypeMirror> types) {
-    return types.stream().map(MoreTypes.equivalence()::wrap).collect(toImmutableList());
-  }
-}
diff --git a/java/dagger/internal/codegen/componentgenerator/TopLevelImplementationComponent.java b/java/dagger/internal/codegen/componentgenerator/TopLevelImplementationComponent.java
deleted file mode 100644
index 7919e47..0000000
--- a/java/dagger/internal/codegen/componentgenerator/TopLevelImplementationComponent.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.componentgenerator;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-import dagger.internal.codegen.writing.ComponentImplementation;
-import dagger.internal.codegen.writing.PerGeneratedFile;
-import dagger.internal.codegen.writing.TopLevel;
-
-/**
- * A shared subcomponent for a top-level {@link ComponentImplementation} and any nested child
- * implementations.
- */
-@PerGeneratedFile
-@Subcomponent
-// This only needs to be public because the type is referenced by generated component.
-public interface TopLevelImplementationComponent {
-  CurrentImplementationSubcomponent.Builder currentImplementationSubcomponentBuilder();
-
-  /** Returns the builder for {@link TopLevelImplementationComponent}. */
-  @Subcomponent.Builder
-  interface Builder {
-    @BindsInstance
-    Builder topLevelComponent(@TopLevel ComponentImplementation topLevelImplementation);
-    TopLevelImplementationComponent build();
-  }
-}
diff --git a/java/dagger/internal/codegen/dagger_statistics.proto b/java/dagger/internal/codegen/dagger_statistics.proto
new file mode 100644
index 0000000..273e472
--- /dev/null
+++ b/java/dagger/internal/codegen/dagger_statistics.proto
@@ -0,0 +1,25 @@
+syntax = "proto2";
+
+package dagger.internal.codegen.proto;
+option java_package = "dagger.internal.codegen.proto";
+
+import "google/protobuf/duration.proto";
+
+message DaggerBuildStatistics {
+  optional google.protobuf.Duration total_processing_time = 1;
+  repeated DaggerRound rounds = 2;
+}
+
+// Duration of each Dagger ProcessingStep for a single annotation processing
+// round.
+message DaggerRound {
+  optional google.protobuf.Duration map_key_step_time = 1;
+  optional google.protobuf.Duration inject_step_time = 2;
+  optional google.protobuf.Duration monitoring_module_step_time = 3;
+  optional google.protobuf.Duration multibinding_annotations_step_time = 4;
+  optional google.protobuf.Duration binds_instance_step_time = 5;
+  optional google.protobuf.Duration module_step_time = 6;
+  optional google.protobuf.Duration component_step_time = 7;
+  optional google.protobuf.Duration component_hjar_step_time = 8;
+  optional google.protobuf.Duration binding_method_step_time = 9;
+}
diff --git a/java/dagger/internal/codegen/extension/BUILD b/java/dagger/internal/codegen/extension/BUILD
deleted file mode 100644
index 468a685..0000000
--- a/java/dagger/internal/codegen/extension/BUILD
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Extra features for the JDK and Guava. This code is merged into both
-#   the dagger-compiler and dagger-spi artifacts that are sent to Maven
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "extension",
-    srcs = glob(["*.java"]),
-    tags = ["maven:merged"],
-    deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:graph",
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-    ],
-)
diff --git a/java/dagger/internal/codegen/extension/DaggerCollectors.java b/java/dagger/internal/codegen/extension/DaggerCollectors.java
deleted file mode 100644
index 7b01676..0000000
--- a/java/dagger/internal/codegen/extension/DaggerCollectors.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2019 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.extension;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Optional;
-import java.util.stream.Collector;
-import javax.annotation.Nullable;
-
-/**
- * A copy of {@link com.google.common.collect.MoreCollectors} to avoid issues with the '-android'
- * variant of Guava. See b/68008628
- */
-public final class DaggerCollectors {
-
-  private static final Collector<Object, ?, Optional<Object>> TO_OPTIONAL =
-      Collector.of(
-          ToOptionalState::new,
-          ToOptionalState::add,
-          ToOptionalState::combine,
-          ToOptionalState::getOptional,
-          Collector.Characteristics.UNORDERED);
-
-  /**
-   * A collector that converts a stream of zero or one elements to an {@code Optional}. The returned
-   * collector throws an {@code IllegalArgumentException} if the stream consists of two or more
-   * elements, and a {@code NullPointerException} if the stream consists of exactly one element,
-   * which is null.
-   */
-  @SuppressWarnings("unchecked")
-  public static <T> Collector<T, ?, Optional<T>> toOptional() {
-    return (Collector) TO_OPTIONAL;
-  }
-
-  private static final Object NULL_PLACEHOLDER = new Object();
-
-  private static final Collector<Object, ?, Object> ONLY_ELEMENT =
-      Collector.of(
-          ToOptionalState::new,
-          (state, o) -> state.add((o == null) ? NULL_PLACEHOLDER : o),
-          ToOptionalState::combine,
-          state -> {
-            Object result = state.getElement();
-            return (result == NULL_PLACEHOLDER) ? null : result;
-          },
-          Collector.Characteristics.UNORDERED);
-
-  /**
-   * A collector that takes a stream containing exactly one element and returns that element. The
-   * returned collector throws an {@code IllegalArgumentException} if the stream consists of two or
-   * more elements, and a {@code NoSuchElementException} if the stream is empty.
-   */
-  @SuppressWarnings("unchecked")
-  public static <T> Collector<T, ?, T> onlyElement() {
-    return (Collector) ONLY_ELEMENT;
-  }
-
-  private static final class ToOptionalState {
-    static final int MAX_EXTRAS = 4;
-
-    @Nullable Object element;
-    @Nullable List<Object> extras;
-
-    ToOptionalState() {
-      element = null;
-      extras = null;
-    }
-
-    IllegalArgumentException multiples(boolean overflow) {
-      StringBuilder sb =
-          new StringBuilder().append("expected one element but was: <").append(element);
-      for (Object o : extras) {
-        sb.append(", ").append(o);
-      }
-      if (overflow) {
-        sb.append(", ...");
-      }
-      sb.append('>');
-      throw new IllegalArgumentException(sb.toString());
-    }
-
-    void add(Object o) {
-      checkNotNull(o);
-      if (element == null) {
-        this.element = o;
-      } else if (extras == null) {
-        extras = new ArrayList<>(MAX_EXTRAS);
-        extras.add(o);
-      } else if (extras.size() < MAX_EXTRAS) {
-        extras.add(o);
-      } else {
-        throw multiples(true);
-      }
-    }
-
-    ToOptionalState combine(ToOptionalState other) {
-      if (element == null) {
-        return other;
-      } else if (other.element == null) {
-        return this;
-      } else {
-        if (extras == null) {
-          extras = new ArrayList<>();
-        }
-        extras.add(other.element);
-        if (other.extras != null) {
-          this.extras.addAll(other.extras);
-        }
-        if (extras.size() > MAX_EXTRAS) {
-          extras.subList(MAX_EXTRAS, extras.size()).clear();
-          throw multiples(true);
-        }
-        return this;
-      }
-    }
-
-    Optional<Object> getOptional() {
-      if (extras == null) {
-        return Optional.ofNullable(element);
-      } else {
-        throw multiples(false);
-      }
-    }
-
-    Object getElement() {
-      if (element == null) {
-        throw new NoSuchElementException();
-      } else if (extras == null) {
-        return element;
-      } else {
-        throw multiples(false);
-      }
-    }
-  }
-
-  private DaggerCollectors() {}
-}
diff --git a/java/dagger/internal/codegen/extension/DaggerGraphs.java b/java/dagger/internal/codegen/extension/DaggerGraphs.java
deleted file mode 100644
index 587445b..0000000
--- a/java/dagger/internal/codegen/extension/DaggerGraphs.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.extension;
-
-import static com.google.common.collect.Sets.difference;
-import static com.google.common.graph.Graphs.reachableNodes;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.graph.Graph;
-import com.google.common.graph.SuccessorsFunction;
-import java.util.ArrayDeque;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
-
-/** Utility methods for {@link com.google.common.graph} types. */
-public final class DaggerGraphs {
-  /**
-   * Returns a shortest path from {@code nodeU} to {@code nodeV} in {@code graph} as a list of the
-   * nodes visited in sequence, including both {@code nodeU} and {@code nodeV}. (Note that there may
-   * be many possible shortest paths.)
-   *
-   * <p>If {@code nodeV} is not {@link
-   * com.google.common.graph.Graphs#reachableNodes(com.google.common.graph.Graph, Object) reachable}
-   * from {@code nodeU}, the list returned is empty.
-   *
-   * @throws IllegalArgumentException if {@code nodeU} or {@code nodeV} is not present in {@code
-   *     graph}
-   */
-  public static <N> ImmutableList<N> shortestPath(SuccessorsFunction<N> graph, N nodeU, N nodeV) {
-    if (nodeU.equals(nodeV)) {
-      return ImmutableList.of(nodeU);
-    }
-    Set<N> successors = ImmutableSet.copyOf(graph.successors(nodeU));
-    if (successors.contains(nodeV)) {
-      return ImmutableList.of(nodeU, nodeV);
-    }
-
-    Map<N, N> visitedNodeToPathPredecessor = new HashMap<>(); // encodes shortest path tree
-    for (N node : successors) {
-      visitedNodeToPathPredecessor.put(node, nodeU);
-    }
-    Queue<N> currentNodes = new ArrayDeque<N>(successors);
-    Queue<N> nextNodes = new ArrayDeque<N>();
-
-    // Perform a breadth-first traversal starting with the successors of nodeU.
-    while (!currentNodes.isEmpty()) {
-      while (!currentNodes.isEmpty()) {
-        N currentNode = currentNodes.remove();
-        for (N nextNode : graph.successors(currentNode)) {
-          if (visitedNodeToPathPredecessor.containsKey(nextNode)) {
-            continue; // we already have a shortest path to nextNode
-          }
-          visitedNodeToPathPredecessor.put(nextNode, currentNode);
-          if (nextNode.equals(nodeV)) {
-            ImmutableList.Builder<N> builder = ImmutableList.builder();
-            N node = nodeV;
-            builder.add(node);
-            while (!node.equals(nodeU)) {
-              node = visitedNodeToPathPredecessor.get(node);
-              builder.add(node);
-            }
-            return builder.build().reverse();
-          }
-          nextNodes.add(nextNode);
-        }
-      }
-      Queue<N> emptyQueue = currentNodes;
-      currentNodes = nextNodes;
-      nextNodes = emptyQueue; // reusing empty queue faster than allocating new one
-    }
-
-    return ImmutableList.of();
-  }
-
-  /** Returns the nodes in a graph that are not reachable from a node. */
-  public static <N> ImmutableSet<N> unreachableNodes(Graph<N> graph, N node) {
-    return ImmutableSet.copyOf(difference(graph.nodes(), reachableNodes(graph, node)));
-  }
-
-  private DaggerGraphs() {}
-}
diff --git a/java/dagger/internal/codegen/extension/DaggerStreams.java b/java/dagger/internal/codegen/extension/DaggerStreams.java
deleted file mode 100644
index 136280d..0000000
--- a/java/dagger/internal/codegen/extension/DaggerStreams.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2013 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.extension;
-
-import static java.util.stream.Collectors.collectingAndThen;
-import static java.util.stream.Collectors.toList;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Maps;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Collector;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-/** Utilities for streams. */
-public final class DaggerStreams {
-
-  /**
-   * Returns a {@link Collector} that accumulates the input elements into a new {@link
-   * ImmutableList}, in encounter order.
-   */
-  // TODO(b/68008628): Use ImmutableList.toImmutableList().
-  public static <T> Collector<T, ?, ImmutableList<T>> toImmutableList() {
-    return collectingAndThen(toList(), ImmutableList::copyOf);
-  }
-
-  /**
-   * Returns a {@link Collector} that accumulates the input elements into a new {@link
-   * ImmutableSet}, in encounter order.
-   */
-  // TODO(b/68008628): Use ImmutableSet.toImmutableSet().
-  public static <T> Collector<T, ?, ImmutableSet<T>> toImmutableSet() {
-    return collectingAndThen(toList(), ImmutableSet::copyOf);
-  }
-
-  /**
-   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys
-   * and values are the result of applying the provided mapping functions to the input elements.
-   * Entries appear in the result {@code ImmutableMap} in encounter order.
-   */
-  // TODO(b/68008628): Use ImmutableMap.toImmutableMap().
-  public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
-      Function<? super T, K> keyMapper, Function<? super T, V> valueMapper) {
-    return Collectors.mapping(
-        value -> Maps.immutableEntry(keyMapper.apply(value), valueMapper.apply(value)),
-        Collector.of(
-            ImmutableMap::builder,
-            (ImmutableMap.Builder<K, V> builder, Map.Entry<K, V> entry) -> builder.put(entry),
-            (left, right) -> left.putAll(right.build()),
-            ImmutableMap.Builder::build));
-  }
-
-  /**
-   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSetMultimap}
-   * whose keys and values are the result of applying the provided mapping functions to the input
-   * elements. Entries appear in the result {@code ImmutableSetMultimap} in encounter order.
-   */
-  // TODO(b/68008628): Use ImmutableSetMultimap.toImmutableSetMultimap().
-  public static <T, K, V> Collector<T, ?, ImmutableSetMultimap<K, V>> toImmutableSetMultimap(
-      Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
-    return Collectors.mapping(
-        value -> Maps.immutableEntry(keyMapper.apply(value), valueMapper.apply(value)),
-        Collector.of(
-            ImmutableSetMultimap::builder,
-            (ImmutableSetMultimap.Builder<K, V> builder, Map.Entry<K, V> entry) ->
-                builder.put(entry),
-            (left, right) -> left.putAll(right.build()),
-            ImmutableSetMultimap.Builder::build));
-  }
-
-  /**
-   * Returns a function from {@link Object} to {@code Stream<T>}, which returns a stream containing
-   * its input if its input is an instance of {@code T}.
-   *
-   * <p>Use as an argument to {@link Stream#flatMap(Function)}:
-   *
-   * <pre>{@code Stream<Bar>} barStream = fooStream.flatMap(instancesOf(Bar.class));</pre>
-   */
-  public static <T> Function<Object, Stream<T>> instancesOf(Class<T> to) {
-    return f -> to.isInstance(f) ? Stream.of(to.cast(f)) : Stream.empty();
-  }
-
-  /** Returns a stream of all values of the given {@code enumType}. */
-  public static <E extends Enum<E>> Stream<E> valuesOf(Class<E> enumType) {
-    return EnumSet.allOf(enumType).stream();
-  }
-
-  /**
-   * A function that you can use to extract the present values from a stream of {@link Optional}s.
-   *
-   * <pre>{@code
-   * Set<Foo> foos =
-   *     optionalFoos()
-   *         .flatMap(DaggerStreams.presentValues())
-   *         .collect(toSet());
-   * }</pre>
-   */
-  public static <T> Function<Optional<T>, Stream<T>> presentValues() {
-    return optional -> optional.map(Stream::of).orElse(Stream.empty());
-  }
-
-  /**
-   * Returns a sequential {@link Stream} of the contents of {@code iterable}, delegating to {@link
-   * Collection#stream} if possible.
-   */
-  public static <T> Stream<T> stream(Iterable<T> iterable) {
-    return (iterable instanceof Collection)
-        ? ((Collection<T>) iterable).stream()
-        : StreamSupport.stream(iterable.spliterator(), false);
-  }
-
-  private DaggerStreams() {}
-}
diff --git a/java/dagger/internal/codegen/extension/Optionals.java b/java/dagger/internal/codegen/extension/Optionals.java
deleted file mode 100644
index 57494a2..0000000
--- a/java/dagger/internal/codegen/extension/Optionals.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 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.extension;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Lists.asList;
-
-import java.util.Comparator;
-import java.util.Optional;
-import java.util.function.Function;
-
-/** Utilities for {@link Optional}s. */
-public final class Optionals {
-  /**
-   * A {@link Comparator} that puts empty {@link Optional}s before present ones, and compares
-   * present {@link Optional}s by their values.
-   */
-  public static <C extends Comparable<C>> Comparator<Optional<C>> optionalComparator() {
-    return Comparator.comparing((Optional<C> optional) -> optional.isPresent())
-        .thenComparing(Optional::get);
-  }
-
-  public static <T> Comparator<Optional<T>> emptiesLast(Comparator<? super T> valueComparator) {
-    checkNotNull(valueComparator);
-    return Comparator.comparing(o -> o.orElse(null), Comparator.nullsLast(valueComparator));
-  }
-
-  /** Returns the first argument that is present, or empty if none are. */
-  @SafeVarargs
-  public static <T> Optional<T> firstPresent(
-      Optional<T> first, Optional<T> second, Optional<T>... rest) {
-    return asList(first, second, rest).stream()
-        .filter(Optional::isPresent)
-        .findFirst()
-        .orElse(Optional.empty());
-  }
-
-  /**
-   * Walks a chain of present optionals as defined by successive calls to {@code nextFunction},
-   * returning the value of the final optional that is present. The first optional in the chain is
-   * the result of {@code nextFunction(start)}.
-   */
-  public static <T> T rootmostValue(T start, Function<T, Optional<T>> nextFunction) {
-    T current = start;
-    for (Optional<T> next = nextFunction.apply(start);
-        next.isPresent();
-        next = nextFunction.apply(current)) {
-      current = next.get();
-    }
-    return current;
-  }
-
-  private Optionals() {}
-}
diff --git a/java/dagger/internal/codegen/javac/BUILD b/java/dagger/internal/codegen/javac/BUILD
deleted file mode 100644
index b8cb37c..0000000
--- a/java/dagger/internal/codegen/javac/BUILD
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 2017 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.
-
-# Description:
-#   A library for javac the javac plugin module.
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "javac",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen:component-codegen"],
-    exports = [
-        ":javac-import",
-    ],
-    deps = [
-        ":javac-import",
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/langmodel",
-    ],
-)
-
-load("@rules_java//java:defs.bzl", "java_import")
-
-# Replacement for @bazel_tools//third_party/java/jdk/langtools:javac, which seems to have gone away?
-java_import(
-    name = "javac-import",
-    jars = ["@bazel_tools//third_party/java/jdk/langtools:javac_jar"],
-)
diff --git a/java/dagger/internal/codegen/javac/JavacPluginModule.java b/java/dagger/internal/codegen/javac/JavacPluginModule.java
deleted file mode 100644
index 214191a..0000000
--- a/java/dagger/internal/codegen/javac/JavacPluginModule.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2017 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.javac;
-
-import com.sun.tools.javac.model.JavacElements;
-import com.sun.tools.javac.model.JavacTypes;
-import com.sun.tools.javac.util.Context;
-import dagger.Binds;
-import dagger.Module;
-import dagger.Provides;
-import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.compileroption.JavacPluginCompilerOptions;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.util.Types;
-import javax.tools.Diagnostic;
-
-/**
- * A module that provides a {@link BindingGraphFactory} and {@link ComponentDescriptorFactory} for
- * use in {@code javac} plugins. Requires a binding for the {@code javac} {@link Context}.
- */
-@Module
-public abstract class JavacPluginModule {
-  @Binds
-  abstract CompilerOptions compilerOptions(JavacPluginCompilerOptions compilerOptions);
-
-  @Binds
-  abstract Messager messager(NullMessager nullMessager);
-
-  static final class NullMessager implements Messager {
-
-    @Inject
-    NullMessager() {}
-
-    @Override
-    public void printMessage(Diagnostic.Kind kind, CharSequence charSequence) {}
-
-    @Override
-    public void printMessage(Diagnostic.Kind kind, CharSequence charSequence, Element element) {}
-
-    @Override
-    public void printMessage(
-        Diagnostic.Kind kind,
-        CharSequence charSequence,
-        Element element,
-        AnnotationMirror annotationMirror) {}
-
-    @Override
-    public void printMessage(
-        Diagnostic.Kind kind,
-        CharSequence charSequence,
-        Element element,
-        AnnotationMirror annotationMirror,
-        AnnotationValue annotationValue) {}
-  }
-
-  @Provides
-  static DaggerElements daggerElements(Context javaContext) {
-    return new DaggerElements(
-        JavacElements.instance(javaContext), JavacTypes.instance(javaContext));
-  }
-
-  @Provides
-  static DaggerTypes daggerTypes(Context javaContext, DaggerElements elements) {
-    return new DaggerTypes(JavacTypes.instance(javaContext), elements);
-  }
-
-  @Binds abstract Types types(DaggerTypes daggerTypes);
-
-  private JavacPluginModule() {}
-}
diff --git a/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java b/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
index b66d266..cc0d7de 100644
--- a/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
+++ b/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
@@ -16,38 +16,34 @@
 
 package dagger.internal.codegen.javapoet;
 
-import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
 
-import com.google.common.collect.ImmutableSet;
+import com.google.common.base.Ascii;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.squareup.javapoet.AnnotationSpec;
+import java.util.Arrays;
 
 /** Static factories to create {@link AnnotationSpec}s. */
 public final class AnnotationSpecs {
   /** Values for an {@link SuppressWarnings} annotation. */
   public enum Suppression {
-    RAWTYPES("rawtypes"),
-    UNCHECKED("unchecked"),
-    FUTURE_RETURN_VALUE_IGNORED("FutureReturnValueIgnored"),
+    RAWTYPES,
+    UNCHECKED,
     ;
 
-    private final String value;
-
-    Suppression(String value) {
-      this.value = value;
+    @Override
+    public String toString() {
+      return Ascii.toLowerCase(name());
     }
   }
 
   /** Creates an {@link AnnotationSpec} for {@link SuppressWarnings}. */
   public static AnnotationSpec suppressWarnings(Suppression first, Suppression... rest) {
-    return suppressWarnings(ImmutableSet.copyOf(Lists.asList(first, rest)));
-  }
-
-  /** Creates an {@link AnnotationSpec} for {@link SuppressWarnings}. */
-  public static AnnotationSpec suppressWarnings(ImmutableSet<Suppression> suppressions) {
-    checkArgument(!suppressions.isEmpty());
+    checkNotNull(first);
+    Arrays.stream(rest).forEach(Preconditions::checkNotNull);
     AnnotationSpec.Builder builder = AnnotationSpec.builder(SuppressWarnings.class);
-    suppressions.forEach(suppression -> builder.addMember("value", "$S", suppression.value));
+    Lists.asList(first, rest).forEach(suppression -> builder.addMember("value", "$S", suppression));
     return builder.build();
   }
 
diff --git a/java/dagger/internal/codegen/javapoet/BUILD b/java/dagger/internal/codegen/javapoet/BUILD
index ddb9f88..f829d49 100644
--- a/java/dagger/internal/codegen/javapoet/BUILD
+++ b/java/dagger/internal/codegen/javapoet/BUILD
@@ -15,22 +15,20 @@
 # Description:
 #   JavaPoet extensions for use in Dagger
 
-load("@rules_java//java:defs.bzl", "java_library")
-
 package(default_visibility = ["//:src"])
 
 java_library(
     name = "javapoet",
     srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
+    plugins = ["//java/dagger/internal/codegen:bootstrap_compiler_plugin"],
     tags = ["maven:merged"],
     deps = [
         "//java/dagger:core",
         "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:collect",
         "//java/dagger/producers",
+        "@google_bazel_common//third_party/java/auto:common",
         "@google_bazel_common//third_party/java/error_prone:annotations",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
     ],
 )
diff --git a/java/dagger/internal/codegen/javapoet/TypeNames.java b/java/dagger/internal/codegen/javapoet/TypeNames.java
index 71f03f0..9301dbc 100644
--- a/java/dagger/internal/codegen/javapoet/TypeNames.java
+++ b/java/dagger/internal/codegen/javapoet/TypeNames.java
@@ -25,7 +25,6 @@
 import dagger.MembersInjector;
 import dagger.internal.DoubleCheck;
 import dagger.internal.Factory;
-import dagger.internal.InjectedFieldSignature;
 import dagger.internal.InstanceFactory;
 import dagger.internal.MapFactory;
 import dagger.internal.MapProviderFactory;
@@ -35,7 +34,6 @@
 import dagger.internal.SingleCheck;
 import dagger.producers.Produced;
 import dagger.producers.Producer;
-import dagger.producers.ProducerModule;
 import dagger.producers.internal.AbstractProducer;
 import dagger.producers.internal.DependencyMethodProducer;
 import dagger.producers.internal.MapOfProducedProducer;
@@ -59,8 +57,6 @@
   public static final ClassName DOUBLE_CHECK = ClassName.get(DoubleCheck.class);
   public static final ClassName FACTORY = ClassName.get(Factory.class);
   public static final ClassName FUTURES = ClassName.get(Futures.class);
-  public static final ClassName INJECTED_FIELD_SIGNATURE =
-      ClassName.get(InjectedFieldSignature.class);
   public static final ClassName INSTANCE_FACTORY = ClassName.get(InstanceFactory.class);
   public static final ClassName LAZY = ClassName.get(Lazy.class);
   public static final ClassName LIST = ClassName.get(List.class);
@@ -78,7 +74,6 @@
   public static final ClassName PRODUCED = ClassName.get(Produced.class);
   public static final ClassName PRODUCER = ClassName.get(Producer.class);
   public static final ClassName PRODUCERS = ClassName.get(Producers.class);
-  public static final ClassName PRODUCER_MODULE = ClassName.get(ProducerModule.class);
   public static final ClassName PRODUCTION_COMPONENT_MONITOR_FACTORY =
       ClassName.get(ProductionComponentMonitor.Factory.class);
   public static final ClassName PROVIDER = ClassName.get(Provider.class);
diff --git a/java/dagger/internal/codegen/kotlin/BUILD b/java/dagger/internal/codegen/kotlin/BUILD
deleted file mode 100644
index d1c5458..0000000
--- a/java/dagger/internal/codegen/kotlin/BUILD
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Sources related to Kotlin metadata.
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "kotlin",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    tags = ["maven:merged"],
-    deps = [
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/base:shared",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/jsr305_annotations",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-        "@maven//:org_jetbrains_kotlin_kotlin_stdlib",
-        "@maven//:org_jetbrains_kotlinx_kotlinx_metadata_jvm",
-    ],
-)
diff --git a/java/dagger/internal/codegen/kotlin/KotlinMetadata.java b/java/dagger/internal/codegen/kotlin/KotlinMetadata.java
deleted file mode 100644
index 296da44..0000000
--- a/java/dagger/internal/codegen/kotlin/KotlinMetadata.java
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright (C) 2019 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.kotlin;
-
-import static dagger.internal.codegen.base.MoreAnnotationValues.getIntArrayValue;
-import static dagger.internal.codegen.base.MoreAnnotationValues.getIntValue;
-import static dagger.internal.codegen.base.MoreAnnotationValues.getOptionalIntValue;
-import static dagger.internal.codegen.base.MoreAnnotationValues.getOptionalStringValue;
-import static dagger.internal.codegen.base.MoreAnnotationValues.getStringArrayValue;
-import static dagger.internal.codegen.base.MoreAnnotationValues.getStringValue;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
-import static dagger.internal.codegen.langmodel.DaggerElements.getFieldDescriptor;
-import static dagger.internal.codegen.langmodel.DaggerElements.getMethodDescriptor;
-import static kotlinx.metadata.Flag.ValueParameter.DECLARES_DEFAULT_VALUE;
-
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.extension.DaggerCollectors;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Function;
-import javax.annotation.Nullable;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.util.ElementFilter;
-import kotlin.Metadata;
-import kotlinx.metadata.Flag;
-import kotlinx.metadata.KmClassVisitor;
-import kotlinx.metadata.KmConstructorExtensionVisitor;
-import kotlinx.metadata.KmConstructorVisitor;
-import kotlinx.metadata.KmExtensionType;
-import kotlinx.metadata.KmFunctionExtensionVisitor;
-import kotlinx.metadata.KmFunctionVisitor;
-import kotlinx.metadata.KmPropertyExtensionVisitor;
-import kotlinx.metadata.KmPropertyVisitor;
-import kotlinx.metadata.KmValueParameterVisitor;
-import kotlinx.metadata.jvm.JvmConstructorExtensionVisitor;
-import kotlinx.metadata.jvm.JvmFieldSignature;
-import kotlinx.metadata.jvm.JvmFunctionExtensionVisitor;
-import kotlinx.metadata.jvm.JvmMethodSignature;
-import kotlinx.metadata.jvm.JvmPropertyExtensionVisitor;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
-
-/** Data class of a TypeElement and its Kotlin metadata. */
-@AutoValue
-abstract class KotlinMetadata {
-  // Kotlin suffix for fields that are for a delegated property.
-  // See:
-  // https://github.com/JetBrains/kotlin/blob/master/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAbi.kt#L32
-  private static final String DELEGATED_PROPERTY_NAME_SUFFIX = "$delegate";
-
-  // Map that associates field elements with its Kotlin synthetic method for annotations.
-  private final Map<VariableElement, Optional<MethodForAnnotations>>
-      elementFieldAnnotationMethodMap = new HashMap<>();
-
-  // Map that associates field elements with its Kotlin getter method.
-  private final Map<VariableElement, Optional<ExecutableElement>> elementFieldGetterMethodMap =
-      new HashMap<>();
-
-  abstract TypeElement typeElement();
-
-  abstract ClassMetadata classMetadata();
-
-  @Memoized
-  ImmutableMap<String, ExecutableElement> methodDescriptors() {
-    return ElementFilter.methodsIn(typeElement().getEnclosedElements()).stream()
-        .collect(toImmutableMap(DaggerElements::getMethodDescriptor, Function.identity()));
-  }
-
-  /** Returns true if any constructor of the defined a default parameter. */
-  @Memoized
-  boolean containsConstructorWithDefaultParam() {
-    return classMetadata().constructors().stream()
-        .flatMap(constructor -> constructor.parameters().stream())
-        .anyMatch(parameter -> parameter.flags(DECLARES_DEFAULT_VALUE));
-  }
-
-  /** Gets the synthetic method for annotations of a given field element. */
-  Optional<ExecutableElement> getSyntheticAnnotationMethod(VariableElement fieldElement) {
-    return getAnnotationMethod(fieldElement)
-        .map(
-            methodForAnnotations -> {
-              if (methodForAnnotations == MethodForAnnotations.MISSING) {
-                throw new IllegalStateException(
-                    "Method for annotations is missing for " + fieldElement);
-              }
-              return methodForAnnotations.method();
-            });
-  }
-
-  /**
-   * Returns true if the synthetic method for annotations is missing. This can occur when inspecting
-   * the Kotlin metadata of a property from another compilation unit.
-   */
-  boolean isMissingSyntheticAnnotationMethod(VariableElement fieldElement) {
-    return getAnnotationMethod(fieldElement)
-        .map(methodForAnnotations -> methodForAnnotations == MethodForAnnotations.MISSING)
-        // This can be missing if there was no property annotation at all (e.g. no annotations or
-        // the qualifier is already properly attached to the field). For these cases, it isn't
-        // considered missing since there was no method to look for in the first place.
-        .orElse(false);
-  }
-
-  private Optional<MethodForAnnotations> getAnnotationMethod(VariableElement fieldElement) {
-    return elementFieldAnnotationMethodMap.computeIfAbsent(
-        fieldElement, this::getAnnotationMethodUncached);
-  }
-
-  private Optional<MethodForAnnotations> getAnnotationMethodUncached(VariableElement fieldElement) {
-    return findProperty(fieldElement)
-        .methodForAnnotationsSignature()
-        .map(
-            signature ->
-                Optional.ofNullable(methodDescriptors().get(signature))
-                    .map(MethodForAnnotations::create)
-                    // The method may be missing across different compilations.
-                    // See https://youtrack.jetbrains.com/issue/KT-34684
-                    .orElse(MethodForAnnotations.MISSING));
-  }
-
-  /** Gets the getter method of a given field element corresponding to a property. */
-  Optional<ExecutableElement> getPropertyGetter(VariableElement fieldElement) {
-    return elementFieldGetterMethodMap.computeIfAbsent(
-        fieldElement, this::getPropertyGetterUncached);
-  }
-
-  private Optional<ExecutableElement> getPropertyGetterUncached(VariableElement fieldElement) {
-    return findProperty(fieldElement)
-        .getterSignature()
-        .flatMap(signature -> Optional.ofNullable(methodDescriptors().get(signature)));
-  }
-
-  private PropertyMetadata findProperty(VariableElement field) {
-    String fieldDescriptor = getFieldDescriptor(field);
-    if (classMetadata().propertiesByFieldSignature().containsKey(fieldDescriptor)) {
-      return classMetadata().propertiesByFieldSignature().get(fieldDescriptor);
-    } else {
-      // Fallback to finding property by name, see: https://youtrack.jetbrains.com/issue/KT-35124
-      final String propertyName = getPropertyNameFromField(field);
-      return classMetadata().propertiesByFieldSignature().values().stream()
-          .filter(property -> propertyName.contentEquals(property.name()))
-          .collect(DaggerCollectors.onlyElement());
-    }
-  }
-
-  private static String getPropertyNameFromField(VariableElement field) {
-    String name = field.getSimpleName().toString();
-    if (name.endsWith(DELEGATED_PROPERTY_NAME_SUFFIX)) {
-      return name.substring(0, name.length() - DELEGATED_PROPERTY_NAME_SUFFIX.length());
-    } else {
-      return name;
-    }
-  }
-
-  FunctionMetadata getFunctionMetadata(ExecutableElement method) {
-    return classMetadata().functionsBySignature().get(getMethodDescriptor(method));
-  }
-
-  /** Parse Kotlin class metadata from a given type element * */
-  static KotlinMetadata from(TypeElement typeElement) {
-    return new AutoValue_KotlinMetadata(
-        typeElement, ClassVisitor.createClassMetadata(metadataOf(typeElement)));
-  }
-
-  private static KotlinClassMetadata.Class metadataOf(TypeElement typeElement) {
-    Optional<AnnotationMirror> metadataAnnotation =
-        getAnnotationMirror(typeElement, Metadata.class);
-    Preconditions.checkState(metadataAnnotation.isPresent());
-    KotlinClassHeader header =
-        new KotlinClassHeader(
-            getIntValue(metadataAnnotation.get(), "k"),
-            getIntArrayValue(metadataAnnotation.get(), "mv"),
-            getIntArrayValue(metadataAnnotation.get(), "bv"),
-            getStringArrayValue(metadataAnnotation.get(), "d1"),
-            getStringArrayValue(metadataAnnotation.get(), "d2"),
-            getStringValue(metadataAnnotation.get(), "xs"),
-            getOptionalStringValue(metadataAnnotation.get(), "pn").orElse(null),
-            getOptionalIntValue(metadataAnnotation.get(), "xi").orElse(null));
-    KotlinClassMetadata metadata = KotlinClassMetadata.read(header);
-    if (metadata == null) {
-      // Should only happen on Kotlin < 1.0 (i.e. metadata version < 1.1)
-      throw new IllegalStateException(
-          "Unsupported metadata version. Check that your Kotlin version is >= 1.0");
-    }
-    if (metadata instanceof KotlinClassMetadata.Class) {
-      // TODO(danysantiago): If when we need other types of metadata then move to right method.
-      return (KotlinClassMetadata.Class) metadata;
-    } else {
-      throw new IllegalStateException("Unsupported metadata type: " + metadata);
-    }
-  }
-
-  private static final class ClassVisitor extends KmClassVisitor {
-    static ClassMetadata createClassMetadata(KotlinClassMetadata.Class data) {
-      ClassVisitor visitor = new ClassVisitor();
-      data.accept(visitor);
-      return visitor.classMetadata.build();
-    }
-
-    private final ClassMetadata.Builder classMetadata = ClassMetadata.builder();
-
-    @Override
-    public void visit(int flags, String name) {
-      classMetadata.flags(flags).name(name);
-    }
-
-    @Override
-    public KmConstructorVisitor visitConstructor(int flags) {
-      return new KmConstructorVisitor() {
-        private final FunctionMetadata.Builder constructor =
-            FunctionMetadata.builder(flags, "<init>");
-
-        @Override
-        public KmValueParameterVisitor visitValueParameter(int flags, String name) {
-          constructor.addParameter(ValueParameterMetadata.create(flags, name));
-          return super.visitValueParameter(flags, name);
-        }
-
-        @Override
-        public KmConstructorExtensionVisitor visitExtensions(KmExtensionType kmExtensionType) {
-          return kmExtensionType.equals(JvmConstructorExtensionVisitor.TYPE)
-              ? new JvmConstructorExtensionVisitor() {
-                @Override
-                public void visit(JvmMethodSignature jvmMethodSignature) {
-                  constructor.signature(jvmMethodSignature.asString());
-                }
-              }
-              : null;
-        }
-
-        @Override
-        public void visitEnd() {
-          classMetadata.addConstructor(constructor.build());
-        }
-      };
-    }
-
-    @Override
-    public KmFunctionVisitor visitFunction(int flags, String name) {
-      return new KmFunctionVisitor() {
-        private final FunctionMetadata.Builder function = FunctionMetadata.builder(flags, name);
-
-        @Override
-        public KmValueParameterVisitor visitValueParameter(int flags, String name) {
-          function.addParameter(ValueParameterMetadata.create(flags, name));
-          return super.visitValueParameter(flags, name);
-        }
-
-        @Override
-        public KmFunctionExtensionVisitor visitExtensions(KmExtensionType kmExtensionType) {
-          return kmExtensionType.equals(JvmFunctionExtensionVisitor.TYPE)
-              ? new JvmFunctionExtensionVisitor() {
-                @Override
-                public void visit(JvmMethodSignature jvmMethodSignature) {
-                  function.signature(jvmMethodSignature.asString());
-                }
-              }
-              : null;
-        }
-
-        @Override
-        public void visitEnd() {
-          classMetadata.addFunction(function.build());
-        }
-      };
-    }
-
-    @Override
-    public void visitCompanionObject(String companionObjectName) {
-      classMetadata.companionObjectName(companionObjectName);
-    }
-
-    @Override
-    public KmPropertyVisitor visitProperty(
-        int flags, String name, int getterFlags, int setterFlags) {
-      return new KmPropertyVisitor() {
-        private final PropertyMetadata.Builder property = PropertyMetadata.builder(flags, name);
-
-        @Override
-        public KmPropertyExtensionVisitor visitExtensions(KmExtensionType kmExtensionType) {
-          if (!kmExtensionType.equals(JvmPropertyExtensionVisitor.TYPE)) {
-            return null;
-          }
-
-          return new JvmPropertyExtensionVisitor() {
-            @Override
-            public void visit(
-                int jvmFlags,
-                @Nullable JvmFieldSignature jvmFieldSignature,
-                @Nullable JvmMethodSignature jvmGetterSignature,
-                @Nullable JvmMethodSignature jvmSetterSignature) {
-              property.fieldSignature(
-                  Optional.ofNullable(jvmFieldSignature).map(JvmFieldSignature::asString));
-              property.getterSignature(
-                  Optional.ofNullable(jvmGetterSignature).map(JvmMethodSignature::asString));
-            }
-
-            @Override
-            public void visitSyntheticMethodForAnnotations(
-                @Nullable JvmMethodSignature methodSignature) {
-              property.methodForAnnotationsSignature(
-                  Optional.ofNullable(methodSignature).map(JvmMethodSignature::asString));
-            }
-          };
-        }
-
-        @Override
-        public void visitEnd() {
-          classMetadata.addProperty(property.build());
-        }
-      };
-    }
-  }
-
-  @AutoValue
-  abstract static class ClassMetadata extends BaseMetadata {
-    abstract Optional<String> companionObjectName();
-
-    abstract ImmutableSet<FunctionMetadata> constructors();
-
-    abstract ImmutableMap<String, FunctionMetadata> functionsBySignature();
-
-    abstract ImmutableMap<String, PropertyMetadata> propertiesByFieldSignature();
-
-    static Builder builder() {
-      return new AutoValue_KotlinMetadata_ClassMetadata.Builder();
-    }
-
-    @AutoValue.Builder
-    abstract static class Builder implements BaseMetadata.Builder<Builder> {
-      abstract Builder companionObjectName(String companionObjectName);
-
-      abstract ImmutableSet.Builder<FunctionMetadata> constructorsBuilder();
-
-      abstract ImmutableMap.Builder<String, FunctionMetadata> functionsBySignatureBuilder();
-
-      abstract ImmutableMap.Builder<String, PropertyMetadata> propertiesByFieldSignatureBuilder();
-
-      Builder addConstructor(FunctionMetadata constructor) {
-        constructorsBuilder().add(constructor);
-        return this;
-      }
-
-      Builder addFunction(FunctionMetadata function) {
-        functionsBySignatureBuilder().put(function.signature(), function);
-        return this;
-      }
-
-      Builder addProperty(PropertyMetadata property) {
-        if (property.fieldSignature().isPresent()) {
-          propertiesByFieldSignatureBuilder().put(property.fieldSignature().get(), property);
-        }
-        return this;
-      }
-
-      abstract ClassMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class FunctionMetadata extends BaseMetadata {
-    abstract String signature();
-
-    abstract ImmutableList<ValueParameterMetadata> parameters();
-
-    static Builder builder(int flags, String name) {
-      return new AutoValue_KotlinMetadata_FunctionMetadata.Builder().flags(flags).name(name);
-    }
-
-    @AutoValue.Builder
-    abstract static class Builder implements BaseMetadata.Builder<Builder> {
-      abstract Builder signature(String signature);
-
-      abstract ImmutableList.Builder<ValueParameterMetadata> parametersBuilder();
-
-      Builder addParameter(ValueParameterMetadata parameter) {
-        parametersBuilder().add(parameter);
-        return this;
-      }
-
-      abstract FunctionMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class PropertyMetadata extends BaseMetadata {
-    /** Returns the JVM field descriptor of the backing field of this property. */
-    abstract Optional<String> fieldSignature();
-
-    abstract Optional<String> getterSignature();
-
-    /** Returns JVM method descriptor of the synthetic method for property annotations. */
-    abstract Optional<String> methodForAnnotationsSignature();
-
-    static Builder builder(int flags, String name) {
-      return new AutoValue_KotlinMetadata_PropertyMetadata.Builder().flags(flags).name(name);
-    }
-
-    @AutoValue.Builder
-    interface Builder extends BaseMetadata.Builder<Builder> {
-      Builder fieldSignature(Optional<String> signature);
-
-      Builder getterSignature(Optional<String> signature);
-
-      Builder methodForAnnotationsSignature(Optional<String> signature);
-
-      PropertyMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class ValueParameterMetadata extends BaseMetadata {
-    private static ValueParameterMetadata create(int flags, String name) {
-      return new AutoValue_KotlinMetadata_ValueParameterMetadata(flags, name);
-    }
-  }
-
-  abstract static class BaseMetadata {
-    /** Returns the Kotlin metadata flags for this property. */
-    abstract int flags();
-
-    /** returns {@code true} if the given flag (e.g. {@link Flag.IS_PRIVATE}) applies. */
-    boolean flags(Flag flag) {
-      return flag.invoke(flags());
-    }
-
-    /** Returns the simple name of this property. */
-    abstract String name();
-
-    interface Builder<BuilderT> {
-      BuilderT flags(int flags);
-
-      BuilderT name(String name);
-    }
-  }
-
-  @AutoValue
-  abstract static class MethodForAnnotations {
-    static MethodForAnnotations create(ExecutableElement method) {
-      return new AutoValue_KotlinMetadata_MethodForAnnotations(method);
-    }
-
-    static final MethodForAnnotations MISSING = MethodForAnnotations.create(null);
-
-    @Nullable
-    abstract ExecutableElement method();
-  }
-}
diff --git a/java/dagger/internal/codegen/kotlin/KotlinMetadataFactory.java b/java/dagger/internal/codegen/kotlin/KotlinMetadataFactory.java
deleted file mode 100644
index 1515469..0000000
--- a/java/dagger/internal/codegen/kotlin/KotlinMetadataFactory.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 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.kotlin;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
-
-import dagger.internal.codegen.base.ClearableCache;
-import java.util.HashMap;
-import java.util.Map;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import kotlin.Metadata;
-
-/**
- * Factory creating Kotlin metadata data objects.
- *
- * <p>The metadata is cache since it can be expensive to parse the information stored in a proto
- * binary string format in the metadata annotation values.
- */
-@Singleton
-public final class KotlinMetadataFactory implements ClearableCache {
-  private final Map<TypeElement, KotlinMetadata> metadataCache = new HashMap<>();
-
-  @Inject
-  KotlinMetadataFactory() {}
-
-  /**
-   * Parses and returns the {@link KotlinMetadata} out of a given element.
-   *
-   * @throws IllegalStateException if the element has no metadata or is not enclosed in a type
-   *     element with metadata. To check if an element has metadata use {@link
-   *     KotlinMetadataUtil#hasMetadata(Element)}
-   */
-  public KotlinMetadata create(Element element) {
-    TypeElement enclosingElement = closestEnclosingTypeElement(element);
-    if (!isAnnotationPresent(enclosingElement, Metadata.class)) {
-      throw new IllegalStateException("Missing @Metadata for: " + enclosingElement);
-    }
-    return metadataCache.computeIfAbsent(enclosingElement, KotlinMetadata::from);
-  }
-
-  @Override
-  public void clearCache() {
-    metadataCache.clear();
-  }
-}
diff --git a/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java b/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java
deleted file mode 100644
index 76d28f0..0000000
--- a/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2019 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.kotlin;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotatedAnnotations;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
-import static kotlinx.metadata.Flag.Class.IS_COMPANION_OBJECT;
-import static kotlinx.metadata.Flag.Class.IS_DATA;
-import static kotlinx.metadata.Flag.Class.IS_OBJECT;
-import static kotlinx.metadata.Flag.IS_PRIVATE;
-
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-import dagger.internal.codegen.extension.DaggerCollectors;
-import java.lang.annotation.Annotation;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.util.ElementFilter;
-import kotlin.Metadata;
-import kotlin.jvm.JvmStatic;
-import kotlinx.metadata.Flag;
-
-/** Utility class for interacting with Kotlin Metadata. */
-public final class KotlinMetadataUtil {
-
-  private final KotlinMetadataFactory metadataFactory;
-
-  @Inject
-  KotlinMetadataUtil(KotlinMetadataFactory metadataFactory) {
-    this.metadataFactory = metadataFactory;
-  }
-
-  /**
-   * Returns {@code true} if this element has the Kotlin Metadata annotation or if it is enclosed in
-   * an element that does.
-   */
-  public boolean hasMetadata(Element element) {
-    return isAnnotationPresent(closestEnclosingTypeElement(element), Metadata.class);
-  }
-
-  /**
-   * Returns the synthetic annotations of a Kotlin property.
-   *
-   * <p>Note that this method only looks for additional annotations in the synthetic property
-   * method, if any, of a Kotlin property and not for annotations in its backing field.
-   */
-  public ImmutableCollection<? extends AnnotationMirror> getSyntheticPropertyAnnotations(
-      VariableElement fieldElement, Class<? extends Annotation> annotationType) {
-    return metadataFactory
-        .create(fieldElement)
-        .getSyntheticAnnotationMethod(fieldElement)
-        .map(methodElement -> getAnnotatedAnnotations(methodElement, annotationType).asList())
-        .orElse(ImmutableList.of());
-  }
-
-  /**
-   * Returns {@code true} if the synthetic method for annotations is missing. This can occur when
-   * the Kotlin metadata of the property reports that it contains a synthetic method for annotations
-   * but such method is not found since it is synthetic and ignored by the processor.
-   */
-  public boolean isMissingSyntheticPropertyForAnnotations(VariableElement fieldElement) {
-    return metadataFactory.create(fieldElement).isMissingSyntheticAnnotationMethod(fieldElement);
-  }
-
-  /** Returns {@code true} if this type element is a Kotlin Object. */
-  public boolean isObjectClass(TypeElement typeElement) {
-    return hasMetadata(typeElement)
-        && metadataFactory.create(typeElement).classMetadata().flags(IS_OBJECT);
-  }
-
-  /** Returns {@code true} if this type element is a Kotlin data class. */
-  public boolean isDataClass(TypeElement typeElement) {
-    return hasMetadata(typeElement)
-        && metadataFactory.create(typeElement).classMetadata().flags(IS_DATA);
-  }
-
-  /* Returns {@code true} if this type element is a Kotlin Companion Object. */
-  public boolean isCompanionObjectClass(TypeElement typeElement) {
-    return hasMetadata(typeElement)
-        && metadataFactory.create(typeElement).classMetadata().flags(IS_COMPANION_OBJECT);
-  }
-
-  /* Returns {@code true} if this type element has a Kotlin Companion Object. */
-  public boolean hasEnclosedCompanionObject(TypeElement typeElement) {
-    return hasMetadata(typeElement)
-        && metadataFactory.create(typeElement).classMetadata().companionObjectName().isPresent();
-  }
-
-  /* Returns the Companion Object element enclosed by the given type element. */
-  public TypeElement getEnclosedCompanionObject(TypeElement typeElement) {
-    return metadataFactory
-        .create(typeElement)
-        .classMetadata()
-        .companionObjectName()
-        .map(
-            companionObjectName ->
-                ElementFilter.typesIn(typeElement.getEnclosedElements()).stream()
-                    .filter(
-                        innerType -> innerType.getSimpleName().contentEquals(companionObjectName))
-                    .collect(DaggerCollectors.onlyElement()))
-        .get();
-  }
-
-  /**
-   * Returns {@code true} if the given type element was declared <code>private</code> in its Kotlin
-   * source.
-   */
-  public boolean isVisibilityPrivate(TypeElement typeElement) {
-    return hasMetadata(typeElement)
-        && metadataFactory.create(typeElement).classMetadata().flags(IS_PRIVATE);
-  }
-
-  /**
-   * Returns {@code true} if the given executable element was declared {@code internal} in its
-   * Kotlin source.
-   */
-  public boolean isVisibilityInternal(ExecutableElement method) {
-    return hasMetadata(method)
-        && metadataFactory.create(method).getFunctionMetadata(method).flags(Flag.IS_INTERNAL);
-  }
-
-  public Optional<ExecutableElement> getPropertyGetter(VariableElement fieldElement) {
-    return metadataFactory.create(fieldElement).getPropertyGetter(fieldElement);
-  }
-
-  public boolean containsConstructorWithDefaultParam(TypeElement typeElement) {
-    return hasMetadata(typeElement)
-        && metadataFactory.create(typeElement).containsConstructorWithDefaultParam();
-  }
-
-  /**
-   * Returns {@code true} if the <code>@JvmStatic</code> annotation is present in the given element.
-   */
-  public static boolean isJvmStaticPresent(ExecutableElement element) {
-    return isAnnotationPresent(element, JvmStatic.class);
-  }
-}
diff --git a/java/dagger/internal/codegen/kythe/BUILD b/java/dagger/internal/codegen/kythe/BUILD
deleted file mode 100644
index 9e8dea1..0000000
--- a/java/dagger/internal/codegen/kythe/BUILD
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (C) 2017 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.
-
-# Description:
-#   A library for the kythe plugin.
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "kythe",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen:component-codegen"],
-    deps = [
-        ":kythe_plugin",
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/javac",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/codegen/validation",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "@google_bazel_common//third_party/java/auto:service",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-load("@rules_java//java:defs.bzl", "java_import")
-
-# A _deploy.jar consisting of the java_librarys in https://github.com/kythe/kythe needed to build a
-# Kythe plugin
-# TODO(ronshapiro): replace this with a http_archive of the next release in
-# https://github.com/kythe/kythe/releases
-java_import(
-    name = "kythe_plugin",
-    jars = ["kythe_plugin_deploy.jar"],
-    neverlink = 1,
-)
diff --git a/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java b/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java
deleted file mode 100644
index 4c6f85e..0000000
--- a/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-// This must be in the dagger.internal.codegen package since Dagger doesn't expose its APIs publicly
-// https://github.com/google/dagger/issues/773 could present an opportunity to put this somewhere in
-// the regular kythe/java tree.
-package dagger.internal.codegen.kythe;
-
-import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
-
-import com.google.auto.service.AutoService;
-import com.google.common.collect.Iterables;
-import com.google.devtools.kythe.analyzers.base.EntrySet;
-import com.google.devtools.kythe.analyzers.base.FactEmitter;
-import com.google.devtools.kythe.analyzers.base.KytheEntrySets;
-import com.google.devtools.kythe.analyzers.java.Plugin;
-import com.google.devtools.kythe.proto.Storage.VName;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.Context;
-import dagger.BindsInstance;
-import dagger.Component;
-import dagger.internal.codegen.binding.Binding;
-import dagger.internal.codegen.binding.BindingDeclaration;
-import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.BindingNode;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
-import dagger.internal.codegen.binding.ModuleDescriptor;
-import dagger.internal.codegen.javac.JavacPluginModule;
-import dagger.internal.codegen.validation.InjectBindingRegistryModule;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.BindingGraph.Edge;
-import dagger.model.BindingGraph.Node;
-import dagger.model.DependencyRequest;
-import dagger.producers.ProductionComponent;
-import java.util.Optional;
-import java.util.logging.Logger;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.lang.model.element.Element;
-
-/**
- * A plugin which emits nodes and edges for <a href="https://github.com/google/dagger">Dagger</a>
- * specific code.
- */
-@AutoService(Plugin.class)
-public class DaggerKythePlugin extends Plugin.Scanner<Void, Void> {
-  // TODO(ronshapiro): use flogger
-  private static final Logger logger = Logger.getLogger(DaggerKythePlugin.class.getCanonicalName());
-  private FactEmitter emitter;
-  @Inject ComponentDescriptorFactory componentDescriptorFactory;
-  @Inject BindingGraphFactory bindingGraphFactory;
-
-  @Override
-  public Void visitClassDef(JCClassDecl tree, Void p) {
-    if (tree.sym != null
-        && isAnyAnnotationPresent(tree.sym, Component.class, ProductionComponent.class)) {
-      addNodesForGraph(
-          bindingGraphFactory.create(
-              componentDescriptorFactory.rootComponentDescriptor(tree.sym), false));
-    }
-    return super.visitClassDef(tree, p);
-  }
-
-  private void addNodesForGraph(dagger.internal.codegen.binding.BindingGraph graph) {
-    addDependencyEdges(graph.topLevelBindingGraph());
-
-    // TODO(bcorso): Convert these to use the new BindingGraph
-    addModuleEdges(graph);
-    addChildComponentEdges(graph);
-  }
-
-  private void addDependencyEdges(BindingGraph graph) {
-    for (DependencyEdge dependencyEdge : graph.dependencyEdges()) {
-      DependencyRequest dependency = dependencyEdge.dependencyRequest();
-      Node node = graph.network().incidentNodes(dependencyEdge).target();
-      addEdgesForDependencyRequest(dependency, (BindingNode) node, graph);
-    }
-  }
-
-  /**
-   * Add {@code /inject/satisfiedby} edges from {@code dependency}'s {@link
-   * DependencyRequest#requestElement()} to any {@link BindingDeclaration#bindingElement() binding
-   * elements} that satisfy the request.
-   *
-   * <p>This collapses requests for synthetic bindings so that a request for a multibound key
-   * points to all of the contributions for the multibound object. It does so by recursively calling
-   * this method, with each dependency's key as the {@code targetKey}.
-   */
-  private void addEdgesForDependencyRequest(
-      DependencyRequest dependency, BindingNode bindingNode, BindingGraph graph) {
-    if (!dependency.requestElement().isPresent()) {
-      return;
-    }
-    Binding binding = bindingNode.delegate();
-    if (binding.bindingElement().isPresent()) {
-      addDependencyEdge(dependency, binding);
-    } else {
-      for (Edge outEdge : graph.network().outEdges(bindingNode)) {
-        if (outEdge instanceof DependencyEdge) {
-          Node outNode = graph.network().incidentNodes(outEdge).target();
-          addEdgesForDependencyRequest(dependency, (BindingNode) outNode, graph);
-        }
-      }
-    }
-    for (BindingDeclaration bindingDeclaration :
-        Iterables.concat(
-            bindingNode.multibindingDeclarations(),
-            bindingNode.optionalBindingDeclarations())) {
-      addDependencyEdge(dependency, bindingDeclaration);
-    }
-  }
-
-  private void addDependencyEdge(
-      DependencyRequest dependency, BindingDeclaration bindingDeclaration) {
-    Element requestElement = dependency.requestElement().get();
-    Element bindingElement = bindingDeclaration.bindingElement().get();
-    Optional<VName> requestElementNode = jvmNode(requestElement, "request element");
-    Optional<VName> bindingElementNode = jvmNode(bindingElement, "binding element");
-    emitEdge(requestElementNode, "/inject/satisfiedby", bindingElementNode);
-    // TODO(ronshapiro): emit facts about the component that satisfies the edge
-  }
-
-  private void addModuleEdges(dagger.internal.codegen.binding.BindingGraph graph) {
-    Optional<VName> componentNode = jvmNode(graph.componentTypeElement(), "component");
-    for (ModuleDescriptor module : graph.componentDescriptor().modules()) {
-      Optional<VName> moduleNode = jvmNode(module.moduleElement(), "module");
-      emitEdge(componentNode, "/inject/installsmodule", moduleNode);
-    }
-    graph.subgraphs().forEach(this::addModuleEdges);
-  }
-
-  private void addChildComponentEdges(dagger.internal.codegen.binding.BindingGraph graph) {
-    Optional<VName> componentNode = jvmNode(graph.componentTypeElement(), "component");
-    for (dagger.internal.codegen.binding.BindingGraph subgraph : graph.subgraphs()) {
-      Optional<VName> subcomponentNode =
-          jvmNode(subgraph.componentTypeElement(), "child component");
-      emitEdge(componentNode, "/inject/childcomponent", subcomponentNode);
-    }
-    graph.subgraphs().forEach(this::addChildComponentEdges);
-  }
-
-  private Optional<VName> jvmNode(Element element, String name) {
-    Optional<VName> jvmNode = kytheGraph.getJvmNode((Symbol) element).map(KytheNode::getVName);
-    if (!jvmNode.isPresent()) {
-      logger.warning(String.format("Missing JVM node for %s: %s", name, element));
-    }
-    return jvmNode;
-  }
-
-  private void emitEdge(Optional<VName> source, String edgeName, Optional<VName> target) {
-    source.ifPresent(
-        s -> target.ifPresent(t -> new EntrySet.Builder(s, edgeName, t).build().emit(emitter)));
-  }
-
-  @Override
-  public void run(
-      JCCompilationUnit compilationUnit, KytheEntrySets entrySets, KytheGraph kytheGraph) {
-    if (bindingGraphFactory == null) {
-      emitter = entrySets.getEmitter();
-      DaggerDaggerKythePlugin_PluginComponent.builder()
-          .context(kytheGraph.getJavaContext())
-          .build()
-          .inject(this);
-    }
-    super.run(compilationUnit, entrySets, kytheGraph);
-  }
-
-  @Singleton
-  @Component(modules = {InjectBindingRegistryModule.class, JavacPluginModule.class})
-  interface PluginComponent {
-    void inject(DaggerKythePlugin plugin);
-
-    @Component.Builder
-    interface Builder {
-      @BindsInstance
-      Builder context(Context context);
-
-      PluginComponent build();
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/kythe/kythe_plugin_deploy.jar b/java/dagger/internal/codegen/kythe_plugin_deploy.jar
similarity index 100%
rename from java/dagger/internal/codegen/kythe/kythe_plugin_deploy.jar
rename to java/dagger/internal/codegen/kythe_plugin_deploy.jar
Binary files differ
diff --git a/java/dagger/internal/codegen/langmodel/BUILD b/java/dagger/internal/codegen/langmodel/BUILD
index 670f4aa..16fa5d8 100644
--- a/java/dagger/internal/codegen/langmodel/BUILD
+++ b/java/dagger/internal/codegen/langmodel/BUILD
@@ -15,22 +15,17 @@
 # Description:
 #   Dagger-specific extensions to the javax.lang.model APIs
 
-load("@rules_java//java:defs.bzl", "java_library")
-
 package(default_visibility = ["//:src"])
 
 java_library(
     name = "langmodel",
     srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
+    plugins = ["//java/dagger/internal/codegen:bootstrap_compiler_plugin"],
     tags = ["maven:merged"],
     deps = [
         "//java/dagger:core",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
-        "//java/dagger/internal/guava:graph",
+        "@google_bazel_common//third_party/java/auto:common",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/javapoet",
-        "@maven//:com_google_auto_auto_common",
     ],
 )
diff --git a/java/dagger/internal/codegen/langmodel/DaggerElements.java b/java/dagger/internal/codegen/langmodel/DaggerElements.java
index 12cec31..873ad3d 100644
--- a/java/dagger/internal/codegen/langmodel/DaggerElements.java
+++ b/java/dagger/internal/codegen/langmodel/DaggerElements.java
@@ -28,7 +28,6 @@
 import com.google.auto.common.MoreElements;
 import com.google.auto.common.MoreTypes;
 import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.graph.Traverser;
@@ -43,7 +42,6 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.AnnotationValue;
@@ -53,22 +51,8 @@
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Name;
 import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.QualifiedNameable;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ErrorType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.IntersectionType;
-import javax.lang.model.type.NoType;
-import javax.lang.model.type.NullType;
-import javax.lang.model.type.PrimitiveType;
 import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVariable;
-import javax.lang.model.type.UnionType;
-import javax.lang.model.type.WildcardType;
-import javax.lang.model.util.AbstractTypeVisitor8;
 import javax.lang.model.util.Elements;
 import javax.lang.model.util.SimpleElementVisitor8;
 import javax.lang.model.util.Types;
@@ -247,161 +231,6 @@
   }
 
   /**
-   * Returns the field descriptor of the given {@code element}.
-   *
-   * <p>This is useful for matching Kotlin Metadata JVM Signatures with elements from the AST.
-   *
-   * <p>For reference, see the <a
-   * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2">JVM
-   * specification, section 4.3.2</a>.
-   */
-  public static String getFieldDescriptor(VariableElement element) {
-    return element.getSimpleName() + ":" + getDescriptor(element.asType());
-  }
-
-  /**
-   * Returns the method descriptor of the given {@code element}.
-   *
-   * <p>This is useful for matching Kotlin Metadata JVM Signatures with elements from the AST.
-   *
-   * <p>For reference, see the <a
-   * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.3">JVM
-   * specification, section 4.3.3</a>.
-   */
-  public static String getMethodDescriptor(ExecutableElement element) {
-    return element.getSimpleName() + getDescriptor(element.asType());
-  }
-
-  private static String getDescriptor(TypeMirror t) {
-    return t.accept(JVM_DESCRIPTOR_TYPE_VISITOR, null);
-  }
-
-  private static final AbstractTypeVisitor8<String, Void> JVM_DESCRIPTOR_TYPE_VISITOR =
-      new AbstractTypeVisitor8<String, Void>() {
-
-        @Override
-        public String visitArray(ArrayType arrayType, Void v) {
-          return "[" + getDescriptor(arrayType.getComponentType());
-        }
-
-        @Override
-        public String visitDeclared(DeclaredType declaredType, Void v) {
-          return "L" + getInternalName(declaredType.asElement()) + ";";
-        }
-
-        @Override
-        public String visitError(ErrorType errorType, Void v) {
-          // For descriptor generating purposes we don't need a fully modeled type since we are
-          // only interested in obtaining the class name in its "internal form".
-          return visitDeclared(errorType, v);
-        }
-
-        @Override
-        public String visitExecutable(ExecutableType executableType, Void v) {
-          String parameterDescriptors =
-              executableType.getParameterTypes().stream()
-                  .map(DaggerElements::getDescriptor)
-                  .collect(Collectors.joining());
-          String returnDescriptor = getDescriptor(executableType.getReturnType());
-          return "(" + parameterDescriptors + ")" + returnDescriptor;
-        }
-
-        @Override
-        public String visitIntersection(IntersectionType intersectionType, Void v) {
-          // For a type variable with multiple bounds: "the erasure of a type variable is determined
-          // by the first type in its bound" - JVM Spec Sec 4.4
-          return getDescriptor(intersectionType.getBounds().get(0));
-        }
-
-        @Override
-        public String visitNoType(NoType noType, Void v) {
-          return "V";
-        }
-
-        @Override
-        public String visitNull(NullType nullType, Void v) {
-          return visitUnknown(nullType, null);
-        }
-
-        @Override
-        public String visitPrimitive(PrimitiveType primitiveType, Void v) {
-          switch (primitiveType.getKind()) {
-            case BOOLEAN:
-              return "Z";
-            case BYTE:
-              return "B";
-            case SHORT:
-              return "S";
-            case INT:
-              return "I";
-            case LONG:
-              return "J";
-            case CHAR:
-              return "C";
-            case FLOAT:
-              return "F";
-            case DOUBLE:
-              return "D";
-            default:
-              throw new IllegalArgumentException("Unknown primitive type.");
-          }
-        }
-
-        @Override
-        public String visitTypeVariable(TypeVariable typeVariable, Void v) {
-          // The erasure of a type variable is the erasure of its leftmost bound. - JVM Spec Sec 4.6
-          return getDescriptor(typeVariable.getUpperBound());
-        }
-
-        @Override
-        public String visitUnion(UnionType unionType, Void v) {
-          return visitUnknown(unionType, null);
-        }
-
-        @Override
-        public String visitUnknown(TypeMirror typeMirror, Void v) {
-          throw new IllegalArgumentException("Unsupported type: " + typeMirror);
-        }
-
-        @Override
-        public String visitWildcard(WildcardType wildcardType, Void v) {
-          return "";
-        }
-
-        /**
-         * Returns the name of this element in its "internal form".
-         *
-         * <p>For reference, see the <a
-         * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.2">JVM
-         * specification, section 4.2</a>.
-         */
-        private String getInternalName(Element element) {
-          try {
-            TypeElement typeElement = MoreElements.asType(element);
-            switch (typeElement.getNestingKind()) {
-              case TOP_LEVEL:
-                return typeElement.getQualifiedName().toString().replace('.', '/');
-              case MEMBER:
-                return getInternalName(typeElement.getEnclosingElement())
-                    + "$"
-                    + typeElement.getSimpleName();
-              default:
-                throw new IllegalArgumentException("Unsupported nesting kind.");
-            }
-          } catch (IllegalArgumentException e) {
-            // Not a TypeElement, try something else...
-          }
-
-          if (element instanceof QualifiedNameable) {
-            QualifiedNameable qualifiedNameElement = (QualifiedNameable) element;
-            return qualifiedNameElement.getQualifiedName().toString().replace('.', '/');
-          }
-
-          return element.getSimpleName().toString();
-        }
-      };
-
-  /**
    * Invokes {@link Elements#getTypeElement(CharSequence)}, throwing {@link TypeNotPresentException}
    * if it is not accessible in the current compilation.
    */
@@ -424,14 +253,6 @@
     return elements.getElementValuesWithDefaults(a);
   }
 
-  /** Returns a map of annotation values keyed by attribute name. */
-  public Map<String, ? extends AnnotationValue> getElementValuesWithDefaultsByName(
-      AnnotationMirror a) {
-    ImmutableMap.Builder<String, AnnotationValue> builder = ImmutableMap.builder();
-    getElementValuesWithDefaults(a).forEach((k, v) -> builder.put(k.getSimpleName().toString(), v));
-    return builder.build();
-  }
-
   @Override
   public String getDocComment(Element e) {
     return elements.getDocComment(e);
diff --git a/java/dagger/internal/codegen/langmodel/DaggerTypes.java b/java/dagger/internal/codegen/langmodel/DaggerTypes.java
index fb291db..e588fbd 100644
--- a/java/dagger/internal/codegen/langmodel/DaggerTypes.java
+++ b/java/dagger/internal/codegen/langmodel/DaggerTypes.java
@@ -83,7 +83,7 @@
    * @throws IllegalArgumentException if {@code type} is not a declared type or has zero or more
    *     than one type arguments.
    */
-  public static TypeMirror unwrapType(TypeMirror type) {
+  public TypeMirror unwrapType(TypeMirror type) {
     TypeMirror unwrapped = unwrapTypeOrDefault(type, null);
     checkArgument(unwrapped != null, "%s is a raw type", type);
     return unwrapped;
@@ -101,7 +101,7 @@
     return unwrapTypeOrDefault(type, elements.getTypeElement(Object.class).asType());
   }
 
-  private static TypeMirror unwrapTypeOrDefault(TypeMirror type, TypeMirror defaultType) {
+  private TypeMirror unwrapTypeOrDefault(TypeMirror type, TypeMirror defaultType) {
     DeclaredType declaredType = MoreTypes.asDeclared(type);
     TypeElement typeElement = MoreElements.asType(declaredType.asElement());
     checkArgument(
diff --git a/java/dagger/internal/codegen/package-info.java b/java/dagger/internal/codegen/package-info.java
index 4c478d6..c8cc404 100644
--- a/java/dagger/internal/codegen/package-info.java
+++ b/java/dagger/internal/codegen/package-info.java
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-/** Apply {@link CheckReturnValue} by default to every method in this package. */
 @CheckReturnValue
 package dagger.internal.codegen;
 
diff --git a/java/dagger/internal/codegen/serialization/BUILD b/java/dagger/internal/codegen/serialization/BUILD
new file mode 100644
index 0000000..2bc02b4
--- /dev/null
+++ b/java/dagger/internal/codegen/serialization/BUILD
@@ -0,0 +1,41 @@
+# Copyright (C) 2019 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.
+
+# Description:
+#    Serialized forms of types used in the Dagger processor.
+
+package(default_visibility = ["//:src"])
+
+proto_library(
+    name = "serialization_proto",
+    srcs = ["serialization.proto"],
+    visibility = ["//visibility:private"],
+)
+
+java_proto_library(
+    name = "serialization_java_proto",
+    visibility = ["//visibility:private"],
+    deps = [":serialization_proto"],
+)
+
+java_library(
+    name = "serialization",
+    srcs = glob(["*.java"]),
+    exports = [":serialization_java_proto"],
+    deps = [
+        "@google_bazel_common//third_party/java/guava",
+        "@google_bazel_common//third_party/java/javapoet",
+        "@google_bazel_common//third_party/java/protobuf",
+    ],
+)
diff --git a/java/dagger/internal/codegen/serialization/ProtoSerialization.java b/java/dagger/internal/codegen/serialization/ProtoSerialization.java
new file mode 100644
index 0000000..1449e9d
--- /dev/null
+++ b/java/dagger/internal/codegen/serialization/ProtoSerialization.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 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.serialization;
+
+import static com.google.common.io.BaseEncoding.base64;
+
+import com.google.common.io.BaseEncoding;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Message;
+import com.squareup.javapoet.CodeBlock;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.AnnotationValueVisitor;
+import javax.lang.model.util.SimpleAnnotationValueVisitor8;
+
+/**
+ * Serializes and deserializes {@link Message}s using {@link BaseEncoding#base64()} for use in
+ * annotation values.
+ */
+public final class ProtoSerialization {
+  /** Returns a {@link CodeBlock} of {@code message} serialized as a String. */
+  public static CodeBlock toAnnotationValue(Message message) {
+    return CodeBlock.of("$S", base64().encode(message.toByteArray()));
+  }
+
+  /**
+   * Returns a {@link Message T} from the deserialized the String {@code value}.
+   *
+   * @throws IllegalArgumentException if {@code value} represents an {@link AnnotationValue} who's
+   *     type is not {@link String}
+   */
+  public static <T extends Message> T fromAnnotationValue(
+      AnnotationValue value, T defaultInstance) {
+    byte[] bytes = base64().decode(value.accept(STRING_VALUE, null));
+    Message message;
+    try {
+      message = defaultInstance.getParserForType().parseFrom(bytes);
+    } catch (InvalidProtocolBufferException e) {
+      throw new InconsistentSerializedProtoException(e);
+    }
+    @SuppressWarnings("unchecked") // guaranteed by proto API
+    T t = (T) message;
+    return t;
+  }
+
+  private static final AnnotationValueVisitor<String, Void> STRING_VALUE =
+      new SimpleAnnotationValueVisitor8<String, Void>() {
+        @Override
+        public String visitString(String s, Void ignored) {
+          return s;
+        }
+
+        @Override
+        protected String defaultAction(Object o, Void ignored) {
+          throw new IllegalArgumentException(o + " is not a String");
+        }
+      };
+
+  /**
+   * An exception thrown when the proto that's serialized in a compiled subcomponent implementation
+   * is from a different version than the current compiler's.
+   */
+  public static final class InconsistentSerializedProtoException extends RuntimeException {
+    InconsistentSerializedProtoException(Throwable cause) {
+      super(cause);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/serialization/serialization.proto b/java/dagger/internal/codegen/serialization/serialization.proto
new file mode 100644
index 0000000..e6c9577
--- /dev/null
+++ b/java/dagger/internal/codegen/serialization/serialization.proto
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Serialized forms of types used in the Dagger processor. The wire format of
+// these types is not guaranteed to remain compatible over time; serialization
+// is only expected to function correctly within an individual version of the
+// Dagger processor.
+
+syntax = "proto3";
+
+package dagger.internal.codegen.serialization;
+option java_package = "dagger.internal.codegen.serialization";
+option java_multiple_files = true;
+
+// TODO(ronshapiro): consider exposing some of these in
+// dagger.model.serialization
+
+// Serialized form of `dagger.internal.codegen.BindingRequest`
+message BindingRequestProto {
+  KeyProto key = 1;
+  RequestKindWrapper.RequestKind request_kind = 2;
+  FrameworkTypeWrapper.FrameworkType framework_type = 3;
+}
+
+message RequestKindWrapper {
+  // Serialized form of `dagger.model.RequestKind`
+  enum RequestKind {
+    UNKNOWN = 0;
+    INSTANCE = 1;
+    PROVIDER = 2;
+    LAZY = 3;
+    PROVIDER_OF_LAZY = 4;
+    MEMBERS_INJECTION = 5;
+    PRODUCER = 6;
+    PRODUCED = 7;
+    FUTURE = 8;
+  }
+}
+
+message FrameworkTypeWrapper {
+  // Serialized form of `dagger.internal.codegen.FrameworkType`
+  enum FrameworkType {
+    UNKNOWN = 0;
+    PROVIDER = 1;
+    PRODUCER_NODE = 2;
+  }
+}
+
+// Serialized form of `dagger.model.Key`
+message KeyProto {
+  TypeProto type = 1;
+  AnnotationProto qualifier = 2;
+  MultibindingContributionIdentifier multibinding_contribution_identifier =
+      3;
+
+  // Serialized form of `dagger.model.Key.MultibindingContributionIdentifier`
+  message MultibindingContributionIdentifier {
+    string module = 1;
+    string binding_element = 2;
+  }
+}
+
+// Serialized form of `javax.lang.model.type.TypeMirror`
+message TypeProto {
+  PrimitiveKind primitive_kind = 1;
+
+  // The qualified name of the type. Absent if this is an inner type.
+  string qualified_name = 2;
+
+  // The enclosing type if this is an inner type, otherwise absent.
+  TypeProto enclosing_type = 3;
+
+  // Simple name of the type if this is an inner type, otherwise absent.
+  string simple_name = 4;
+
+  repeated TypeProto type_arguments = 5;
+
+  message Wildcard {
+    TypeProto extends_bound = 1;
+    TypeProto super_bound = 2;
+  }
+  Wildcard wildcard = 6;
+
+  int32 array_dimensions = 7;
+
+  // Kinds of primitive types
+  enum PrimitiveKind {
+    UNKNOWN = 0;
+    BOOLEAN = 1;
+    BYTE = 2;
+    SHORT = 3;
+    CHAR = 4;
+    INT = 5;
+    FLOAT = 6;
+    LONG = 7;
+    DOUBLE = 8;
+  }
+}
+
+// Serialized form of `javax.lang.model.element.AnnotationMirror`
+message AnnotationProto {
+  TypeProto annotation_type = 1;
+  map<string, AnnotationValueProto> values = 2;
+}
+
+// Serialized form of `javax.lang.model.element.AnnotationValue`
+message AnnotationValueProto {
+  Kind kind = 1;
+  bool boolean_value = 2;
+  int32 int_value = 3;
+  int64 long_value = 4;
+  float float_value = 5;
+  double double_value = 6;
+  string string_value = 7;
+  TypeProto class_literal = 8;
+  TypeProto enum_type = 9;
+  string enum_name = 10;
+  AnnotationProto nested_annotation = 11;
+
+  repeated AnnotationValueProto array_values = 12;
+
+  // The type of annotation value
+  enum Kind {
+    UNKNOWN = 0;
+    BOOLEAN = 1;
+    BYTE = 2;
+    SHORT = 3;
+    CHAR = 4;
+    INT = 5;
+    FLOAT = 6;
+    LONG = 7;
+    DOUBLE = 8;
+    STRING = 9;
+    CLASS_LITERAL = 10;
+    ENUM = 11;
+    ANNOTATION = 12;
+    ARRAY = 13;
+  }
+}
+
+// Serialized form of `dagger.internal.codegen.ComponentRequirement`
+message ComponentRequirementProto {
+  oneof requirement {
+    TypeProto dependency = 1;
+    TypeProto module = 2;
+    BoundInstanceRequirement bound_instance = 3;
+  }
+
+  message BoundInstanceRequirement {
+    KeyProto key = 1;
+    bool nullable = 2;
+    string variable_name = 3;
+  }
+}
diff --git a/java/dagger/internal/codegen/validation/AnyBindingMethodValidator.java b/java/dagger/internal/codegen/validation/AnyBindingMethodValidator.java
deleted file mode 100644
index 140afd2..0000000
--- a/java/dagger/internal/codegen/validation/AnyBindingMethodValidator.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
-import static java.util.stream.Collectors.joining;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.base.ClearableCache;
-import java.lang.annotation.Annotation;
-import java.util.HashMap;
-import java.util.Map;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.lang.model.element.ExecutableElement;
-
-/** Validates any binding method. */
-@Singleton
-public final class AnyBindingMethodValidator implements ClearableCache {
-  private final ImmutableMap<Class<? extends Annotation>, BindingMethodValidator> validators;
-  private final Map<ExecutableElement, ValidationReport<ExecutableElement>> reports =
-      new HashMap<>();
-
-  @Inject
-  AnyBindingMethodValidator(
-      ImmutableMap<Class<? extends Annotation>, BindingMethodValidator> validators) {
-    this.validators = validators;
-  }
-
-  @Override
-  public void clearCache() {
-    reports.clear();
-  }
-
-  /** Returns the binding method annotations considered by this validator. */
-  ImmutableSet<Class<? extends Annotation>> methodAnnotations() {
-    return validators.keySet();
-  }
-
-  /**
-   * Returns {@code true} if {@code method} is annotated with at least one of {@link
-   * #methodAnnotations()}.
-   */
-  boolean isBindingMethod(ExecutableElement method) {
-    return isAnyAnnotationPresent(method, methodAnnotations());
-  }
-
-  /**
-   * Returns a validation report for a method.
-   *
-   * <ul>
-   *   <li>Reports an error if {@code method} is annotated with more than one {@linkplain
-   *       #methodAnnotations() binding method annotation}.
-   *   <li>Validates {@code method} with the {@link BindingMethodValidator} for the single
-   *       {@linkplain #methodAnnotations() binding method annotation}.
-   * </ul>
-   *
-   * @throws IllegalArgumentException if {@code method} is not annotated by any {@linkplain
-   *     #methodAnnotations() binding method annotation}
-   */
-  ValidationReport<ExecutableElement> validate(ExecutableElement method) {
-    return reentrantComputeIfAbsent(reports, method, this::validateUncached);
-  }
-
-  /**
-   * Returns {@code true} if {@code method} was already {@linkplain #validate(ExecutableElement)
-   * validated}.
-   */
-  boolean wasAlreadyValidated(ExecutableElement method) {
-    return reports.containsKey(method);
-  }
-
-  private ValidationReport<ExecutableElement> validateUncached(ExecutableElement method) {
-    ValidationReport.Builder<ExecutableElement> report = ValidationReport.about(method);
-    ImmutableSet<? extends Class<? extends Annotation>> bindingMethodAnnotations =
-        methodAnnotations()
-            .stream()
-            .filter(annotation -> isAnnotationPresent(method, annotation))
-            .collect(toImmutableSet());
-    switch (bindingMethodAnnotations.size()) {
-      case 0:
-        throw new IllegalArgumentException(
-            String.format("%s has no binding method annotation", method));
-
-      case 1:
-        report.addSubreport(
-            validators.get(getOnlyElement(bindingMethodAnnotations)).validate(method));
-        break;
-
-      default:
-        report.addError(
-            String.format(
-                "%s is annotated with more than one of (%s)",
-                method.getSimpleName(),
-                methodAnnotations().stream().map(Class::getCanonicalName).collect(joining(", "))),
-            method);
-        break;
-    }
-    return report.build();
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BUILD b/java/dagger/internal/codegen/validation/BUILD
deleted file mode 100644
index 602157b..0000000
--- a/java/dagger/internal/codegen/validation/BUILD
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Code related to validating the user-written Dagger code
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "validation",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    tags = ["maven:merged"],
-    deps = [
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:cache",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
-        "//java/dagger/internal/guava:graph",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/checker_framework_annotations",
-        "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
diff --git a/java/dagger/internal/codegen/validation/BindingElementValidator.java b/java/dagger/internal/codegen/validation/BindingElementValidator.java
deleted file mode 100644
index 4557745..0000000
--- a/java/dagger/internal/codegen/validation/BindingElementValidator.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Verify.verifyNotNull;
-import static dagger.internal.codegen.base.Scopes.scopesOf;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedFactoryType;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedInjectionType;
-import static dagger.internal.codegen.binding.MapKeys.getMapKeys;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
-import static javax.lang.model.type.TypeKind.ARRAY;
-import static javax.lang.model.type.TypeKind.DECLARED;
-import static javax.lang.model.type.TypeKind.TYPEVAR;
-import static javax.lang.model.type.TypeKind.VOID;
-
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableSet;
-import com.google.errorprone.annotations.FormatMethod;
-import dagger.MapKey;
-import dagger.Provides;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.FrameworkTypes;
-import dagger.internal.codegen.base.MultibindingAnnotations;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.model.Key;
-import dagger.model.Scope;
-import dagger.multibindings.ElementsIntoSet;
-import dagger.multibindings.IntoMap;
-import dagger.producers.Produces;
-import java.lang.annotation.Annotation;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.inject.Qualifier;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-
-/** A validator for elements that represent binding declarations. */
-public abstract class BindingElementValidator<E extends Element> {
-  private final Class<? extends Annotation> bindingAnnotation;
-  private final AllowsMultibindings allowsMultibindings;
-  private final AllowsScoping allowsScoping;
-  private final Map<E, ValidationReport<E>> cache = new HashMap<>();
-  private final InjectionAnnotations injectionAnnotations;
-
-  /**
-   * Creates a validator object.
-   *
-   * @param bindingAnnotation the annotation on an element that identifies it as a binding element
-   */
-  protected BindingElementValidator(
-      Class<? extends Annotation> bindingAnnotation,
-      AllowsMultibindings allowsMultibindings,
-      AllowsScoping allowsScoping,
-      InjectionAnnotations injectionAnnotations) {
-    this.bindingAnnotation = bindingAnnotation;
-    this.allowsMultibindings = allowsMultibindings;
-    this.allowsScoping = allowsScoping;
-    this.injectionAnnotations = injectionAnnotations;
-  }
-
-  /** Returns a {@link ValidationReport} for {@code element}. */
-  final ValidationReport<E> validate(E element) {
-    return reentrantComputeIfAbsent(cache, element, this::validateUncached);
-  }
-
-  private ValidationReport<E> validateUncached(E element) {
-    return elementValidator(element).validate();
-  }
-
-  /**
-   * Returns an error message of the form "&lt;{@link #bindingElements()}&gt; <i>rule</i>", where
-   * <i>rule</i> comes from calling {@link String#format(String, Object...)} on {@code ruleFormat}
-   * and the other arguments.
-   */
-  @FormatMethod
-  protected final String bindingElements(String ruleFormat, Object... args) {
-    return new Formatter().format("%s ", bindingElements()).format(ruleFormat, args).toString();
-  }
-
-  /**
-   * The kind of elements that this validator validates. Should be plural. Used for error reporting.
-   */
-  protected abstract String bindingElements();
-
-  /** The verb describing the {@link ElementValidator#bindingElementType()} in error messages. */
-  // TODO(ronshapiro,dpb): improve the name of this method and it's documentation.
-  protected abstract String bindingElementTypeVerb();
-
-  /** The error message when a binding element has a bad type. */
-  protected String badTypeMessage() {
-    return bindingElements(
-        "must %s a primitive, an array, a type variable, or a declared type",
-        bindingElementTypeVerb());
-  }
-
-  /**
-   * The error message when a the type for a binding element with {@link
-   * ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} is a not set type.
-   */
-  protected String elementsIntoSetNotASetMessage() {
-    return bindingElements(
-        "annotated with @ElementsIntoSet must %s a Set", bindingElementTypeVerb());
-  }
-
-  /**
-   * The error message when a the type for a binding element with {@link
-   * ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} is a raw set.
-   */
-  protected String elementsIntoSetRawSetMessage() {
-    return bindingElements(
-        "annotated with @ElementsIntoSet cannot %s a raw Set", bindingElementTypeVerb());
-  }
-
-  /*** Returns an {@link ElementValidator} for validating the given {@code element}. */
-  protected abstract ElementValidator elementValidator(E element);
-
-  /** Validator for a single binding element. */
-  protected abstract class ElementValidator {
-    protected final E element;
-    protected final ValidationReport.Builder<E> report;
-
-    protected ElementValidator(E element) {
-      this.element = element;
-      this.report = ValidationReport.about(element);
-    }
-
-    /** Checks the element for validity. */
-    private ValidationReport<E> validate() {
-      checkType();
-      checkQualifiers();
-      checkMapKeys();
-      checkMultibindings();
-      checkScopes();
-      checkAdditionalProperties();
-      return report.build();
-    }
-
-    /** Check any additional properties of the element. Does nothing by default. */
-    protected void checkAdditionalProperties() {}
-
-    /**
-     * The type declared by this binding element. This may differ from a binding's {@link
-     * Key#type()}, for example in multibindings. An {@link Optional#empty()} return value indicates
-     * that the contributed type is ambiguous or missing, i.e. a {@code @BindsInstance} method with
-     * zero or many parameters.
-     */
-    // TODO(dpb): should this be an ImmutableList<TypeMirror>, with this class checking the size?
-    protected abstract Optional<TypeMirror> bindingElementType();
-
-    /**
-     * Adds an error if the {@link #bindingElementType() binding element type} is not appropriate.
-     *
-     * <p>Adds an error if the type is not a primitive, array, declared type, or type variable.
-     *
-     * <p>If the binding is not a multibinding contribution, adds an error if the type is a
-     * framework type.
-     *
-     * <p>If the element has {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES}, adds an
-     * error if the type is not a {@code Set<T>} for some {@code T}
-     */
-    protected void checkType() {
-      switch (ContributionType.fromBindingElement(element)) {
-        case UNIQUE:
-          /* Validate that a unique binding is not attempting to bind a framework type. This
-           * validation is only appropriate for unique bindings because multibindings may collect
-           * framework types.  E.g. Set<Provider<Foo>> is perfectly reasonable. */
-          checkFrameworkType();
-          // fall through
-
-        case SET:
-        case MAP:
-          bindingElementType().ifPresent(type -> checkKeyType(type));
-          break;
-
-        case SET_VALUES:
-          checkSetValuesType();
-      }
-    }
-
-    /**
-     * Adds an error if {@code keyType} is not a primitive, declared type, array, or type variable.
-     */
-    protected void checkKeyType(TypeMirror keyType) {
-      TypeKind kind = keyType.getKind();
-      if (kind.equals(VOID)) {
-        report.addError(bindingElements("must %s a value (not void)", bindingElementTypeVerb()));
-      } else if (kind == DECLARED) {
-        checkNotAssistedInject(keyType);
-      } else if (!(kind.isPrimitive() || kind.equals(ARRAY) || kind.equals(TYPEVAR))) {
-        report.addError(badTypeMessage());
-      }
-    }
-
-    /** Adds errors for a method return type. */
-    private void checkNotAssistedInject(TypeMirror keyType) {
-      checkState(keyType.getKind() == TypeKind.DECLARED);
-      TypeElement keyElement = asTypeElement(keyType);
-      if (isAssistedInjectionType(keyElement)) {
-        report.addError("Dagger does not support providing @AssistedInject types.", keyElement);
-      }
-      if (isAssistedFactoryType(keyElement)) {
-        report.addError("Dagger does not support providing @AssistedFactory types.", keyElement);
-      }
-    }
-
-    /**
-     * Adds an error if the type for an element with {@link ElementsIntoSet @ElementsIntoSet} or
-     * {@code SET_VALUES} is not a a {@code Set<T>} for a reasonable {@code T}.
-     */
-    // TODO(gak): should we allow "covariant return" for set values?
-    protected void checkSetValuesType() {
-      bindingElementType().ifPresent(keyType -> checkSetValuesType(keyType));
-    }
-
-    /** Adds an error if {@code type} is not a {@code Set<T>} for a reasonable {@code T}. */
-    protected final void checkSetValuesType(TypeMirror type) {
-      if (!SetType.isSet(type)) {
-        report.addError(elementsIntoSetNotASetMessage());
-      } else {
-        SetType setType = SetType.from(type);
-        if (setType.isRawType()) {
-          report.addError(elementsIntoSetRawSetMessage());
-        } else {
-          checkKeyType(setType.elementType());
-        }
-      }
-    }
-
-    /**
-     * Adds an error if the element has more than one {@linkplain Qualifier qualifier} annotation.
-     */
-    private void checkQualifiers() {
-      ImmutableCollection<? extends AnnotationMirror> qualifiers =
-          injectionAnnotations.getQualifiers(element);
-      if (qualifiers.size() > 1) {
-        for (AnnotationMirror qualifier : qualifiers) {
-          report.addError(
-              bindingElements("may not use more than one @Qualifier"),
-              element,
-              qualifier);
-        }
-      }
-    }
-
-    /**
-     * Adds an error if an {@link IntoMap @IntoMap} element doesn't have exactly one {@link
-     * MapKey @MapKey} annotation, or if an element that is {@link IntoMap @IntoMap} has any.
-     */
-    private void checkMapKeys() {
-      if (!allowsMultibindings.allowsMultibindings()) {
-        return;
-      }
-      ImmutableSet<? extends AnnotationMirror> mapKeys = getMapKeys(element);
-      if (ContributionType.fromBindingElement(element).equals(ContributionType.MAP)) {
-        switch (mapKeys.size()) {
-          case 0:
-            report.addError(bindingElements("of type map must declare a map key"));
-            break;
-          case 1:
-            break;
-          default:
-            report.addError(bindingElements("may not have more than one map key"));
-            break;
-        }
-      } else if (!mapKeys.isEmpty()) {
-        report.addError(bindingElements("of non map type cannot declare a map key"));
-      }
-    }
-
-    /**
-     * Adds errors if:
-     *
-     * <ul>
-     *   <li>the element doesn't allow {@linkplain MultibindingAnnotations multibinding annotations}
-     *       and has any
-     *   <li>the element does allow them but has more than one
-     *   <li>the element has a multibinding annotation and its {@link Provides} or {@link Produces}
-     *       annotation has a {@code type} parameter.
-     * </ul>
-     */
-    private void checkMultibindings() {
-      ImmutableSet<AnnotationMirror> multibindingAnnotations =
-          MultibindingAnnotations.forElement(element);
-
-      switch (allowsMultibindings) {
-        case NO_MULTIBINDINGS:
-          for (AnnotationMirror annotation : multibindingAnnotations) {
-            report.addError(
-                bindingElements("cannot have multibinding annotations"),
-                element,
-                annotation);
-          }
-          break;
-
-        case ALLOWS_MULTIBINDINGS:
-          if (multibindingAnnotations.size() > 1) {
-            for (AnnotationMirror annotation : multibindingAnnotations) {
-              report.addError(
-                  bindingElements("cannot have more than one multibinding annotation"),
-                  element,
-                  annotation);
-            }
-          }
-          break;
-      }
-
-      // TODO(ronshapiro): move this into ProvidesMethodValidator
-      if (bindingAnnotation.equals(Provides.class)) {
-        AnnotationMirror bindingAnnotationMirror =
-            getAnnotationMirror(element, bindingAnnotation).get();
-        boolean usesProvidesType = false;
-        for (ExecutableElement member : bindingAnnotationMirror.getElementValues().keySet()) {
-          usesProvidesType |= member.getSimpleName().contentEquals("type");
-        }
-        if (usesProvidesType && !multibindingAnnotations.isEmpty()) {
-          report.addError(
-              "@Provides.type cannot be used with multibinding annotations", element);
-        }
-      }
-    }
-
-    /**
-     * Adds an error if the element has a scope but doesn't allow scoping, or if it has more than
-     * one {@linkplain Scope scope} annotation.
-     */
-    private void checkScopes() {
-      ImmutableSet<Scope> scopes = scopesOf(element);
-      String error = null;
-      switch (allowsScoping) {
-        case ALLOWS_SCOPING:
-          if (scopes.size() <= 1) {
-            return;
-          }
-          error = bindingElements("cannot use more than one @Scope");
-          break;
-        case NO_SCOPING:
-          error = bindingElements("cannot be scoped");
-          break;
-      }
-      verifyNotNull(error);
-      for (Scope scope : scopes) {
-        report.addError(error, element, scope.scopeAnnotation());
-      }
-    }
-
-    /**
-     * Adds an error if the {@link #bindingElementType() type} is a {@linkplain FrameworkTypes
-     * framework type}.
-     */
-    private void checkFrameworkType() {
-      if (bindingElementType().filter(FrameworkTypes::isFrameworkType).isPresent()) {
-        report.addError(bindingElements("must not %s framework types", bindingElementTypeVerb()));
-      }
-    }
-  }
-
-  /** Whether to check multibinding annotations. */
-  enum AllowsMultibindings {
-    /**
-     * This element disallows multibinding annotations, so don't bother checking for their validity.
-     * {@link MultibindingAnnotationsProcessingStep} will add errors if the element has any
-     * multibinding annotations.
-     */
-    NO_MULTIBINDINGS,
-
-    /** This element allows multibinding annotations, so validate them. */
-    ALLOWS_MULTIBINDINGS,
-    ;
-
-    private boolean allowsMultibindings() {
-      return this == ALLOWS_MULTIBINDINGS;
-    }
-  }
-
-  /** How to check scoping annotations. */
-  enum AllowsScoping {
-    /** This element disallows scoping, so check that no scope annotations are present. */
-    NO_SCOPING,
-
-    /** This element allows scoping, so validate that there's at most one scope annotation. */
-    ALLOWS_SCOPING,
-    ;
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindingGraphPlugins.java b/java/dagger/internal/codegen/validation/BindingGraphPlugins.java
deleted file mode 100644
index 16ef78f..0000000
--- a/java/dagger/internal/codegen/validation/BindingGraphPlugins.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.validation;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import dagger.internal.codegen.compileroption.ProcessingOptions;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.spi.BindingGraphPlugin;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-
-/** Initializes {@link BindingGraphPlugin}s. */
-public final class BindingGraphPlugins {
-  private final ImmutableSet<BindingGraphPlugin> plugins;
-  private final Filer filer;
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-  private final Map<String, String> processingOptions;
-
-  @Inject
-  BindingGraphPlugins(
-      @Validation ImmutableSet<BindingGraphPlugin> validationPlugins,
-      ImmutableSet<BindingGraphPlugin> externalPlugins,
-      Filer filer,
-      DaggerTypes types,
-      DaggerElements elements,
-      @ProcessingOptions Map<String, String> processingOptions) {
-    this.plugins = Sets.union(validationPlugins, externalPlugins).immutableCopy();
-    this.filer = filer;
-    this.types = types;
-    this.elements = elements;
-    this.processingOptions = processingOptions;
-  }
-
-  /** Returns {@link BindingGraphPlugin#supportedOptions()} from all the plugins. */
-  public ImmutableSet<String> allSupportedOptions() {
-    return plugins.stream()
-        .flatMap(plugin -> plugin.supportedOptions().stream())
-        .collect(toImmutableSet());
-  }
-
-  /** Initializes the plugins. */
-  // TODO(ronshapiro): Should we validate the uniqueness of plugin names?
-  public void initializePlugins() {
-    plugins.forEach(this::initializePlugin);
-  }
-
-  private void initializePlugin(BindingGraphPlugin plugin) {
-    plugin.initFiler(filer);
-    plugin.initTypes(types);
-    plugin.initElements(elements);
-    Set<String> supportedOptions = plugin.supportedOptions();
-    if (!supportedOptions.isEmpty()) {
-      plugin.initOptions(Maps.filterKeys(processingOptions, supportedOptions::contains));
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindingGraphValidator.java b/java/dagger/internal/codegen/validation/BindingGraphValidator.java
deleted file mode 100644
index 99e86e7..0000000
--- a/java/dagger/internal/codegen/validation/BindingGraphValidator.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.validation;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.compileroption.ValidationType;
-import dagger.internal.codegen.validation.DiagnosticReporterFactory.DiagnosticReporterImpl;
-import dagger.model.BindingGraph;
-import dagger.spi.BindingGraphPlugin;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.lang.model.element.TypeElement;
-
-/** Validates a {@link BindingGraph}. */
-@Singleton
-public final class BindingGraphValidator {
-  private final ImmutableSet<BindingGraphPlugin> validationPlugins;
-  private final ImmutableSet<BindingGraphPlugin> externalPlugins;
-  private final DiagnosticReporterFactory diagnosticReporterFactory;
-  private final CompilerOptions compilerOptions;
-
-  @Inject
-  BindingGraphValidator(
-      @Validation ImmutableSet<BindingGraphPlugin> validationPlugins,
-      ImmutableSet<BindingGraphPlugin> externalPlugins,
-      DiagnosticReporterFactory diagnosticReporterFactory,
-      CompilerOptions compilerOptions) {
-    this.validationPlugins = validationPlugins;
-    this.externalPlugins = externalPlugins;
-    this.diagnosticReporterFactory = checkNotNull(diagnosticReporterFactory);
-    this.compilerOptions = compilerOptions;
-  }
-
-  /** Returns {@code true} if validation or analysis is required on the full binding graph. */
-  public boolean shouldDoFullBindingGraphValidation(TypeElement component) {
-    return requiresFullBindingGraphValidation()
-        || compilerOptions.pluginsVisitFullBindingGraphs(component);
-  }
-
-  private boolean requiresFullBindingGraphValidation() {
-    return !compilerOptions.fullBindingGraphValidationType().equals(ValidationType.NONE);
-  }
-
-  /** Returns {@code true} if no errors are reported for {@code graph}. */
-  public boolean isValid(BindingGraph graph) {
-    return validate(graph) && visitPlugins(graph);
-  }
-
-  /** Returns {@code true} if validation plugins report no errors. */
-  private boolean validate(BindingGraph graph) {
-    if (graph.isFullBindingGraph() && !requiresFullBindingGraphValidation()) {
-      return true;
-    }
-
-    boolean errorsAsWarnings =
-        graph.isFullBindingGraph()
-        && compilerOptions.fullBindingGraphValidationType().equals(ValidationType.WARNING);
-
-    return runPlugins(validationPlugins, graph, errorsAsWarnings);
-  }
-
-  /** Returns {@code true} if external plugins report no errors. */
-  private boolean visitPlugins(BindingGraph graph) {
-    TypeElement component = graph.rootComponentNode().componentPath().currentComponent();
-    if (graph.isFullBindingGraph()
-        // TODO(b/135938915): Consider not visiting plugins if only
-        // fullBindingGraphValidation is enabled.
-        && !requiresFullBindingGraphValidation()
-        && !compilerOptions.pluginsVisitFullBindingGraphs(component)) {
-      return true;
-    }
-    return runPlugins(externalPlugins, graph, /*errorsAsWarnings=*/ false);
-  }
-
-  /** Returns {@code false} if any of the plugins reported an error. */
-  private boolean runPlugins(
-      ImmutableSet<BindingGraphPlugin> plugins, BindingGraph graph, boolean errorsAsWarnings) {
-    boolean isClean = true;
-    for (BindingGraphPlugin plugin : plugins) {
-      DiagnosticReporterImpl reporter =
-          diagnosticReporterFactory.reporter(graph, plugin, errorsAsWarnings);
-      plugin.visitGraph(graph, reporter);
-      if (reporter.reportedDiagnosticKinds().contains(ERROR)) {
-        isClean = false;
-      }
-    }
-    return isClean;
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindingMethodProcessingStep.java b/java/dagger/internal/codegen/validation/BindingMethodProcessingStep.java
deleted file mode 100644
index 10aec06..0000000
--- a/java/dagger/internal/codegen/validation/BindingMethodProcessingStep.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSet;
-import java.lang.annotation.Annotation;
-import java.util.Set;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-
-/** A step that validates all binding methods that were not validated while processing modules. */
-public final class BindingMethodProcessingStep
-    extends TypeCheckingProcessingStep<ExecutableElement> {
-
-  private final Messager messager;
-  private final AnyBindingMethodValidator anyBindingMethodValidator;
-
-  @Inject
-  BindingMethodProcessingStep(
-      Messager messager, AnyBindingMethodValidator anyBindingMethodValidator) {
-    super(MoreElements::asExecutable);
-    this.messager = messager;
-    this.anyBindingMethodValidator = anyBindingMethodValidator;
-  }
-
-  @Override
-  public Set<? extends Class<? extends Annotation>> annotations() {
-    return anyBindingMethodValidator.methodAnnotations();
-  }
-
-  @Override
-  protected void process(
-      ExecutableElement method, ImmutableSet<Class<? extends Annotation>> annotations) {
-    checkArgument(
-        anyBindingMethodValidator.isBindingMethod(method),
-        "%s is not annotated with any of %s",
-        method,
-        annotations());
-    if (!anyBindingMethodValidator.wasAlreadyValidated(method)) {
-      anyBindingMethodValidator.validate(method).printMessagesTo(messager);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindingMethodValidator.java b/java/dagger/internal/codegen/validation/BindingMethodValidator.java
deleted file mode 100644
index 81349b9..0000000
--- a/java/dagger/internal/codegen/validation/BindingMethodValidator.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static com.google.auto.common.MoreElements.asType;
-import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
-import static java.util.stream.Collectors.joining;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.errorprone.annotations.FormatMethod;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.lang.annotation.Annotation;
-import java.util.Optional;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeMirror;
-
-/** A validator for methods that represent binding declarations. */
-abstract class BindingMethodValidator extends BindingElementValidator<ExecutableElement> {
-
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final KotlinMetadataUtil metadataUtil;
-  private final DependencyRequestValidator dependencyRequestValidator;
-  private final Class<? extends Annotation> methodAnnotation;
-  private final ImmutableSet<? extends Class<? extends Annotation>> enclosingElementAnnotations;
-  private final Abstractness abstractness;
-  private final ExceptionSuperclass exceptionSuperclass;
-
-  /**
-   * Creates a validator object.
-   *
-   * @param methodAnnotation the annotation on a method that identifies it as a binding method
-   * @param enclosingElementAnnotation the method must be declared in a class or interface annotated
-   *     with this annotation
-   */
-  protected BindingMethodValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil metadataUtil,
-      DependencyRequestValidator dependencyRequestValidator,
-      Class<? extends Annotation> methodAnnotation,
-      Class<? extends Annotation> enclosingElementAnnotation,
-      Abstractness abstractness,
-      ExceptionSuperclass exceptionSuperclass,
-      AllowsMultibindings allowsMultibindings,
-      AllowsScoping allowsScoping,
-      InjectionAnnotations injectionAnnotations) {
-    this(
-        elements,
-        types,
-        metadataUtil,
-        methodAnnotation,
-        ImmutableSet.of(enclosingElementAnnotation),
-        dependencyRequestValidator,
-        abstractness,
-        exceptionSuperclass,
-        allowsMultibindings,
-        allowsScoping,
-        injectionAnnotations);
-  }
-
-  /**
-   * Creates a validator object.
-   *
-   * @param methodAnnotation the annotation on a method that identifies it as a binding method
-   * @param enclosingElementAnnotations the method must be declared in a class or interface
-   *     annotated with one of these annotations
-   */
-  protected BindingMethodValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil metadataUtil,
-      Class<? extends Annotation> methodAnnotation,
-      Iterable<? extends Class<? extends Annotation>> enclosingElementAnnotations,
-      DependencyRequestValidator dependencyRequestValidator,
-      Abstractness abstractness,
-      ExceptionSuperclass exceptionSuperclass,
-      AllowsMultibindings allowsMultibindings,
-      AllowsScoping allowsScoping,
-      InjectionAnnotations injectionAnnotations) {
-    super(methodAnnotation, allowsMultibindings, allowsScoping, injectionAnnotations);
-    this.elements = elements;
-    this.types = types;
-    this.metadataUtil = metadataUtil;
-    this.methodAnnotation = methodAnnotation;
-    this.enclosingElementAnnotations = ImmutableSet.copyOf(enclosingElementAnnotations);
-    this.dependencyRequestValidator = dependencyRequestValidator;
-    this.abstractness = abstractness;
-    this.exceptionSuperclass = exceptionSuperclass;
-  }
-
-  /** The annotation that identifies binding methods validated by this object. */
-  final Class<? extends Annotation> methodAnnotation() {
-    return methodAnnotation;
-  }
-
-  /**
-   * Returns an error message of the form "@<i>annotation</i> methods <i>rule</i>", where
-   * <i>rule</i> comes from calling {@link String#format(String, Object...)} on {@code ruleFormat}
-   * and the other arguments.
-   */
-  @FormatMethod
-  protected final String bindingMethods(String ruleFormat, Object... args) {
-    return bindingElements(ruleFormat, args);
-  }
-
-  @Override
-  protected final String bindingElements() {
-    return String.format("@%s methods", methodAnnotation.getSimpleName());
-  }
-
-  @Override
-  protected final String bindingElementTypeVerb() {
-    return "return";
-  }
-
-  /** Abstract validator for individual binding method elements. */
-  protected abstract class MethodValidator extends ElementValidator {
-    protected MethodValidator(ExecutableElement element) {
-      super(element);
-    }
-
-    @Override
-    protected final Optional<TypeMirror> bindingElementType() {
-      return Optional.of(element.getReturnType());
-    }
-
-    @Override
-    protected final void checkAdditionalProperties() {
-      checkEnclosingElement();
-      checkTypeParameters();
-      checkNotPrivate();
-      checkAbstractness();
-      checkThrows();
-      checkParameters();
-      checkAdditionalMethodProperties();
-    }
-
-    /** Checks additional properties of the binding method. */
-    protected void checkAdditionalMethodProperties() {}
-
-    /**
-     * Adds an error if the method is not declared in a class or interface annotated with one of the
-     * {@link #enclosingElementAnnotations}.
-     */
-    private void checkEnclosingElement() {
-      TypeElement enclosingElement = asType(element.getEnclosingElement());
-      if (metadataUtil.isCompanionObjectClass(enclosingElement)) {
-        // Binding method is in companion object, use companion object's enclosing class instead.
-        enclosingElement = asType(enclosingElement.getEnclosingElement());
-      }
-      if (!isAnyAnnotationPresent(enclosingElement, enclosingElementAnnotations)) {
-        report.addError(
-            bindingMethods(
-                "can only be present within a @%s",
-                enclosingElementAnnotations.stream()
-                    .map(Class::getSimpleName)
-                    .collect(joining(" or @"))));
-      }
-    }
-
-    /** Adds an error if the method is generic. */
-    private void checkTypeParameters() {
-      if (!element.getTypeParameters().isEmpty()) {
-        report.addError(bindingMethods("may not have type parameters"));
-      }
-    }
-
-    /** Adds an error if the method is private. */
-    private void checkNotPrivate() {
-      if (element.getModifiers().contains(PRIVATE)) {
-        report.addError(bindingMethods("cannot be private"));
-      }
-    }
-
-    /** Adds an error if the method is abstract but must not be, or is not and must be. */
-    private void checkAbstractness() {
-      boolean isAbstract = element.getModifiers().contains(ABSTRACT);
-      switch (abstractness) {
-        case MUST_BE_ABSTRACT:
-          if (!isAbstract) {
-            report.addError(bindingMethods("must be abstract"));
-          }
-          break;
-
-        case MUST_BE_CONCRETE:
-          if (isAbstract) {
-            report.addError(bindingMethods("cannot be abstract"));
-          }
-      }
-    }
-
-    /**
-     * Adds an error if the method declares throws anything but an {@link Error} or an appropriate
-     * subtype of {@link Exception}.
-     */
-    private void checkThrows() {
-      exceptionSuperclass.checkThrows(BindingMethodValidator.this, element, report);
-    }
-
-    /** Adds errors for the method parameters. */
-    protected void checkParameters() {
-      for (VariableElement parameter : element.getParameters()) {
-        checkParameter(parameter);
-      }
-    }
-
-    /**
-     * Adds errors for a method parameter. This implementation reports an error if the parameter has
-     * more than one qualifier.
-     */
-    protected void checkParameter(VariableElement parameter) {
-      dependencyRequestValidator.validateDependencyRequest(report, parameter, parameter.asType());
-    }
-  }
-
-  /** An abstract/concrete restriction on methods. */
-  protected enum Abstractness {
-    MUST_BE_ABSTRACT,
-    MUST_BE_CONCRETE
-  }
-
-  /**
-   * The exception class that all {@code throws}-declared throwables must extend, other than {@link
-   * Error}.
-   */
-  protected enum ExceptionSuperclass {
-    /** Methods may not declare any throwable types. */
-    NO_EXCEPTIONS {
-      @Override
-      protected String errorMessage(BindingMethodValidator validator) {
-        return validator.bindingMethods("may not throw");
-      }
-
-      @Override
-      protected void checkThrows(
-          BindingMethodValidator validator,
-          ExecutableElement element,
-          ValidationReport.Builder<ExecutableElement> report) {
-        if (!element.getThrownTypes().isEmpty()) {
-          report.addError(validator.bindingMethods("may not throw"));
-          return;
-        }
-      }
-    },
-
-    /** Methods may throw checked or unchecked exceptions or errors. */
-    EXCEPTION(Exception.class) {
-      @Override
-      protected String errorMessage(BindingMethodValidator validator) {
-        return validator.bindingMethods(
-            "may only throw unchecked exceptions or exceptions subclassing Exception");
-      }
-    },
-
-    /** Methods may throw unchecked exceptions or errors. */
-    RUNTIME_EXCEPTION(RuntimeException.class) {
-      @Override
-      protected String errorMessage(BindingMethodValidator validator) {
-        return validator.bindingMethods("may only throw unchecked exceptions");
-      }
-    },
-    ;
-
-    private final Class<? extends Exception> superclass;
-
-    ExceptionSuperclass() {
-      this(null);
-    }
-
-    ExceptionSuperclass(Class<? extends Exception> superclass) {
-      this.superclass = superclass;
-    }
-
-    /**
-     * Adds an error if the method declares throws anything but an {@link Error} or an appropriate
-     * subtype of {@link Exception}.
-     *
-     * <p>This method is overridden in {@link #NO_EXCEPTIONS}.
-     */
-    protected void checkThrows(
-        BindingMethodValidator validator,
-        ExecutableElement element,
-        ValidationReport.Builder<ExecutableElement> report) {
-      TypeMirror exceptionSupertype = validator.elements.getTypeElement(superclass).asType();
-      TypeMirror errorType = validator.elements.getTypeElement(Error.class).asType();
-      for (TypeMirror thrownType : element.getThrownTypes()) {
-        if (!validator.types.isSubtype(thrownType, exceptionSupertype)
-            && !validator.types.isSubtype(thrownType, errorType)) {
-          report.addError(errorMessage(validator));
-          break;
-        }
-      }
-    }
-
-    protected abstract String errorMessage(BindingMethodValidator validator);
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindingMethodValidatorsModule.java b/java/dagger/internal/codegen/validation/BindingMethodValidatorsModule.java
deleted file mode 100644
index 08afbc8..0000000
--- a/java/dagger/internal/codegen/validation/BindingMethodValidatorsModule.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.validation;
-
-import static com.google.common.collect.Maps.uniqueIndex;
-
-import com.google.common.collect.ImmutableMap;
-import dagger.Binds;
-import dagger.Module;
-import dagger.Provides;
-import dagger.multibindings.IntoSet;
-import java.lang.annotation.Annotation;
-import java.util.Set;
-
-/**
- * Binds each {@link BindingMethodValidator} into a map, keyed by {@link
- * BindingMethodValidator#methodAnnotation()}.
- */
-@Module
-public interface BindingMethodValidatorsModule {
-  @Provides
-  static ImmutableMap<Class<? extends Annotation>, BindingMethodValidator> indexValidators(
-      Set<BindingMethodValidator> validators) {
-    return uniqueIndex(validators, BindingMethodValidator::methodAnnotation);
-  }
-
-  @Binds
-  @IntoSet
-  BindingMethodValidator provides(ProvidesMethodValidator validator);
-
-  @Binds
-  @IntoSet
-  BindingMethodValidator produces(ProducesMethodValidator validator);
-
-  @Binds
-  @IntoSet
-  BindingMethodValidator binds(BindsMethodValidator validator);
-
-  @Binds
-  @IntoSet
-  BindingMethodValidator multibinds(MultibindsMethodValidator validator);
-
-  @Binds
-  @IntoSet
-  BindingMethodValidator bindsOptionalOf(BindsOptionalOfMethodValidator validator);
-}
diff --git a/java/dagger/internal/codegen/validation/BindsInstanceElementValidator.java b/java/dagger/internal/codegen/validation/BindsInstanceElementValidator.java
deleted file mode 100644
index 283af7d..0000000
--- a/java/dagger/internal/codegen/validation/BindsInstanceElementValidator.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import dagger.BindsInstance;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import javax.lang.model.element.Element;
-
-abstract class BindsInstanceElementValidator<E extends Element> extends BindingElementValidator<E> {
-  BindsInstanceElementValidator(InjectionAnnotations injectionAnnotations) {
-    super(
-        BindsInstance.class,
-        AllowsMultibindings.NO_MULTIBINDINGS,
-        AllowsScoping.NO_SCOPING,
-        injectionAnnotations);
-  }
-
-  @Override
-  protected final String bindingElements() {
-    // Even though @BindsInstance may be placed on methods, the subject of errors is the
-    // parameter
-    return "@BindsInstance parameters";
-  }
-
-  @Override
-  protected final String bindingElementTypeVerb() {
-    return "be";
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindsInstanceMethodValidator.java b/java/dagger/internal/codegen/validation/BindsInstanceMethodValidator.java
deleted file mode 100644
index 6d144bd..0000000
--- a/java/dagger/internal/codegen/validation/BindsInstanceMethodValidator.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.ComponentAnnotation.anyComponentAnnotation;
-import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-
-import com.google.auto.common.MoreElements;
-import dagger.internal.codegen.base.ModuleAnnotation;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import java.util.List;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeMirror;
-
-final class BindsInstanceMethodValidator extends BindsInstanceElementValidator<ExecutableElement> {
-  @Inject
-  BindsInstanceMethodValidator(InjectionAnnotations injectionAnnotations) {
-    super(injectionAnnotations);
-  }
-
-  @Override
-  protected ElementValidator elementValidator(ExecutableElement element) {
-    return new Validator(element);
-  }
-
-  private class Validator extends ElementValidator {
-    Validator(ExecutableElement element) {
-      super(element);
-    }
-
-    @Override
-    protected void checkAdditionalProperties() {
-      if (!element.getModifiers().contains(ABSTRACT)) {
-        report.addError("@BindsInstance methods must be abstract");
-      }
-      if (element.getParameters().size() != 1) {
-        report.addError(
-            "@BindsInstance methods should have exactly one parameter for the bound type");
-      }
-      TypeElement enclosingType = MoreElements.asType(element.getEnclosingElement());
-      moduleAnnotation(enclosingType)
-          .ifPresent(moduleAnnotation -> report.addError(didYouMeanBinds(moduleAnnotation)));
-      anyComponentAnnotation(enclosingType)
-          .ifPresent(
-              componentAnnotation ->
-                  report.addError(
-                      String.format(
-                          "@BindsInstance methods should not be included in @%1$ss. "
-                              + "Did you mean to put it in a @%1$s.Builder?",
-                          componentAnnotation.simpleName())));
-    }
-
-    @Override
-    protected Optional<TypeMirror> bindingElementType() {
-      List<? extends VariableElement> parameters =
-          MoreElements.asExecutable(element).getParameters();
-      return parameters.size() == 1
-          ? Optional.of(getOnlyElement(parameters).asType())
-          : Optional.empty();
-    }
-  }
-
-  private static String didYouMeanBinds(ModuleAnnotation moduleAnnotation) {
-    return String.format(
-        "@BindsInstance methods should not be included in @%ss. Did you mean @Binds?",
-        moduleAnnotation.annotationName());
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindsInstanceParameterValidator.java b/java/dagger/internal/codegen/validation/BindsInstanceParameterValidator.java
deleted file mode 100644
index 24d65a9..0000000
--- a/java/dagger/internal/codegen/validation/BindsInstanceParameterValidator.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static javax.lang.model.element.ElementKind.METHOD;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.type.TypeKind.DECLARED;
-import static javax.lang.model.type.TypeKind.TYPEVAR;
-
-import com.google.auto.common.MoreElements;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-
-final class BindsInstanceParameterValidator extends BindsInstanceElementValidator<VariableElement> {
-  @Inject
-  BindsInstanceParameterValidator(InjectionAnnotations injectionAnnotations) {
-    super(injectionAnnotations);
-  }
-
-  @Override
-  protected ElementValidator elementValidator(VariableElement element) {
-    return new Validator(element);
-  }
-
-  private class Validator extends ElementValidator {
-    Validator(VariableElement element) {
-      super(element);
-    }
-
-    @Override
-    protected void checkAdditionalProperties() {
-      Element enclosing = element.getEnclosingElement();
-      if (!enclosing.getKind().equals(METHOD)) {
-        report.addError(
-            "@BindsInstance should only be applied to methods or parameters of methods");
-        return;
-      }
-
-      ExecutableElement method = MoreElements.asExecutable(enclosing);
-      if (!method.getModifiers().contains(ABSTRACT)) {
-        report.addError("@BindsInstance parameters may only be used in abstract methods");
-      }
-
-      TypeKind returnKind = method.getReturnType().getKind();
-      if (!(returnKind.equals(DECLARED) || returnKind.equals(TYPEVAR))) {
-        report.addError(
-            "@BindsInstance parameters may not be used in methods with a void, array or primitive "
-                + "return type");
-      }
-    }
-
-    @Override
-    protected Optional<TypeMirror> bindingElementType() {
-      return Optional.of(element.asType());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindsInstanceProcessingStep.java b/java/dagger/internal/codegen/validation/BindsInstanceProcessingStep.java
deleted file mode 100644
index 0e79b91..0000000
--- a/java/dagger/internal/codegen/validation/BindsInstanceProcessingStep.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSet;
-import dagger.BindsInstance;
-import java.lang.annotation.Annotation;
-import java.util.Set;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-
-/**
- * Processing step that validates that the {@code BindsInstance} annotation is applied to the
- * correct elements.
- */
-public final class BindsInstanceProcessingStep extends TypeCheckingProcessingStep<Element> {
-  private final BindsInstanceMethodValidator methodValidator;
-  private final BindsInstanceParameterValidator parameterValidator;
-  private final Messager messager;
-
-  @Inject
-  BindsInstanceProcessingStep(
-      BindsInstanceMethodValidator methodValidator,
-      BindsInstanceParameterValidator parameterValidator,
-      Messager messager) {
-    super(element -> element);
-    this.methodValidator = methodValidator;
-    this.parameterValidator = parameterValidator;
-    this.messager = messager;
-  }
-
-  @Override
-  public Set<? extends Class<? extends Annotation>> annotations() {
-    return ImmutableSet.of(BindsInstance.class);
-  }
-
-  @Override
-  protected void process(Element element, ImmutableSet<Class<? extends Annotation>> annotations) {
-    switch (element.getKind()) {
-      case PARAMETER:
-        parameterValidator.validate(MoreElements.asVariable(element)).printMessagesTo(messager);
-        break;
-      case METHOD:
-        methodValidator.validate(MoreElements.asExecutable(element)).printMessagesTo(messager);
-        break;
-      default:
-        throw new AssertionError(element);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindsMethodValidator.java b/java/dagger/internal/codegen/validation/BindsMethodValidator.java
deleted file mode 100644
index 6d2dd18..0000000
--- a/java/dagger/internal/codegen/validation/BindsMethodValidator.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.ALLOWS_SCOPING;
-import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
-import static dagger.internal.codegen.validation.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS;
-import static dagger.internal.codegen.validation.TypeHierarchyValidator.validateTypeHierarchy;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSet;
-import dagger.Binds;
-import dagger.Module;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.binding.BindsTypeChecker;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.producers.ProducerModule;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeMirror;
-
-/** A validator for {@link Binds} methods. */
-final class BindsMethodValidator extends BindingMethodValidator {
-  private final DaggerTypes types;
-  private final BindsTypeChecker bindsTypeChecker;
-
-  @Inject
-  BindsMethodValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil kotlinMetadataUtil,
-      BindsTypeChecker bindsTypeChecker,
-      DependencyRequestValidator dependencyRequestValidator,
-      InjectionAnnotations injectionAnnotations) {
-    super(
-        elements,
-        types,
-        kotlinMetadataUtil,
-        Binds.class,
-        ImmutableSet.of(Module.class, ProducerModule.class),
-        dependencyRequestValidator,
-        MUST_BE_ABSTRACT,
-        NO_EXCEPTIONS,
-        ALLOWS_MULTIBINDINGS,
-        ALLOWS_SCOPING,
-        injectionAnnotations);
-    this.types = types;
-    this.bindsTypeChecker = bindsTypeChecker;
-  }
-
-  @Override
-  protected ElementValidator elementValidator(ExecutableElement element) {
-    return new Validator(element);
-  }
-
-  private class Validator extends MethodValidator {
-    Validator(ExecutableElement element) {
-      super(element);
-    }
-
-    @Override
-    protected void checkParameters() {
-      if (element.getParameters().size() != 1) {
-        report.addError(
-            bindingMethods(
-                "must have exactly one parameter, whose type is assignable to the return type"));
-      } else {
-        super.checkParameters();
-      }
-    }
-
-    @Override
-    protected void checkParameter(VariableElement parameter) {
-      super.checkParameter(parameter);
-      TypeMirror leftHandSide = boxIfNecessary(element.getReturnType());
-      TypeMirror rightHandSide = parameter.asType();
-      ContributionType contributionType = ContributionType.fromBindingElement(element);
-      if (contributionType.equals(ContributionType.SET_VALUES) && !SetType.isSet(leftHandSide)) {
-        report.addError(
-            "@Binds @ElementsIntoSet methods must return a Set and take a Set parameter");
-      }
-
-      if (!bindsTypeChecker.isAssignable(rightHandSide, leftHandSide, contributionType)) {
-        // Validate the type hierarchy of both sides to make sure they're both valid.
-        // If one of the types isn't valid it means we need to delay validation to the next round.
-        // Note: BasicAnnotationProcessor only performs superficial validation on the referenced
-        // types within the module. Thus, we're guaranteed that the types in the @Binds method are
-        // valid, but it says nothing about their supertypes, which are needed for isAssignable.
-        validateTypeHierarchy(leftHandSide, types);
-        validateTypeHierarchy(rightHandSide, types);
-        // TODO(ronshapiro): clarify this error message for @ElementsIntoSet cases, where the
-        // right-hand-side might not be assignable to the left-hand-side, but still compatible with
-        // Set.addAll(Collection<? extends E>)
-        report.addError("@Binds methods' parameter type must be assignable to the return type");
-      }
-    }
-
-    private TypeMirror boxIfNecessary(TypeMirror maybePrimitive) {
-      if (maybePrimitive.getKind().isPrimitive()) {
-        return types.boxedClass(MoreTypes.asPrimitiveType(maybePrimitive)).asType();
-      }
-      return maybePrimitive;
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/BindsOptionalOfMethodValidator.java b/java/dagger/internal/codegen/validation/BindsOptionalOfMethodValidator.java
deleted file mode 100644
index cb776e1..0000000
--- a/java/dagger/internal/codegen/validation/BindsOptionalOfMethodValidator.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static dagger.internal.codegen.base.Keys.isValidImplicitProvisionKey;
-import static dagger.internal.codegen.binding.InjectionAnnotations.injectedConstructors;
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS;
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.NO_SCOPING;
-import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
-import static dagger.internal.codegen.validation.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS;
-
-import com.google.common.collect.ImmutableSet;
-import dagger.BindsOptionalOf;
-import dagger.Module;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.producers.ProducerModule;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.TypeMirror;
-
-/** A validator for {@link BindsOptionalOf} methods. */
-final class BindsOptionalOfMethodValidator extends BindingMethodValidator {
-
-  private final DaggerTypes types;
-  private final InjectionAnnotations injectionAnnotations;
-
-  @Inject
-  BindsOptionalOfMethodValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil kotlinMetadataUtil,
-      DependencyRequestValidator dependencyRequestValidator,
-      InjectionAnnotations injectionAnnotations) {
-    super(
-        elements,
-        types,
-        kotlinMetadataUtil,
-        BindsOptionalOf.class,
-        ImmutableSet.of(Module.class, ProducerModule.class),
-        dependencyRequestValidator,
-        MUST_BE_ABSTRACT,
-        NO_EXCEPTIONS,
-        NO_MULTIBINDINGS,
-        NO_SCOPING,
-        injectionAnnotations);
-    this.types = types;
-    this.injectionAnnotations = injectionAnnotations;
-  }
-
-
-  @Override
-  protected ElementValidator elementValidator(ExecutableElement element) {
-    return new Validator(element);
-  }
-
-  private class Validator extends MethodValidator {
-    Validator(ExecutableElement element) {
-      super(element);
-    }
-
-    @Override
-    protected void checkKeyType(TypeMirror keyType) {
-      super.checkKeyType(keyType);
-      if (isValidImplicitProvisionKey(
-              injectionAnnotations.getQualifiers(element).stream().findFirst(), keyType, types)
-          && !injectedConstructors(asTypeElement(keyType)).isEmpty()) {
-        report.addError(
-            "@BindsOptionalOf methods cannot return unqualified types that have an @Inject-"
-                + "annotated constructor because those are always present");
-      }
-    }
-
-    @Override
-    protected void checkParameters() {
-      if (!element.getParameters().isEmpty()) {
-        report.addError("@BindsOptionalOf methods cannot have parameters");
-      }
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/ComponentCreatorValidator.java b/java/dagger/internal/codegen/validation/ComponentCreatorValidator.java
deleted file mode 100644
index a6d9a3f..0000000
--- a/java/dagger/internal/codegen/validation/ComponentCreatorValidator.java
+++ /dev/null
@@ -1,408 +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.validation;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.getCreatorAnnotations;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ObjectArrays;
-import dagger.BindsInstance;
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.binding.ComponentCreatorAnnotation;
-import dagger.internal.codegen.binding.ErrorMessages;
-import dagger.internal.codegen.binding.ErrorMessages.ComponentCreatorMessages;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-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.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-
-/** Validates types annotated with component creator annotations. */
-@Singleton
-public final class ComponentCreatorValidator implements ClearableCache {
-
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final Map<TypeElement, ValidationReport<TypeElement>> reports = new HashMap<>();
-
-  @Inject
-  ComponentCreatorValidator(DaggerElements elements, DaggerTypes types) {
-    this.elements = elements;
-    this.types = types;
-  }
-
-  @Override
-  public void clearCache() {
-    reports.clear();
-  }
-
-  /** Validates that the given {@code type} is potentially a valid component creator type. */
-  public ValidationReport<TypeElement> validate(TypeElement type) {
-    return reentrantComputeIfAbsent(reports, type, this::validateUncached);
-  }
-
-  private ValidationReport<TypeElement> validateUncached(TypeElement type) {
-    ValidationReport.Builder<TypeElement> report = ValidationReport.about(type);
-
-    ImmutableSet<ComponentCreatorAnnotation> creatorAnnotations = getCreatorAnnotations(type);
-    if (!validateOnlyOneCreatorAnnotation(creatorAnnotations, report)) {
-      return report.build();
-    }
-
-    // Note: there's more validation in ComponentDescriptorValidator:
-    // - to make sure the setter methods/factory parameters mirror the deps
-    // - to make sure each type or key is set by only one method or parameter
-    ElementValidator validator =
-        new ElementValidator(type, report, getOnlyElement(creatorAnnotations));
-    return validator.validate();
-  }
-
-  private boolean validateOnlyOneCreatorAnnotation(
-      ImmutableSet<ComponentCreatorAnnotation> creatorAnnotations,
-      ValidationReport.Builder<?> report) {
-    // creatorAnnotations should never be empty because this should only ever be called for
-    // types that have been found to have some creator annotation
-    if (creatorAnnotations.size() > 1) {
-      String error =
-          "May not have more than one component Factory or Builder annotation on a type"
-              + ": found "
-              + creatorAnnotations;
-      report.addError(error);
-      return false;
-    }
-
-    return true;
-  }
-
-  /**
-   * Validator for a single {@link TypeElement} that is annotated with a {@code Builder} or {@code
-   * Factory} annotation.
-   */
-  private final class ElementValidator {
-    private final TypeElement type;
-    private final Element component;
-    private final ValidationReport.Builder<TypeElement> report;
-    private final ComponentCreatorAnnotation annotation;
-    private final ComponentCreatorMessages messages;
-
-    private ElementValidator(
-        TypeElement type,
-        ValidationReport.Builder<TypeElement> report,
-        ComponentCreatorAnnotation annotation) {
-      this.type = type;
-      this.component = type.getEnclosingElement();
-      this.report = report;
-      this.annotation = annotation;
-      this.messages = ErrorMessages.creatorMessagesFor(annotation);
-    }
-
-    /** Validates the creator type. */
-    final ValidationReport<TypeElement> validate() {
-      if (!isAnnotationPresent(component, annotation.componentAnnotation())) {
-        report.addError(messages.mustBeInComponent());
-      }
-
-      // If the type isn't a class or interface, don't validate anything else since the rest of the
-      // messages will be bogus.
-      if (!validateIsClassOrInterface()) {
-        return report.build();
-      }
-
-      validateTypeRequirements();
-      switch (annotation.creatorKind()) {
-        case FACTORY:
-          validateFactory();
-          break;
-        case BUILDER:
-          validateBuilder();
-      }
-
-      return report.build();
-    }
-
-    /** Validates that the type is a class or interface type and returns true if it is. */
-    private boolean validateIsClassOrInterface() {
-      switch (type.getKind()) {
-        case CLASS:
-          validateConstructor();
-          return true;
-        case INTERFACE:
-          return true;
-        default:
-          report.addError(messages.mustBeClassOrInterface());
-      }
-      return false;
-    }
-
-    private void validateConstructor() {
-      List<? extends Element> allElements = type.getEnclosedElements();
-      List<ExecutableElement> constructors = ElementFilter.constructorsIn(allElements);
-
-      boolean valid = true;
-      if (constructors.size() != 1) {
-        valid = false;
-      } else {
-        ExecutableElement constructor = getOnlyElement(constructors);
-        valid =
-            constructor.getParameters().isEmpty() && !constructor.getModifiers().contains(PRIVATE);
-      }
-
-      if (!valid) {
-        report.addError(messages.invalidConstructor());
-      }
-    }
-
-    /** Validates basic requirements about the type that are common to both creator kinds. */
-    private void validateTypeRequirements() {
-      if (!type.getTypeParameters().isEmpty()) {
-        report.addError(messages.generics());
-      }
-
-      Set<Modifier> modifiers = type.getModifiers();
-      if (modifiers.contains(PRIVATE)) {
-        report.addError(messages.isPrivate());
-      }
-      if (!modifiers.contains(STATIC)) {
-        report.addError(messages.mustBeStatic());
-      }
-      // Note: Must be abstract, so no need to check for final.
-      if (!modifiers.contains(ABSTRACT)) {
-        report.addError(messages.mustBeAbstract());
-      }
-    }
-
-    private void validateBuilder() {
-      ExecutableElement buildMethod = null;
-      for (ExecutableElement method : elements.getUnimplementedMethods(type)) {
-        switch (method.getParameters().size()) {
-          case 0: // If this is potentially a build() method, validate it returns the correct type.
-            if (validateFactoryMethodReturnType(method)) {
-              if (buildMethod != null) {
-                // If we found more than one build-like method, fail.
-                error(
-                    method,
-                    messages.twoFactoryMethods(),
-                    messages.inheritedTwoFactoryMethods(),
-                    buildMethod);
-              }
-            }
-            // We set the buildMethod regardless of the return type to reduce error spam.
-            buildMethod = method;
-            break;
-
-          case 1: // If this correctly had one parameter, make sure the return types are valid.
-            validateSetterMethod(method);
-            break;
-
-          default: // more than one parameter
-            error(
-                method,
-                messages.setterMethodsMustTakeOneArg(),
-                messages.inheritedSetterMethodsMustTakeOneArg());
-            break;
-        }
-      }
-
-      if (buildMethod == null) {
-        report.addError(messages.missingFactoryMethod());
-      } else {
-        validateNotGeneric(buildMethod);
-      }
-    }
-
-    private void validateSetterMethod(ExecutableElement method) {
-      TypeMirror returnType = types.resolveExecutableType(method, type.asType()).getReturnType();
-      if (returnType.getKind() != TypeKind.VOID && !types.isSubtype(type.asType(), returnType)) {
-        error(
-            method,
-            messages.setterMethodsMustReturnVoidOrBuilder(),
-            messages.inheritedSetterMethodsMustReturnVoidOrBuilder());
-      }
-
-      validateNotGeneric(method);
-
-      VariableElement parameter = method.getParameters().get(0);
-
-      boolean methodIsBindsInstance = isAnnotationPresent(method, BindsInstance.class);
-      boolean parameterIsBindsInstance = isAnnotationPresent(parameter, BindsInstance.class);
-      boolean bindsInstance = methodIsBindsInstance || parameterIsBindsInstance;
-
-      if (methodIsBindsInstance && parameterIsBindsInstance) {
-        error(
-            method,
-            messages.bindsInstanceNotAllowedOnBothSetterMethodAndParameter(),
-            messages.inheritedBindsInstanceNotAllowedOnBothSetterMethodAndParameter());
-      }
-
-      if (!bindsInstance && parameter.asType().getKind().isPrimitive()) {
-        error(
-            method,
-            messages.nonBindsInstanceParametersMayNotBePrimitives(),
-            messages.inheritedNonBindsInstanceParametersMayNotBePrimitives());
-      }
-    }
-
-    private void validateFactory() {
-      ImmutableList<ExecutableElement> abstractMethods =
-          elements.getUnimplementedMethods(type).asList();
-      switch (abstractMethods.size()) {
-        case 0:
-          report.addError(messages.missingFactoryMethod());
-          return;
-        case 1:
-          break; // good
-        default:
-          error(
-              abstractMethods.get(1),
-              messages.twoFactoryMethods(),
-              messages.inheritedTwoFactoryMethods(),
-              abstractMethods.get(0));
-          return;
-      }
-
-      validateFactoryMethod(getOnlyElement(abstractMethods));
-    }
-
-    /** Validates that the given {@code method} is a valid component factory method. */
-    private void validateFactoryMethod(ExecutableElement method) {
-      validateNotGeneric(method);
-
-      if (!validateFactoryMethodReturnType(method)) {
-        // If we can't determine that the single method is a valid factory method, don't bother
-        // validating its parameters.
-        return;
-      }
-
-      for (VariableElement parameter : method.getParameters()) {
-        if (!isAnnotationPresent(parameter, BindsInstance.class)
-            && parameter.asType().getKind().isPrimitive()) {
-          error(
-              method,
-              messages.nonBindsInstanceParametersMayNotBePrimitives(),
-              messages.inheritedNonBindsInstanceParametersMayNotBePrimitives());
-        }
-      }
-    }
-
-    /**
-     * Validates that the factory method that actually returns a new component instance. Returns
-     * true if the return type was valid.
-     */
-    private boolean validateFactoryMethodReturnType(ExecutableElement method) {
-      TypeMirror returnType = types.resolveExecutableType(method, type.asType()).getReturnType();
-
-      if (!types.isSubtype(component.asType(), returnType)) {
-        error(
-            method,
-            messages.factoryMethodMustReturnComponentType(),
-            messages.inheritedFactoryMethodMustReturnComponentType());
-        return false;
-      }
-
-      if (isAnnotationPresent(method, BindsInstance.class)) {
-        error(
-            method,
-            messages.factoryMethodMayNotBeAnnotatedWithBindsInstance(),
-            messages.inheritedFactoryMethodMayNotBeAnnotatedWithBindsInstance());
-        return false;
-      }
-
-      TypeElement componentType = MoreElements.asType(component);
-      if (!types.isSameType(componentType.asType(), returnType)) {
-        ImmutableSet<ExecutableElement> methodsOnlyInComponent =
-            methodsOnlyInComponent(componentType);
-        if (!methodsOnlyInComponent.isEmpty()) {
-          report.addWarning(
-              messages.factoryMethodReturnsSupertypeWithMissingMethods(
-                  componentType, type, returnType, method, methodsOnlyInComponent),
-              method);
-        }
-      }
-      return true;
-    }
-
-    /**
-     * Generates one of two error messages. If the method is enclosed in the subject, we target the
-     * error to the method itself. Otherwise we target the error to the subject and list the method
-     * as an argument. (Otherwise we have no way of knowing if the method is being compiled in this
-     * pass too, so javac might not be able to pinpoint it's line of code.)
-     */
-    /*
-     * For Component.Builder, the prototypical example would be if someone had:
-     *    libfoo: interface SharedBuilder { void badSetter(A a, B b); }
-     *    libbar: BarComponent { BarBuilder extends SharedBuilder } }
-     * ... the compiler only validates BarBuilder when compiling libbar, but it fails because
-     * of libfoo's SharedBuilder (which could have been compiled in a previous pass).
-     * So we can't point to SharedBuilder#badSetter as the subject of the BarBuilder validation
-     * failure.
-     *
-     * This check is a little more strict than necessary -- ideally we'd check if method's enclosing
-     * class was included in this compile run.  But that's hard, and this is close enough.
-     */
-    private void error(
-        ExecutableElement method,
-        String enclosedError,
-        String inheritedError,
-        Object... extraArgs) {
-      if (method.getEnclosingElement().equals(type)) {
-        report.addError(String.format(enclosedError, extraArgs), method);
-      } else {
-        report.addError(String.format(inheritedError, ObjectArrays.concat(extraArgs, method)));
-      }
-    }
-
-    /** Validates that the given {@code method} is not generic. * */
-    private void validateNotGeneric(ExecutableElement method) {
-      if (!method.getTypeParameters().isEmpty()) {
-        error(
-            method,
-            messages.methodsMayNotHaveTypeParameters(),
-            messages.inheritedMethodsMayNotHaveTypeParameters());
-      }
-    }
-
-    /**
-     * Returns all methods defind in {@code componentType} which are not inherited from a supertype.
-     */
-    private ImmutableSet<ExecutableElement> methodsOnlyInComponent(TypeElement componentType) {
-      // TODO(ronshapiro): Ideally this shouldn't return methods which are redeclared from a
-      // supertype, but do not change the return type. We don't have a good/simple way of checking
-      // that, and it doesn't seem likely, so the warning won't be too bad.
-      return ImmutableSet.copyOf(methodsIn(componentType.getEnclosedElements()));
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/ComponentDescriptorValidator.java b/java/dagger/internal/codegen/validation/ComponentDescriptorValidator.java
deleted file mode 100644
index aa20232..0000000
--- a/java/dagger/internal/codegen/validation/ComponentDescriptorValidator.java
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * 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.validation;
-
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Predicates.in;
-import static com.google.common.collect.Collections2.transform;
-import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotation;
-import static dagger.internal.codegen.base.DiagnosticFormatting.stripCommonTypePrefixes;
-import static dagger.internal.codegen.base.Formatter.INDENT;
-import static dagger.internal.codegen.base.Scopes.getReadableSource;
-import static dagger.internal.codegen.base.Scopes.scopesOf;
-import static dagger.internal.codegen.base.Scopes.singletonScope;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSetMultimap;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.Sets;
-import dagger.internal.codegen.binding.ComponentCreatorDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.ComponentRequirement.NullPolicy;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.ErrorMessages;
-import dagger.internal.codegen.binding.ErrorMessages.ComponentCreatorMessages;
-import dagger.internal.codegen.binding.MethodSignatureFormatter;
-import dagger.internal.codegen.binding.ModuleDescriptor;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.compileroption.ValidationType;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Scope;
-import java.util.ArrayDeque;
-import java.util.Collection;
-import java.util.Deque;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import java.util.StringJoiner;
-import javax.inject.Inject;
-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.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-import javax.tools.Diagnostic;
-
-/**
- * Reports errors in the component hierarchy.
- *
- * <ul>
- *   <li>Validates scope hierarchy of component dependencies and subcomponents.
- *   <li>Reports errors if there are component dependency cycles.
- *   <li>Reports errors if any abstract modules have non-abstract instance binding methods.
- *   <li>Validates component creator types.
- * </ul>
- */
-// TODO(dpb): Combine with ComponentHierarchyValidator.
-public final class ComponentDescriptorValidator {
-
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final CompilerOptions compilerOptions;
-  private final MethodSignatureFormatter methodSignatureFormatter;
-  private final ComponentHierarchyValidator componentHierarchyValidator;
-  private final KotlinMetadataUtil metadataUtil;
-
-  @Inject
-  ComponentDescriptorValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      CompilerOptions compilerOptions,
-      MethodSignatureFormatter methodSignatureFormatter,
-      ComponentHierarchyValidator componentHierarchyValidator,
-      KotlinMetadataUtil metadataUtil) {
-    this.elements = elements;
-    this.types = types;
-    this.compilerOptions = compilerOptions;
-    this.methodSignatureFormatter = methodSignatureFormatter;
-    this.componentHierarchyValidator = componentHierarchyValidator;
-    this.metadataUtil = metadataUtil;
-  }
-
-  public ValidationReport<TypeElement> validate(ComponentDescriptor component) {
-    ComponentValidation validation = new ComponentValidation(component);
-    validation.visitComponent(component);
-    validation.report(component).addSubreport(componentHierarchyValidator.validate(component));
-    return validation.buildReport();
-  }
-
-  private final class ComponentValidation {
-    final ComponentDescriptor rootComponent;
-    final Map<ComponentDescriptor, ValidationReport.Builder<TypeElement>> reports =
-        new LinkedHashMap<>();
-
-    ComponentValidation(ComponentDescriptor rootComponent) {
-      this.rootComponent = checkNotNull(rootComponent);
-    }
-
-    /** Returns a report that contains all validation messages found during traversal. */
-    ValidationReport<TypeElement> buildReport() {
-      ValidationReport.Builder<TypeElement> report =
-          ValidationReport.about(rootComponent.typeElement());
-      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.typeElement()));
-    }
-
-    private void reportComponentItem(
-        Diagnostic.Kind kind, ComponentDescriptor component, String message) {
-      report(component)
-          .addItem(message, kind, component.typeElement(), component.annotation().annotation());
-    }
-
-    private void reportComponentError(ComponentDescriptor component, String error) {
-      reportComponentItem(ERROR, component, error);
-    }
-
-    void visitComponent(ComponentDescriptor component) {
-      validateDependencyScopes(component);
-      validateComponentDependencyHierarchy(component);
-      validateModules(component);
-      validateCreators(component);
-      component.childComponents().forEach(this::visitComponent);
-    }
-
-    /** Validates that component dependencies do not form a cycle. */
-    private void validateComponentDependencyHierarchy(ComponentDescriptor component) {
-      validateComponentDependencyHierarchy(component, component.typeElement(), new ArrayDeque<>());
-    }
-
-    /** Recursive method to validate that component dependencies do not form a cycle. */
-    private void validateComponentDependencyHierarchy(
-        ComponentDescriptor component, TypeElement dependency, Deque<TypeElement> dependencyStack) {
-      if (dependencyStack.contains(dependency)) {
-        // Current component has already appeared in the component chain.
-        StringBuilder message = new StringBuilder();
-        message.append(component.typeElement().getQualifiedName());
-        message.append(" contains a cycle in its component dependencies:\n");
-        dependencyStack.push(dependency);
-        appendIndentedComponentsList(message, dependencyStack);
-        dependencyStack.pop();
-        reportComponentItem(
-            compilerOptions.scopeCycleValidationType().diagnosticKind().get(),
-            component,
-            message.toString());
-      } else if (compilerOptions.validateTransitiveComponentDependencies()
-          // Always validate direct component dependencies referenced by this component regardless
-          // of the flag value
-          || dependencyStack.isEmpty()) {
-        rootComponentAnnotation(dependency)
-            .ifPresent(
-                componentAnnotation -> {
-                  dependencyStack.push(dependency);
-
-                  for (TypeElement nextDependency : componentAnnotation.dependencies()) {
-                    validateComponentDependencyHierarchy(
-                        component, nextDependency, dependencyStack);
-                  }
-
-                  dependencyStack.pop();
-                });
-      }
-    }
-
-    /**
-     * Validates that among the dependencies there are no cycles within the scoping chain, and that
-     * singleton components have no scoped dependencies.
-     */
-    private void validateDependencyScopes(ComponentDescriptor component) {
-      ImmutableSet<Scope> scopes = component.scopes();
-      ImmutableSet<TypeElement> scopedDependencies =
-          scopedTypesIn(
-              component
-                  .dependencies()
-                  .stream()
-                  .map(ComponentRequirement::typeElement)
-                  .collect(toImmutableSet()));
-      if (!scopes.isEmpty()) {
-        Scope singletonScope = singletonScope(elements);
-        // Dagger 1.x scope compatibility requires this be suppress-able.
-        if (compilerOptions.scopeCycleValidationType().diagnosticKind().isPresent()
-            && scopes.contains(singletonScope)) {
-          // Singleton is a special-case representing the longest lifetime, and therefore
-          // @Singleton components may not depend on scoped components
-          if (!scopedDependencies.isEmpty()) {
-            StringBuilder message =
-                new StringBuilder(
-                    "This @Singleton component cannot depend on scoped components:\n");
-            appendIndentedComponentsList(message, scopedDependencies);
-            reportComponentItem(
-                compilerOptions.scopeCycleValidationType().diagnosticKind().get(),
-                component,
-                message.toString());
-          }
-        } else {
-          // Dagger 1.x scope compatibility requires this be suppress-able.
-          if (!compilerOptions.scopeCycleValidationType().equals(ValidationType.NONE)) {
-            validateDependencyScopeHierarchy(
-                component, component.typeElement(), new ArrayDeque<>(), new ArrayDeque<>());
-          }
-        }
-      } else {
-        // Scopeless components may not depend on scoped components.
-        if (!scopedDependencies.isEmpty()) {
-          StringBuilder message =
-              new StringBuilder(component.typeElement().getQualifiedName())
-                  .append(" (unscoped) cannot depend on scoped components:\n");
-          appendIndentedComponentsList(message, scopedDependencies);
-          reportComponentError(component, message.toString());
-        }
-      }
-    }
-
-    private void validateModules(ComponentDescriptor component) {
-      for (ModuleDescriptor module : component.modules()) {
-        if (module.moduleElement().getModifiers().contains(Modifier.ABSTRACT)) {
-          for (ContributionBinding binding : module.bindings()) {
-            if (binding.requiresModuleInstance()) {
-              report(component).addError(abstractModuleHasInstanceBindingMethodsError(module));
-              break;
-            }
-          }
-        }
-      }
-    }
-
-    private String abstractModuleHasInstanceBindingMethodsError(ModuleDescriptor module) {
-      String methodAnnotations;
-      switch (module.kind()) {
-        case MODULE:
-          methodAnnotations = "@Provides";
-          break;
-        case PRODUCER_MODULE:
-          methodAnnotations = "@Provides or @Produces";
-          break;
-        default:
-          throw new AssertionError(module.kind());
-      }
-      return String.format(
-          "%s is abstract and has instance %s methods. Consider making the methods static or "
-              + "including a non-abstract subclass of the module instead.",
-          module.moduleElement(), methodAnnotations);
-    }
-
-    private void validateCreators(ComponentDescriptor component) {
-      if (!component.creatorDescriptor().isPresent()) {
-        // If no builder, nothing to validate.
-        return;
-      }
-
-      ComponentCreatorDescriptor creator = component.creatorDescriptor().get();
-      ComponentCreatorMessages messages = ErrorMessages.creatorMessagesFor(creator.annotation());
-
-      // Requirements for modules and dependencies that the creator can set
-      Set<ComponentRequirement> creatorModuleAndDependencyRequirements =
-          creator.moduleAndDependencyRequirements();
-      // Modules and dependencies the component requires
-      Set<ComponentRequirement> componentModuleAndDependencyRequirements =
-          component.dependenciesAndConcreteModules();
-
-      // Requirements that the creator can set that don't match any requirements that the component
-      // actually has.
-      Set<ComponentRequirement> inapplicableRequirementsOnCreator =
-          Sets.difference(
-              creatorModuleAndDependencyRequirements, componentModuleAndDependencyRequirements);
-
-      DeclaredType container = asDeclared(creator.typeElement().asType());
-      if (!inapplicableRequirementsOnCreator.isEmpty()) {
-        Collection<Element> excessElements =
-            Multimaps.filterKeys(
-                    creator.unvalidatedRequirementElements(), in(inapplicableRequirementsOnCreator))
-                .values();
-        String formatted =
-            excessElements.stream()
-                .map(element -> formatElement(element, container))
-                .collect(joining(", ", "[", "]"));
-        report(component)
-            .addError(String.format(messages.extraSetters(), formatted), creator.typeElement());
-      }
-
-      // Component requirements that the creator must be able to set
-      Set<ComponentRequirement> mustBePassed =
-          Sets.filter(
-              componentModuleAndDependencyRequirements,
-              input -> input.nullPolicy(elements, types, metadataUtil).equals(NullPolicy.THROW));
-      // Component requirements that the creator must be able to set, but can't
-      Set<ComponentRequirement> missingRequirements =
-          Sets.difference(mustBePassed, creatorModuleAndDependencyRequirements);
-
-      if (!missingRequirements.isEmpty()) {
-        report(component)
-            .addError(
-                String.format(
-                    messages.missingSetters(),
-                    missingRequirements.stream().map(ComponentRequirement::type).collect(toList())),
-                creator.typeElement());
-      }
-
-      // Validate that declared creator requirements (modules, dependencies) have unique types.
-      ImmutableSetMultimap<Wrapper<TypeMirror>, Element> declaredRequirementsByType =
-          Multimaps.filterKeys(
-                  creator.unvalidatedRequirementElements(),
-                  creatorModuleAndDependencyRequirements::contains)
-              .entries().stream()
-              .collect(
-                  toImmutableSetMultimap(entry -> entry.getKey().wrappedType(), Entry::getValue));
-      declaredRequirementsByType
-          .asMap()
-          .forEach(
-              (typeWrapper, elementsForType) -> {
-                if (elementsForType.size() > 1) {
-                  TypeMirror type = typeWrapper.get();
-                  // TODO(cgdecker): Attach this error message to the factory method rather than
-                  // the component type if the elements are factory method parameters AND the
-                  // factory method is defined by the factory type itself and not by a supertype.
-                  report(component)
-                      .addError(
-                          String.format(
-                              messages.multipleSettersForModuleOrDependencyType(),
-                              type,
-                              transform(
-                                  elementsForType, element -> formatElement(element, container))),
-                          creator.typeElement());
-                }
-              });
-
-      // TODO(cgdecker): Duplicate binding validation should handle the case of multiple elements
-      // that set the same bound-instance Key, but validating that here would make it fail faster
-      // for subcomponents.
-    }
-
-    private String formatElement(Element element, DeclaredType container) {
-      // TODO(cgdecker): Extract some or all of this to another class?
-      // But note that it does different formatting for parameters than
-      // DaggerElements.elementToString(Element).
-      switch (element.getKind()) {
-        case METHOD:
-          return methodSignatureFormatter.format(
-              MoreElements.asExecutable(element), Optional.of(container));
-        case PARAMETER:
-          return formatParameter(MoreElements.asVariable(element), container);
-        default:
-          // This method shouldn't be called with any other type of element.
-          throw new AssertionError();
-      }
-    }
-
-    private String formatParameter(VariableElement parameter, DeclaredType container) {
-      // TODO(cgdecker): Possibly leave the type (and annotations?) off of the parameters here and
-      // just use their names, since the type will be redundant in the context of the error message.
-      StringJoiner joiner = new StringJoiner(" ");
-      parameter.getAnnotationMirrors().stream().map(Object::toString).forEach(joiner::add);
-      TypeMirror parameterType = resolveParameterType(parameter, container);
-      return joiner
-          .add(stripCommonTypePrefixes(parameterType.toString()))
-          .add(parameter.getSimpleName())
-          .toString();
-    }
-
-    private TypeMirror resolveParameterType(VariableElement parameter, DeclaredType container) {
-      ExecutableElement method =
-          MoreElements.asExecutable(parameter.getEnclosingElement());
-      int parameterIndex = method.getParameters().indexOf(parameter);
-
-      ExecutableType methodType = MoreTypes.asExecutable(types.asMemberOf(container, method));
-      return methodType.getParameterTypes().get(parameterIndex);
-    }
-
-    /**
-     * Validates that scopes do not participate in a scoping cycle - that is to say, scoped
-     * components are in a hierarchical relationship terminating with Singleton.
-     *
-     * <p>As a side-effect, this means scoped components cannot have a dependency cycle between
-     * themselves, since a component's presence within its own dependency path implies a cyclical
-     * relationship between scopes. However, cycles in component dependencies are explicitly checked
-     * in {@link #validateComponentDependencyHierarchy(ComponentDescriptor)}.
-     */
-    private void validateDependencyScopeHierarchy(
-        ComponentDescriptor component,
-        TypeElement dependency,
-        Deque<ImmutableSet<Scope>> scopeStack,
-        Deque<TypeElement> scopedDependencyStack) {
-      ImmutableSet<Scope> scopes = scopesOf(dependency);
-      if (stackOverlaps(scopeStack, scopes)) {
-        scopedDependencyStack.push(dependency);
-        // Current scope has already appeared in the component chain.
-        StringBuilder message = new StringBuilder();
-        message.append(component.typeElement().getQualifiedName());
-        message.append(" depends on scoped components in a non-hierarchical scope ordering:\n");
-        appendIndentedComponentsList(message, scopedDependencyStack);
-        if (compilerOptions.scopeCycleValidationType().diagnosticKind().isPresent()) {
-          reportComponentItem(
-              compilerOptions.scopeCycleValidationType().diagnosticKind().get(),
-              component,
-              message.toString());
-        }
-        scopedDependencyStack.pop();
-      } else if (compilerOptions.validateTransitiveComponentDependencies()
-          // Always validate direct component dependencies referenced by this component regardless
-          // of the flag value
-          || scopedDependencyStack.isEmpty()) {
-        // TODO(beder): transitively check scopes of production components too.
-        rootComponentAnnotation(dependency)
-            .filter(componentAnnotation -> !componentAnnotation.isProduction())
-            .ifPresent(
-                componentAnnotation -> {
-                  ImmutableSet<TypeElement> scopedDependencies =
-                      scopedTypesIn(componentAnnotation.dependencies());
-                  if (!scopedDependencies.isEmpty()) {
-                    // empty can be ignored (base-case)
-                    scopeStack.push(scopes);
-                    scopedDependencyStack.push(dependency);
-                    for (TypeElement scopedDependency : scopedDependencies) {
-                      validateDependencyScopeHierarchy(
-                          component,
-                          scopedDependency,
-                          scopeStack,
-                          scopedDependencyStack);
-                    }
-                    scopedDependencyStack.pop();
-                    scopeStack.pop();
-                  }
-                }); // else: we skip component dependencies which are not components
-      }
-    }
-
-    private <T> boolean stackOverlaps(Deque<ImmutableSet<T>> stack, ImmutableSet<T> set) {
-      for (ImmutableSet<T> entry : stack) {
-        if (!Sets.intersection(entry, set).isEmpty()) {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    /** Appends and formats a list of indented component types (with their scope annotations). */
-    private void appendIndentedComponentsList(StringBuilder message, Iterable<TypeElement> types) {
-      for (TypeElement scopedComponent : types) {
-        message.append(INDENT);
-        for (Scope scope : scopesOf(scopedComponent)) {
-          message.append(getReadableSource(scope)).append(' ');
-        }
-        message
-            .append(stripCommonTypePrefixes(scopedComponent.getQualifiedName().toString()))
-            .append('\n');
-      }
-    }
-
-    /**
-     * Returns a set of type elements containing only those found in the input set that have a
-     * scoping annotation.
-     */
-    private ImmutableSet<TypeElement> scopedTypesIn(Collection<TypeElement> types) {
-      return types.stream().filter(type -> !scopesOf(type).isEmpty()).collect(toImmutableSet());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/ComponentHierarchyValidator.java b/java/dagger/internal/codegen/validation/ComponentHierarchyValidator.java
deleted file mode 100644
index 1861636..0000000
--- a/java/dagger/internal/codegen/validation/ComponentHierarchyValidator.java
+++ /dev/null
@@ -1,273 +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.validation;
-
-import static com.google.common.base.Functions.constant;
-import static com.google.common.base.Predicates.and;
-import static com.google.common.base.Predicates.in;
-import static com.google.common.base.Predicates.not;
-import static dagger.internal.codegen.base.Scopes.getReadableSource;
-import static dagger.internal.codegen.base.Scopes.uniqueScopeOf;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.base.Joiner;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.binding.ModuleDescriptor;
-import dagger.internal.codegen.binding.ModuleKind;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.model.Scope;
-import java.util.Collection;
-import java.util.Formatter;
-import java.util.Map;
-import javax.inject.Inject;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-
-/** Validates the relationships between parent components and subcomponents. */
-final class ComponentHierarchyValidator {
-  private static final Joiner COMMA_SEPARATED_JOINER = Joiner.on(", ");
-  private final CompilerOptions compilerOptions;
-
-  @Inject
-  ComponentHierarchyValidator(CompilerOptions compilerOptions) {
-    this.compilerOptions = compilerOptions;
-  }
-
-  ValidationReport<TypeElement> validate(ComponentDescriptor componentDescriptor) {
-    ValidationReport.Builder<TypeElement> report =
-        ValidationReport.about(componentDescriptor.typeElement());
-    validateSubcomponentMethods(
-        report,
-        componentDescriptor,
-        Maps.toMap(componentDescriptor.moduleTypes(), constant(componentDescriptor.typeElement())));
-    validateRepeatedScopedDeclarations(report, componentDescriptor, LinkedHashMultimap.create());
-
-    if (compilerOptions.scopeCycleValidationType().diagnosticKind().isPresent()) {
-      validateScopeHierarchy(
-          report, componentDescriptor, LinkedHashMultimap.<ComponentDescriptor, Scope>create());
-    }
-    validateProductionModuleUniqueness(report, componentDescriptor, LinkedHashMultimap.create());
-    return report.build();
-  }
-
-  private void validateSubcomponentMethods(
-      ValidationReport.Builder<?> report,
-      ComponentDescriptor componentDescriptor,
-      ImmutableMap<TypeElement, TypeElement> existingModuleToOwners) {
-    componentDescriptor
-        .childComponentsDeclaredByFactoryMethods()
-        .forEach(
-            (method, childComponent) -> {
-              if (childComponent.hasCreator()) {
-                report.addError(
-                    "Components may not have factory methods for subcomponents that define a "
-                        + "builder.",
-                    method.methodElement());
-              } else {
-                validateFactoryMethodParameters(report, method, existingModuleToOwners);
-              }
-
-              validateSubcomponentMethods(
-                  report,
-                  childComponent,
-                  new ImmutableMap.Builder<TypeElement, TypeElement>()
-                      .putAll(existingModuleToOwners)
-                      .putAll(
-                          Maps.toMap(
-                              Sets.difference(
-                                  childComponent.moduleTypes(), existingModuleToOwners.keySet()),
-                              constant(childComponent.typeElement())))
-                      .build());
-            });
-  }
-
-  private void validateFactoryMethodParameters(
-      ValidationReport.Builder<?> report,
-      ComponentMethodDescriptor subcomponentMethodDescriptor,
-      ImmutableMap<TypeElement, TypeElement> existingModuleToOwners) {
-    for (VariableElement factoryMethodParameter :
-        subcomponentMethodDescriptor.methodElement().getParameters()) {
-      TypeElement moduleType = MoreTypes.asTypeElement(factoryMethodParameter.asType());
-      TypeElement originatingComponent = existingModuleToOwners.get(moduleType);
-      if (originatingComponent != null) {
-        /* Factory method tries to pass a module that is already present in the parent.
-         * This is an error. */
-        report.addError(
-            String.format(
-                "%s is present in %s. A subcomponent cannot use an instance of a "
-                    + "module that differs from its parent.",
-                moduleType.getSimpleName(), originatingComponent.getQualifiedName()),
-            factoryMethodParameter);
-      }
-    }
-  }
-
-  /**
-   * Checks that components do not have any scopes that are also applied on any of their ancestors.
-   */
-  private void validateScopeHierarchy(
-      ValidationReport.Builder<TypeElement> report,
-      ComponentDescriptor subject,
-      SetMultimap<ComponentDescriptor, Scope> scopesByComponent) {
-    scopesByComponent.putAll(subject, subject.scopes());
-
-    for (ComponentDescriptor childComponent : subject.childComponents()) {
-      validateScopeHierarchy(report, childComponent, scopesByComponent);
-    }
-
-    scopesByComponent.removeAll(subject);
-
-    Predicate<Scope> subjectScopes =
-        subject.isProduction()
-            // TODO(beder): validate that @ProductionScope is only applied on production components
-            ? and(in(subject.scopes()), not(Scope::isProductionScope))
-            : in(subject.scopes());
-    SetMultimap<ComponentDescriptor, Scope> overlappingScopes =
-        Multimaps.filterValues(scopesByComponent, subjectScopes);
-    if (!overlappingScopes.isEmpty()) {
-      StringBuilder error =
-          new StringBuilder()
-              .append(subject.typeElement().getQualifiedName())
-              .append(" has conflicting scopes:");
-      for (Map.Entry<ComponentDescriptor, Scope> entry : overlappingScopes.entries()) {
-        Scope scope = entry.getValue();
-        error
-            .append("\n  ")
-            .append(entry.getKey().typeElement().getQualifiedName())
-            .append(" also has ")
-            .append(getReadableSource(scope));
-      }
-      report.addItem(
-          error.toString(),
-          compilerOptions.scopeCycleValidationType().diagnosticKind().get(),
-          subject.typeElement());
-    }
-  }
-
-  private void validateProductionModuleUniqueness(
-      ValidationReport.Builder<TypeElement> report,
-      ComponentDescriptor componentDescriptor,
-      SetMultimap<ComponentDescriptor, ModuleDescriptor> producerModulesByComponent) {
-    ImmutableSet<ModuleDescriptor> producerModules =
-        componentDescriptor.modules().stream()
-            .filter(module -> module.kind().equals(ModuleKind.PRODUCER_MODULE))
-            .collect(toImmutableSet());
-
-    producerModulesByComponent.putAll(componentDescriptor, producerModules);
-    for (ComponentDescriptor childComponent : componentDescriptor.childComponents()) {
-      validateProductionModuleUniqueness(report, childComponent, producerModulesByComponent);
-    }
-    producerModulesByComponent.removeAll(componentDescriptor);
-
-
-    SetMultimap<ComponentDescriptor, ModuleDescriptor> repeatedModules =
-        Multimaps.filterValues(producerModulesByComponent, producerModules::contains);
-    if (repeatedModules.isEmpty()) {
-      return;
-    }
-
-    StringBuilder error = new StringBuilder();
-    Formatter formatter = new Formatter(error);
-
-    formatter.format("%s repeats @ProducerModules:", componentDescriptor.typeElement());
-
-    for (Map.Entry<ComponentDescriptor, Collection<ModuleDescriptor>> entry :
-        repeatedModules.asMap().entrySet()) {
-      formatter.format("\n  %s also installs: ", entry.getKey().typeElement());
-      COMMA_SEPARATED_JOINER
-          .appendTo(error, Iterables.transform(entry.getValue(), m -> m.moduleElement()));
-    }
-
-    report.addError(error.toString());
-  }
-
-  private void validateRepeatedScopedDeclarations(
-      ValidationReport.Builder<TypeElement> report,
-      ComponentDescriptor component,
-      // TODO(ronshapiro): optimize ModuleDescriptor.hashCode()/equals. Otherwise this could be
-      // quite costly
-      SetMultimap<ComponentDescriptor, ModuleDescriptor> modulesWithScopes) {
-    ImmutableSet<ModuleDescriptor> modules =
-        component.modules().stream().filter(this::hasScopedDeclarations).collect(toImmutableSet());
-    modulesWithScopes.putAll(component, modules);
-    for (ComponentDescriptor childComponent : component.childComponents()) {
-      validateRepeatedScopedDeclarations(report, childComponent, modulesWithScopes);
-    }
-    modulesWithScopes.removeAll(component);
-
-    SetMultimap<ComponentDescriptor, ModuleDescriptor> repeatedModules =
-        Multimaps.filterValues(modulesWithScopes, modules::contains);
-    if (repeatedModules.isEmpty()) {
-      return;
-    }
-
-    report.addError(
-        repeatedModulesWithScopeError(component, ImmutableSetMultimap.copyOf(repeatedModules)));
-  }
-
-  private boolean hasScopedDeclarations(ModuleDescriptor module) {
-    return !moduleScopes(module).isEmpty();
-  }
-
-  private String repeatedModulesWithScopeError(
-      ComponentDescriptor component,
-      ImmutableSetMultimap<ComponentDescriptor, ModuleDescriptor> repeatedModules) {
-    StringBuilder error =
-        new StringBuilder()
-            .append(component.typeElement().getQualifiedName())
-            .append(" repeats modules with scoped bindings or declarations:");
-
-    repeatedModules
-        .asMap()
-        .forEach(
-            (conflictingComponent, conflictingModules) -> {
-              error
-                  .append("\n  - ")
-                  .append(conflictingComponent.typeElement().getQualifiedName())
-                  .append(" also includes:");
-              for (ModuleDescriptor conflictingModule : conflictingModules) {
-                error
-                    .append("\n    - ")
-                    .append(conflictingModule.moduleElement().getQualifiedName())
-                    .append(" with scopes: ")
-                    .append(COMMA_SEPARATED_JOINER.join(moduleScopes(conflictingModule)));
-              }
-            });
-    return error.toString();
-  }
-
-  private ImmutableSet<Scope> moduleScopes(ModuleDescriptor module) {
-    return FluentIterable.concat(module.allBindingDeclarations())
-        .transform(declaration -> uniqueScopeOf(declaration.bindingElement().get()))
-        .filter(scope -> scope.isPresent() && !scope.get().isReusable())
-        .transform(scope -> scope.get())
-        .toSet();
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/ComponentValidator.java b/java/dagger/internal/codegen/validation/ComponentValidator.java
deleted file mode 100644
index b3322e5..0000000
--- a/java/dagger/internal/codegen/validation/ComponentValidator.java
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright (C) 2014 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.validation;
-
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreElements.getLocalAndInheritedMethods;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.auto.common.MoreTypes.asExecutable;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.common.base.Verify.verify;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.google.common.collect.Multimaps.asMap;
-import static com.google.common.collect.Sets.intersection;
-import static dagger.internal.codegen.base.ComponentAnnotation.anyComponentAnnotation;
-import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.creatorAnnotationsFor;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.productionCreatorAnnotations;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.subcomponentCreatorAnnotations;
-import static dagger.internal.codegen.binding.ComponentKind.annotationsFor;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.enclosedAnnotatedTypes;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.getTransitiveModules;
-import static dagger.internal.codegen.binding.ErrorMessages.ComponentCreatorMessages.builderMethodRequiresNoArgs;
-import static dagger.internal.codegen.binding.ErrorMessages.ComponentCreatorMessages.moreThanOneRefToSubcomponent;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
-import static java.util.Comparator.comparing;
-import static javax.lang.model.element.ElementKind.CLASS;
-import static javax.lang.model.element.ElementKind.INTERFACE;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.type.TypeKind.VOID;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
-import dagger.Component;
-import dagger.Reusable;
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.base.ComponentAnnotation;
-import dagger.internal.codegen.binding.ComponentKind;
-import dagger.internal.codegen.binding.DependencyRequestFactory;
-import dagger.internal.codegen.binding.ErrorMessages;
-import dagger.internal.codegen.binding.MethodSignatureFormatter;
-import dagger.internal.codegen.binding.ModuleKind;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.producers.CancellationPolicy;
-import dagger.producers.ProductionComponent;
-import java.lang.annotation.Annotation;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVisitor;
-import javax.lang.model.util.SimpleTypeVisitor8;
-
-/**
- * Performs superficial validation of the contract of the {@link Component} and {@link
- * ProductionComponent} annotations.
- */
-@Singleton
-public final class ComponentValidator implements ClearableCache {
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final ModuleValidator moduleValidator;
-  private final ComponentCreatorValidator creatorValidator;
-  private final DependencyRequestValidator dependencyRequestValidator;
-  private final MembersInjectionValidator membersInjectionValidator;
-  private final MethodSignatureFormatter methodSignatureFormatter;
-  private final DependencyRequestFactory dependencyRequestFactory;
-  private final Map<TypeElement, ValidationReport<TypeElement>> reports = new HashMap<>();
-
-  @Inject
-  ComponentValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      ModuleValidator moduleValidator,
-      ComponentCreatorValidator creatorValidator,
-      DependencyRequestValidator dependencyRequestValidator,
-      MembersInjectionValidator membersInjectionValidator,
-      MethodSignatureFormatter methodSignatureFormatter,
-      DependencyRequestFactory dependencyRequestFactory) {
-    this.elements = elements;
-    this.types = types;
-    this.moduleValidator = moduleValidator;
-    this.creatorValidator = creatorValidator;
-    this.dependencyRequestValidator = dependencyRequestValidator;
-    this.membersInjectionValidator = membersInjectionValidator;
-    this.methodSignatureFormatter = methodSignatureFormatter;
-    this.dependencyRequestFactory = dependencyRequestFactory;
-  }
-
-  @Override
-  public void clearCache() {
-    reports.clear();
-  }
-
-  /** Validates the given component. */
-  public ValidationReport<TypeElement> validate(TypeElement component) {
-    return reentrantComputeIfAbsent(reports, component, this::validateUncached);
-  }
-
-  private ValidationReport<TypeElement> validateUncached(TypeElement component) {
-    return new ElementValidator(component).validateElement();
-  }
-
-  private class ElementValidator {
-    private final TypeElement component;
-    private final ValidationReport.Builder<TypeElement> report;
-    private final ImmutableSet<ComponentKind> componentKinds;
-
-    // Populated by ComponentMethodValidators
-    private final SetMultimap<Element, ExecutableElement> referencedSubcomponents =
-        LinkedHashMultimap.create();
-
-    ElementValidator(TypeElement component) {
-      this.component = component;
-      this.report = ValidationReport.about(component);
-      this.componentKinds = ComponentKind.getComponentKinds(component);
-    }
-
-    private ComponentKind componentKind() {
-      return getOnlyElement(componentKinds);
-    }
-
-    private ComponentAnnotation componentAnnotation() {
-      return anyComponentAnnotation(component).get();
-    }
-
-    private DeclaredType componentType() {
-      return asDeclared(component.asType());
-    }
-
-    ValidationReport<TypeElement> validateElement() {
-      if (componentKinds.size() > 1) {
-        return moreThanOneComponentAnnotation();
-      }
-
-      validateUseOfCancellationPolicy();
-      validateIsAbstractType();
-      validateCreators();
-      validateNoReusableAnnotation();
-      validateComponentMethods();
-      validateNoConflictingEntryPoints();
-      validateSubcomponentReferences();
-      validateComponentDependencies();
-      validateReferencedModules();
-      validateSubcomponents();
-
-      return report.build();
-    }
-
-    private ValidationReport<TypeElement> moreThanOneComponentAnnotation() {
-      String error =
-          "Components may not be annotated with more than one component annotation: found "
-              + annotationsFor(componentKinds);
-      report.addError(error, component);
-      return report.build();
-    }
-
-    private void validateUseOfCancellationPolicy() {
-      if (isAnnotationPresent(component, CancellationPolicy.class)
-          && !componentKind().isProducer()) {
-        report.addError(
-            "@CancellationPolicy may only be applied to production components and subcomponents",
-            component);
-      }
-    }
-
-    private void validateIsAbstractType() {
-      if (!component.getKind().equals(INTERFACE)
-          && !(component.getKind().equals(CLASS) && component.getModifiers().contains(ABSTRACT))) {
-        report.addError(
-            String.format(
-                "@%s may only be applied to an interface or abstract class",
-                componentKind().annotation().getSimpleName()),
-            component);
-      }
-    }
-
-    private void validateCreators() {
-      ImmutableList<DeclaredType> creators =
-          creatorAnnotationsFor(componentAnnotation()).stream()
-              .flatMap(annotation -> enclosedAnnotatedTypes(component, annotation).stream())
-              .collect(toImmutableList());
-      creators.forEach(
-          creator -> report.addSubreport(creatorValidator.validate(asTypeElement(creator))));
-      if (creators.size() > 1) {
-        report.addError(
-            String.format(
-                ErrorMessages.componentMessagesFor(componentKind()).moreThanOne(), creators),
-            component);
-      }
-    }
-
-    private void validateNoReusableAnnotation() {
-      Optional<AnnotationMirror> reusableAnnotation =
-          getAnnotationMirror(component, Reusable.class);
-      if (reusableAnnotation.isPresent()) {
-        report.addError(
-            "@Reusable cannot be applied to components or subcomponents",
-            component,
-            reusableAnnotation.get());
-      }
-    }
-
-    private void validateComponentMethods() {
-      getLocalAndInheritedMethods(component, types, elements).stream()
-          .filter(method -> method.getModifiers().contains(ABSTRACT))
-          .map(ComponentMethodValidator::new)
-          .forEachOrdered(ComponentMethodValidator::validateMethod);
-    }
-
-    private class ComponentMethodValidator {
-      private final ExecutableElement method;
-      private final ExecutableType resolvedMethod;
-      private final List<? extends TypeMirror> parameterTypes;
-      private final List<? extends VariableElement> parameters;
-      private final TypeMirror returnType;
-
-      ComponentMethodValidator(ExecutableElement method) {
-        this.method = method;
-        this.resolvedMethod = asExecutable(types.asMemberOf(componentType(), method));
-        this.parameterTypes = resolvedMethod.getParameterTypes();
-        this.parameters = method.getParameters();
-        this.returnType = resolvedMethod.getReturnType();
-      }
-
-      void validateMethod() {
-        validateNoTypeVariables();
-
-        // abstract methods are ones we have to implement, so they each need to be validated
-        // first, check the return type. if it's a subcomponent, validate that method as
-        // such.
-        Optional<AnnotationMirror> subcomponentAnnotation = subcomponentAnnotation();
-        if (subcomponentAnnotation.isPresent()) {
-          validateSubcomponentFactoryMethod(subcomponentAnnotation.get());
-        } else if (subcomponentCreatorAnnotation().isPresent()) {
-          validateSubcomponentCreatorMethod();
-        } else {
-          // if it's not a subcomponent...
-          switch (parameters.size()) {
-            case 0:
-              validateProvisionMethod();
-              break;
-            case 1:
-              validateMembersInjectionMethod();
-              break;
-            default:
-              reportInvalidMethod();
-              break;
-          }
-        }
-      }
-
-      private void validateNoTypeVariables() {
-        if (!resolvedMethod.getTypeVariables().isEmpty()) {
-          report.addError("Component methods cannot have type variables", method);
-        }
-      }
-
-      private Optional<AnnotationMirror> subcomponentAnnotation() {
-        return checkForAnnotations(
-            returnType,
-            componentKind().legalSubcomponentKinds().stream()
-                .map(ComponentKind::annotation)
-                .collect(toImmutableSet()));
-      }
-
-      private Optional<AnnotationMirror> subcomponentCreatorAnnotation() {
-        return checkForAnnotations(
-            returnType,
-            componentAnnotation().isProduction()
-                ? intersection(subcomponentCreatorAnnotations(), productionCreatorAnnotations())
-                : subcomponentCreatorAnnotations());
-      }
-
-      private void validateSubcomponentFactoryMethod(AnnotationMirror subcomponentAnnotation) {
-        referencedSubcomponents.put(MoreTypes.asElement(returnType), method);
-
-        ComponentKind subcomponentKind =
-            ComponentKind.forAnnotatedElement(MoreTypes.asTypeElement(returnType)).get();
-        ImmutableSet<TypeElement> moduleTypes =
-            ComponentAnnotation.componentAnnotation(subcomponentAnnotation).modules();
-
-        // TODO(gak): This logic maybe/probably shouldn't live here as it requires us to traverse
-        // subcomponents and their modules separately from how it is done in ComponentDescriptor and
-        // ModuleDescriptor
-        @SuppressWarnings("deprecation")
-        ImmutableSet<TypeElement> transitiveModules =
-            getTransitiveModules(types, elements, moduleTypes);
-
-        Set<TypeElement> variableTypes = Sets.newHashSet();
-
-        for (int i = 0; i < parameterTypes.size(); i++) {
-          VariableElement parameter = parameters.get(i);
-          TypeMirror parameterType = parameterTypes.get(i);
-          Optional<TypeElement> moduleType =
-              parameterType.accept(
-                  new SimpleTypeVisitor8<Optional<TypeElement>, Void>() {
-                    @Override
-                    protected Optional<TypeElement> defaultAction(TypeMirror e, Void p) {
-                      return Optional.empty();
-                    }
-
-                    @Override
-                    public Optional<TypeElement> visitDeclared(DeclaredType t, Void p) {
-                      for (ModuleKind moduleKind : subcomponentKind.legalModuleKinds()) {
-                        if (isAnnotationPresent(t.asElement(), moduleKind.annotation())) {
-                          return Optional.of(MoreTypes.asTypeElement(t));
-                        }
-                      }
-                      return Optional.empty();
-                    }
-                  },
-                  null);
-          if (moduleType.isPresent()) {
-            if (variableTypes.contains(moduleType.get())) {
-              report.addError(
-                  String.format(
-                      "A module may only occur once an an argument in a Subcomponent factory "
-                          + "method, but %s was already passed.",
-                      moduleType.get().getQualifiedName()),
-                  parameter);
-            }
-            if (!transitiveModules.contains(moduleType.get())) {
-              report.addError(
-                  String.format(
-                      "%s is present as an argument to the %s factory method, but is not one of the"
-                          + " modules used to implement the subcomponent.",
-                      moduleType.get().getQualifiedName(),
-                      MoreTypes.asTypeElement(returnType).getQualifiedName()),
-                  method);
-            }
-            variableTypes.add(moduleType.get());
-          } else {
-            report.addError(
-                String.format(
-                    "Subcomponent factory methods may only accept modules, but %s is not.",
-                    parameterType),
-                parameter);
-          }
-        }
-      }
-
-      private void validateSubcomponentCreatorMethod() {
-        referencedSubcomponents.put(MoreTypes.asElement(returnType).getEnclosingElement(), method);
-
-        if (!parameters.isEmpty()) {
-          report.addError(builderMethodRequiresNoArgs(), method);
-        }
-
-        TypeElement creatorElement = MoreTypes.asTypeElement(returnType);
-        // TODO(sameb): The creator validator right now assumes the element is being compiled
-        // in this pass, which isn't true here.  We should change error messages to spit out
-        // this method as the subject and add the original subject to the message output.
-        report.addSubreport(creatorValidator.validate(creatorElement));
-      }
-
-      private void validateProvisionMethod() {
-        dependencyRequestValidator.validateDependencyRequest(report, method, returnType);
-      }
-
-      private void validateMembersInjectionMethod() {
-        TypeMirror parameterType = getOnlyElement(parameterTypes);
-        report.addSubreport(
-            membersInjectionValidator.validateMembersInjectionMethod(method, parameterType));
-        if (!(returnType.getKind().equals(VOID) || types.isSameType(returnType, parameterType))) {
-          report.addError(
-              "Members injection methods may only return the injected type or void.", method);
-        }
-      }
-
-      private void reportInvalidMethod() {
-        report.addError(
-            "This method isn't a valid provision method, members injection method or "
-                + "subcomponent factory method. Dagger cannot implement this method",
-            method);
-      }
-    }
-
-    private void validateNoConflictingEntryPoints() {
-      // Collect entry point methods that are not overridden by others. If the "same" method is
-      // inherited from more than one supertype, each will be in the multimap.
-      SetMultimap<String, ExecutableElement> entryPointMethods = HashMultimap.create();
-
-      methodsIn(elements.getAllMembers(component)).stream()
-          .filter(
-              method ->
-                  isEntryPoint(method, asExecutable(types.asMemberOf(componentType(), method))))
-          .forEach(
-              method ->
-                  addMethodUnlessOverridden(
-                      method, entryPointMethods.get(method.getSimpleName().toString())));
-
-      for (Set<ExecutableElement> methods : asMap(entryPointMethods).values()) {
-        if (distinctKeys(methods).size() > 1) {
-          reportConflictingEntryPoints(methods);
-        }
-      }
-    }
-
-    private void reportConflictingEntryPoints(Collection<ExecutableElement> methods) {
-      verify(
-          methods.stream().map(ExecutableElement::getEnclosingElement).distinct().count()
-              == methods.size(),
-          "expected each method to be declared on a different type: %s",
-          methods);
-      StringBuilder message = new StringBuilder("conflicting entry point declarations:");
-      methodSignatureFormatter
-          .typedFormatter(componentType())
-          .formatIndentedList(
-              message,
-              ImmutableList.sortedCopyOf(
-                  comparing(
-                      method -> asType(method.getEnclosingElement()).getQualifiedName().toString()),
-                  methods),
-              1);
-      report.addError(message.toString());
-    }
-
-    private void validateSubcomponentReferences() {
-      Maps.filterValues(referencedSubcomponents.asMap(), methods -> methods.size() > 1)
-          .forEach(
-              (subcomponent, methods) ->
-                  report.addError(
-                      String.format(moreThanOneRefToSubcomponent(), subcomponent, methods),
-                      component));
-    }
-
-    private void validateComponentDependencies() {
-      for (TypeMirror type : componentAnnotation().dependencyTypes()) {
-        type.accept(CHECK_DEPENDENCY_TYPES, report);
-      }
-    }
-
-    private void validateReferencedModules() {
-      report.addSubreport(
-          moduleValidator.validateReferencedModules(
-              component,
-              componentAnnotation().annotation(),
-              componentKind().legalModuleKinds(),
-              new HashSet<>()));
-    }
-
-    private void validateSubcomponents() {
-      // Make sure we validate any subcomponents we're referencing.
-      for (Element subcomponent : referencedSubcomponents.keySet()) {
-        ValidationReport<TypeElement> subreport = validate(asType(subcomponent));
-        report.addSubreport(subreport);
-      }
-    }
-
-    private ImmutableSet<Key> distinctKeys(Set<ExecutableElement> methods) {
-      return methods.stream()
-          .map(this::dependencyRequest)
-          .map(DependencyRequest::key)
-          .collect(toImmutableSet());
-    }
-
-    private DependencyRequest dependencyRequest(ExecutableElement method) {
-      ExecutableType methodType = asExecutable(types.asMemberOf(componentType(), method));
-      return ComponentKind.forAnnotatedElement(component).get().isProducer()
-          ? dependencyRequestFactory.forComponentProductionMethod(method, methodType)
-          : dependencyRequestFactory.forComponentProvisionMethod(method, methodType);
-    }
-  }
-
-  private static boolean isEntryPoint(ExecutableElement method, ExecutableType methodType) {
-    return method.getModifiers().contains(ABSTRACT)
-        && method.getParameters().isEmpty()
-        && !methodType.getReturnType().getKind().equals(VOID)
-        && methodType.getTypeVariables().isEmpty();
-  }
-
-  private void addMethodUnlessOverridden(ExecutableElement method, Set<ExecutableElement> methods) {
-    if (methods.stream().noneMatch(existingMethod -> overridesAsDeclared(existingMethod, method))) {
-      methods.removeIf(existingMethod -> overridesAsDeclared(method, existingMethod));
-      methods.add(method);
-    }
-  }
-
-  /**
-   * Returns {@code true} if {@code overrider} overrides {@code overridden} considered from within
-   * the type that declares {@code overrider}.
-   */
-  // TODO(dpb): Does this break for ECJ?
-  private boolean overridesAsDeclared(ExecutableElement overrider, ExecutableElement overridden) {
-    return elements.overrides(overrider, overridden, asType(overrider.getEnclosingElement()));
-  }
-
-  private static final TypeVisitor<Void, ValidationReport.Builder<?>> CHECK_DEPENDENCY_TYPES =
-      new SimpleTypeVisitor8<Void, ValidationReport.Builder<?>>() {
-        @Override
-        protected Void defaultAction(TypeMirror type, ValidationReport.Builder<?> report) {
-          report.addError(type + " is not a valid component dependency type");
-          return null;
-        }
-
-        @Override
-        public Void visitDeclared(DeclaredType type, ValidationReport.Builder<?> report) {
-          if (moduleAnnotation(MoreTypes.asTypeElement(type)).isPresent()) {
-            report.addError(type + " is a module, which cannot be a component dependency");
-          }
-          return null;
-        }
-      };
-
-  private static Optional<AnnotationMirror> checkForAnnotations(
-      TypeMirror type, final Set<? extends Class<? extends Annotation>> annotations) {
-    return type.accept(
-        new SimpleTypeVisitor8<Optional<AnnotationMirror>, Void>(Optional.empty()) {
-          @Override
-          public Optional<AnnotationMirror> visitDeclared(DeclaredType t, Void p) {
-            return getAnyAnnotation(t.asElement(), annotations);
-          }
-        },
-        null);
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/CompositeBindingGraphPlugin.java b/java/dagger/internal/codegen/validation/CompositeBindingGraphPlugin.java
deleted file mode 100644
index a9c650a..0000000
--- a/java/dagger/internal/codegen/validation/CompositeBindingGraphPlugin.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2019 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.validation;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Lists.asList;
-import static dagger.internal.codegen.base.ElementFormatter.elementToString;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.elementEncloses;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.errorprone.annotations.FormatMethod;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.ChildFactoryMethodEdge;
-import dagger.model.BindingGraph.ComponentNode;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.BindingGraph.MaybeBinding;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.util.Elements;  // ALLOW_TYPES_ELEMENTS because of interface dependencies
-import javax.lang.model.util.Types;  // ALLOW_TYPES_ELEMENTS because of interface dependencies
-import javax.tools.Diagnostic;
-
-/**
- * Combines many {@link BindingGraphPlugin} implementations. This helps reduce spam by combining
- * all of the messages that are reported on the root component.
- */
-public final class CompositeBindingGraphPlugin implements BindingGraphPlugin {
-
-  private final ImmutableSet<BindingGraphPlugin> plugins;
-  private final String pluginName;
-  private final DiagnosticMessageGenerator.Factory messageGeneratorFactory;
-
-  /** Factory class for {@link CompositeBindingGraphPlugin}. */
-  public static final class Factory {
-    private final DiagnosticMessageGenerator.Factory messageGeneratorFactory;
-
-    @Inject Factory(DiagnosticMessageGenerator.Factory messageGeneratorFactory) {
-      this.messageGeneratorFactory = messageGeneratorFactory;
-    }
-
-    public CompositeBindingGraphPlugin create(
-        ImmutableSet<BindingGraphPlugin> plugins, String pluginName) {
-      return new CompositeBindingGraphPlugin(plugins, pluginName, messageGeneratorFactory);
-    }
-  }
-
-  private CompositeBindingGraphPlugin(
-      ImmutableSet<BindingGraphPlugin> plugins,
-      String pluginName,
-      DiagnosticMessageGenerator.Factory messageGeneratorFactory) {
-    this.plugins = plugins;
-    this.pluginName = pluginName;
-    this.messageGeneratorFactory = messageGeneratorFactory;
-  }
-
-  @Override
-  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-    AggregatingDiagnosticReporter aggregatingDiagnosticReporter = new AggregatingDiagnosticReporter(
-        bindingGraph, diagnosticReporter, messageGeneratorFactory.create(bindingGraph));
-    plugins.forEach(plugin -> {
-      aggregatingDiagnosticReporter.setCurrentPlugin(plugin.pluginName());
-      plugin.visitGraph(bindingGraph, aggregatingDiagnosticReporter);
-    });
-    aggregatingDiagnosticReporter.report();
-  }
-
-  @Override
-  public void initFiler(Filer filer) {
-    plugins.forEach(plugin -> plugin.initFiler(filer));
-  }
-
-  @Override
-  public void initTypes(Types types) {
-    plugins.forEach(plugin -> plugin.initTypes(types));
-  }
-
-  @Override
-  public void initElements(Elements elements) {
-    plugins.forEach(plugin -> plugin.initElements(elements));
-  }
-
-  @Override
-  public void initOptions(Map<String, String> options) {
-    plugins.forEach(plugin -> plugin.initOptions(options));
-  }
-
-  @Override
-  public Set<String> supportedOptions() {
-    return plugins.stream().flatMap(
-        plugin -> plugin.supportedOptions().stream()).collect(toImmutableSet());
-  }
-
-  @Override
-  public String pluginName() {
-    return pluginName;
-  }
-
-  // TODO(erichang): This kind of breaks some of the encapsulation by relying on or repeating
-  // logic within DiagnosticReporterImpl. Hopefully if the experiment for aggregated messages
-  // goes well though this can be merged with that implementation.
-  private static final class AggregatingDiagnosticReporter implements DiagnosticReporter {
-    private final DiagnosticReporter delegate;
-    private final BindingGraph graph;
-    // Initialize with a new line so the first message appears below the reported component
-    private final StringBuilder messageBuilder = new StringBuilder("\n");
-    private final DiagnosticMessageGenerator messageGenerator;
-    private Optional<Diagnostic.Kind> mergedDiagnosticKind = Optional.empty();
-    private String currentPluginName = null;
-
-    AggregatingDiagnosticReporter(
-        BindingGraph graph,
-        DiagnosticReporter delegate,
-        DiagnosticMessageGenerator messageGenerator) {
-      this.graph = graph;
-      this.delegate = delegate;
-      this.messageGenerator = messageGenerator;
-    }
-
-    /** Sets the currently running aggregated plugin. Used to add a diagnostic prefix. */
-    void setCurrentPlugin(String pluginName) {
-      currentPluginName = pluginName;
-    }
-
-    /** Reports all of the stored diagnostics. */
-    void report() {
-      if (mergedDiagnosticKind.isPresent()) {
-        delegate.reportComponent(
-            mergedDiagnosticKind.get(),
-            graph.rootComponentNode(),
-            PackageNameCompressor.compressPackagesInMessage(messageBuilder.toString()));
-      }
-    }
-
-    @Override
-    public void reportComponent(Diagnostic.Kind diagnosticKind, ComponentNode componentNode,
-        String message) {
-      addMessage(diagnosticKind, message);
-      messageGenerator.appendComponentPathUnlessAtRoot(messageBuilder, componentNode);
-    }
-
-    @Override
-    @FormatMethod
-    public void reportComponent(
-        Diagnostic.Kind diagnosticKind,
-        ComponentNode componentNode,
-        String messageFormat,
-        Object firstArg,
-        Object... moreArgs) {
-      reportComponent(
-          diagnosticKind, componentNode, formatMessage(messageFormat, firstArg, moreArgs));
-    }
-
-    @Override
-    public void reportBinding(Diagnostic.Kind diagnosticKind, MaybeBinding binding,
-        String message) {
-      addMessage(diagnosticKind,
-          String.format("%s%s", message, messageGenerator.getMessage(binding)));
-    }
-
-    @Override
-    @FormatMethod
-    public void reportBinding(
-        Diagnostic.Kind diagnosticKind,
-        MaybeBinding binding,
-        String messageFormat,
-        Object firstArg,
-        Object... moreArgs) {
-      reportBinding(diagnosticKind, binding, formatMessage(messageFormat, firstArg, moreArgs));
-    }
-
-    @Override
-    public void reportDependency(
-        Diagnostic.Kind diagnosticKind, DependencyEdge dependencyEdge, String message) {
-      addMessage(diagnosticKind,
-          String.format("%s%s", message, messageGenerator.getMessage(dependencyEdge)));
-    }
-
-    @Override
-    @FormatMethod
-    public void reportDependency(
-        Diagnostic.Kind diagnosticKind,
-        DependencyEdge dependencyEdge,
-        String messageFormat,
-        Object firstArg,
-        Object... moreArgs) {
-      reportDependency(
-          diagnosticKind, dependencyEdge, formatMessage(messageFormat, firstArg, moreArgs));
-    }
-
-    @Override
-    public void reportSubcomponentFactoryMethod(
-        Diagnostic.Kind diagnosticKind,
-        ChildFactoryMethodEdge childFactoryMethodEdge,
-        String message) {
-      // TODO(erichang): This repeats some of the logic in DiagnosticReporterImpl. Remove when
-      // merged.
-      if (elementEncloses(
-          graph.rootComponentNode().componentPath().currentComponent(),
-          childFactoryMethodEdge.factoryMethod())) {
-        // Let this pass through since it is not an error reported on the root component
-        delegate.reportSubcomponentFactoryMethod(diagnosticKind, childFactoryMethodEdge, message);
-      } else {
-        addMessage(
-            diagnosticKind,
-            String.format(
-                "[%s] %s", elementToString(childFactoryMethodEdge.factoryMethod()), message));
-      }
-    }
-
-    @Override
-    @FormatMethod
-    public void reportSubcomponentFactoryMethod(
-        Diagnostic.Kind diagnosticKind,
-        ChildFactoryMethodEdge childFactoryMethodEdge,
-        String messageFormat,
-        Object firstArg,
-        Object... moreArgs) {
-      reportSubcomponentFactoryMethod(
-          diagnosticKind, childFactoryMethodEdge, formatMessage(messageFormat, firstArg, moreArgs));
-    }
-
-    /** Adds a message to the stored aggregated message. */
-    private void addMessage(Diagnostic.Kind diagnosticKind, String message) {
-      checkNotNull(diagnosticKind);
-      checkNotNull(message);
-      checkState(currentPluginName != null);
-
-      // Add a separator if this isn't the first message
-      if (mergedDiagnosticKind.isPresent()) {
-        messageBuilder.append("\n\n");
-      }
-
-      mergeDiagnosticKind(diagnosticKind);
-      // Adds brackets as well as special color strings to make the string red and bold.
-      messageBuilder.append(String.format("\033[1;31m[%s]\033[0m ", currentPluginName));
-      messageBuilder.append(message);
-    }
-
-    private static String formatMessage(String messageFormat, Object firstArg, Object[] moreArgs) {
-      return String.format(messageFormat, asList(firstArg, moreArgs).toArray());
-    }
-
-    private void mergeDiagnosticKind(Diagnostic.Kind diagnosticKind) {
-      checkArgument(diagnosticKind != Diagnostic.Kind.MANDATORY_WARNING,
-          "Dagger plugins should not be issuing mandatory warnings");
-      if (!mergedDiagnosticKind.isPresent()) {
-        mergedDiagnosticKind = Optional.of(diagnosticKind);
-        return;
-      }
-      Diagnostic.Kind current = mergedDiagnosticKind.get();
-      if (current == Diagnostic.Kind.ERROR || diagnosticKind == Diagnostic.Kind.ERROR) {
-        mergedDiagnosticKind = Optional.of(Diagnostic.Kind.ERROR);
-      } else if (current == Diagnostic.Kind.WARNING || diagnosticKind == Diagnostic.Kind.WARNING) {
-        mergedDiagnosticKind = Optional.of(Diagnostic.Kind.WARNING);
-      } else if (current == Diagnostic.Kind.NOTE || diagnosticKind == Diagnostic.Kind.NOTE) {
-        mergedDiagnosticKind = Optional.of(Diagnostic.Kind.NOTE);
-      } else {
-        mergedDiagnosticKind = Optional.of(Diagnostic.Kind.OTHER);
-      }
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/DependencyRequestValidator.java b/java/dagger/internal/codegen/validation/DependencyRequestValidator.java
deleted file mode 100644
index 68c9604..0000000
--- a/java/dagger/internal/codegen/validation/DependencyRequestValidator.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.validation;
-
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreElements.asVariable;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static dagger.internal.codegen.base.RequestKinds.extractKeyType;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedFactoryType;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedInjectionType;
-import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.type.TypeKind.WILDCARD;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableCollection;
-import dagger.MembersInjector;
-import dagger.assisted.Assisted;
-import dagger.internal.codegen.base.FrameworkTypes;
-import dagger.internal.codegen.base.RequestKinds;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.model.RequestKind;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-
-/** Validation for dependency requests. */
-final class DependencyRequestValidator {
-  private final MembersInjectionValidator membersInjectionValidator;
-  private final InjectionAnnotations injectionAnnotations;
-  private final KotlinMetadataUtil metadataUtil;
-  private final DaggerElements elements;
-
-  @Inject
-  DependencyRequestValidator(
-      MembersInjectionValidator membersInjectionValidator,
-      InjectionAnnotations injectionAnnotations,
-      KotlinMetadataUtil metadataUtil,
-      DaggerElements elements) {
-    this.membersInjectionValidator = membersInjectionValidator;
-    this.injectionAnnotations = injectionAnnotations;
-    this.metadataUtil = metadataUtil;
-    this.elements = elements;
-  }
-
-  /**
-   * Adds an error if the given dependency request has more than one qualifier annotation or is a
-   * non-instance request with a wildcard type.
-   */
-  void validateDependencyRequest(
-      ValidationReport.Builder<?> report, Element requestElement, TypeMirror requestType) {
-    if (MoreElements.isAnnotationPresent(requestElement, Assisted.class)) {
-      // Don't validate assisted parameters. These are not dependency requests.
-      return;
-    }
-    checkQualifiers(report, requestElement);
-    checkType(report, requestElement, requestType);
-  }
-
-  private void checkQualifiers(ValidationReport.Builder<?> report, Element requestElement) {
-    if (requestElement.getKind() == ElementKind.FIELD
-        // static injected fields are not supported, no need to get qualifier from kotlin metadata
-        && !requestElement.getModifiers().contains(STATIC)
-        && metadataUtil.hasMetadata(requestElement)
-        && metadataUtil.isMissingSyntheticPropertyForAnnotations(asVariable(requestElement))) {
-      Optional<TypeElement> membersInjector =
-          Optional.ofNullable(
-              elements.getTypeElement(
-                  membersInjectorNameForType(asType(requestElement.getEnclosingElement()))));
-      if (!membersInjector.isPresent()) {
-        report.addError(
-            "Unable to read annotations on an injected Kotlin property. The Dagger compiler must"
-                + " also be applied to any project containing @Inject properties.",
-            requestElement);
-        return; // finish checking qualifiers since current information is unreliable.
-      }
-    }
-
-    ImmutableCollection<? extends AnnotationMirror> qualifiers =
-        injectionAnnotations.getQualifiers(requestElement);
-    if (qualifiers.size() > 1) {
-      for (AnnotationMirror qualifier : qualifiers) {
-        report.addError(
-            "A single dependency request may not use more than one @Qualifier",
-            requestElement,
-            qualifier);
-      }
-    }
-  }
-
-  private void checkType(
-      ValidationReport.Builder<?> report, Element requestElement, TypeMirror requestType) {
-    TypeMirror keyType = extractKeyType(requestType);
-    RequestKind requestKind = RequestKinds.getRequestKind(requestType);
-    if (keyType.getKind() == TypeKind.DECLARED) {
-      TypeElement typeElement = asTypeElement(keyType);
-      if (isAssistedInjectionType(typeElement)) {
-        report.addError(
-            "Dagger does not support injecting @AssistedInject type, "
-                + requestType
-                + ". Did you mean to inject its assisted factory type instead?",
-            requestElement);
-      }
-      if (requestKind != RequestKind.INSTANCE && isAssistedFactoryType(typeElement)) {
-        report.addError(
-            "Dagger does not support injecting Provider<T>, Lazy<T>, Producer<T>, "
-                + "or Produced<T> when T is an @AssistedFactory-annotated type such as "
-                + keyType,
-            requestElement);
-      }
-    }
-    if (keyType.getKind().equals(WILDCARD)) {
-      // TODO(ronshapiro): Explore creating this message using RequestKinds.
-      report.addError(
-          "Dagger does not support injecting Provider<T>, Lazy<T>, Producer<T>, "
-              + "or Produced<T> when T is a wildcard type such as "
-              + keyType,
-          requestElement);
-    }
-    if (MoreTypes.isType(keyType) && MoreTypes.isTypeOf(MembersInjector.class, keyType)) {
-      DeclaredType membersInjectorType = MoreTypes.asDeclared(keyType);
-      if (membersInjectorType.getTypeArguments().isEmpty()) {
-        report.addError("Cannot inject a raw MembersInjector", requestElement);
-      } else {
-        report.addSubreport(
-            membersInjectionValidator.validateMembersInjectionRequest(
-                requestElement, membersInjectorType.getTypeArguments().get(0)));
-      }
-    }
-  }
-
-  /**
-   * Adds an error if the given dependency request is for a {@link dagger.producers.Producer} or
-   * {@link dagger.producers.Produced}.
-   *
-   * <p>Only call this when processing a provision binding.
-   */
-  // TODO(dpb): Should we disallow Producer entry points in non-production components?
-  void checkNotProducer(ValidationReport.Builder<?> report, VariableElement requestElement) {
-    TypeMirror requestType = requestElement.asType();
-    if (FrameworkTypes.isProducerType(requestType)) {
-      report.addError(
-          String.format(
-              "%s may only be injected in @Produces methods",
-              MoreTypes.asTypeElement(requestType).getSimpleName()),
-          requestElement);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/DiagnosticMessageGenerator.java b/java/dagger/internal/codegen/validation/DiagnosticMessageGenerator.java
deleted file mode 100644
index 7d7b9e3..0000000
--- a/java/dagger/internal/codegen/validation/DiagnosticMessageGenerator.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * 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.validation;
-
-import static com.google.common.base.Predicates.equalTo;
-import static com.google.common.base.Verify.verify;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.getLast;
-import static com.google.common.collect.Iterables.indexOf;
-import static com.google.common.collect.Iterables.transform;
-import static dagger.internal.codegen.base.ElementFormatter.elementToString;
-import static dagger.internal.codegen.extension.DaggerGraphs.shortestPath;
-import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static dagger.internal.codegen.extension.DaggerStreams.presentValues;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.DECLARATION_ORDER;
-import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
-import static java.util.Collections.min;
-import static java.util.Comparator.comparing;
-import static java.util.Comparator.comparingInt;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Table;
-import dagger.internal.codegen.base.ElementFormatter;
-import dagger.internal.codegen.base.Formatter;
-import dagger.internal.codegen.binding.DependencyRequestFormatter;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.BindingGraph.Edge;
-import dagger.model.BindingGraph.MaybeBinding;
-import dagger.model.BindingGraph.Node;
-import dagger.model.ComponentPath;
-import java.util.Comparator;
-import java.util.Set;
-import java.util.function.Function;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-/** Helper class for generating diagnostic messages. */
-public final class DiagnosticMessageGenerator {
-
-  /** Injectable factory for {@code DiagnosticMessageGenerator}. */
-  public static final class Factory {
-    private final DaggerTypes types;
-    private final DependencyRequestFormatter dependencyRequestFormatter;
-    private final ElementFormatter elementFormatter;
-
-    @Inject
-    Factory(
-        DaggerTypes types,
-        DependencyRequestFormatter dependencyRequestFormatter,
-        ElementFormatter elementFormatter) {
-      this.types = types;
-      this.dependencyRequestFormatter = dependencyRequestFormatter;
-      this.elementFormatter = elementFormatter;
-    }
-
-    /** Creates a {@code DiagnosticMessageGenerator} for the given binding graph. */
-    public DiagnosticMessageGenerator create(BindingGraph graph) {
-      return new DiagnosticMessageGenerator(
-          graph, types, dependencyRequestFormatter, elementFormatter);
-    }
-  }
-
-  private final BindingGraph graph;
-  private final DependencyRequestFormatter dependencyRequestFormatter;
-  private final ElementFormatter elementFormatter;
-
-  /** A cached function from type to all of its supertypes in breadth-first order. */
-  private final Function<TypeElement, Iterable<TypeElement>> supertypes;
-
-  /** The shortest path (value) from an entry point (column) to a binding (row). */
-  private final Table<MaybeBinding, DependencyEdge, ImmutableList<Node>> shortestPaths =
-      HashBasedTable.create();
-
-  private static <K, V> Function<K, V> memoize(Function<K, V> uncached) {
-    // If Android Guava is on the processor path, then c.g.c.b.Function (which LoadingCache
-    // implements) does not extend j.u.f.Function.
-    // TODO(erichang): Fix current breakages and try to remove this to enforce not having this on
-    // processor path.
-
-    // First, explicitly convert uncached to c.g.c.b.Function because CacheLoader.from() expects
-    // one.
-    com.google.common.base.Function<K, V> uncachedAsBaseFunction = uncached::apply;
-
-    LoadingCache<K, V> cache =
-        CacheBuilder.newBuilder().build(CacheLoader.from(uncachedAsBaseFunction));
-
-    // Second, explicitly convert LoadingCache to j.u.f.Function.
-    @SuppressWarnings("deprecation") // uncachedAsBaseFunction throws only unchecked exceptions
-    Function<K, V> memoized = cache::apply;
-
-    return memoized;
-  }
-
-  private DiagnosticMessageGenerator(
-      BindingGraph graph,
-      DaggerTypes types,
-      DependencyRequestFormatter dependencyRequestFormatter,
-      ElementFormatter elementFormatter) {
-    this.graph = graph;
-    this.dependencyRequestFormatter = dependencyRequestFormatter;
-    this.elementFormatter = elementFormatter;
-    supertypes =
-        memoize(
-            component -> transform(types.supertypes(component.asType()), MoreTypes::asTypeElement));
-  }
-
-  public String getMessage(MaybeBinding binding) {
-    ImmutableSet<DependencyEdge> entryPoints = graph.entryPointEdgesDependingOnBinding(binding);
-    ImmutableSet<DependencyEdge> requests = requests(binding);
-    ImmutableList<DependencyEdge> dependencyTrace = dependencyTrace(binding, entryPoints);
-
-    return getMessageInternal(dependencyTrace, requests, entryPoints);
-  }
-
-  public String getMessage(DependencyEdge dependencyEdge) {
-    ImmutableSet<DependencyEdge> requests = ImmutableSet.of(dependencyEdge);
-
-    ImmutableSet<DependencyEdge> entryPoints;
-    ImmutableList<DependencyEdge> dependencyTrace;
-    if (dependencyEdge.isEntryPoint()) {
-      entryPoints = ImmutableSet.of(dependencyEdge);
-      dependencyTrace = ImmutableList.of(dependencyEdge);
-    } else {
-      // It's not an entry point, so it's part of a binding
-      dagger.model.Binding binding = (dagger.model.Binding) source(dependencyEdge);
-      entryPoints = graph.entryPointEdgesDependingOnBinding(binding);
-      dependencyTrace =
-          ImmutableList.<DependencyEdge>builder()
-              .add(dependencyEdge)
-              .addAll(dependencyTrace(binding, entryPoints))
-              .build();
-    }
-
-    return getMessageInternal(dependencyTrace, requests, entryPoints);
-  }
-
-  private String getMessageInternal(
-      ImmutableList<DependencyEdge> dependencyTrace,
-      ImmutableSet<DependencyEdge> requests,
-      ImmutableSet<DependencyEdge> entryPoints) {
-    StringBuilder message =
-        graph.isFullBindingGraph()
-            ? new StringBuilder()
-            : new StringBuilder(dependencyTrace.size() * 100 /* a guess heuristic */);
-
-    // Print the dependency trace unless it's a full binding graph
-    if (!graph.isFullBindingGraph()) {
-      dependencyTrace.forEach(
-          edge -> dependencyRequestFormatter.appendFormatLine(message, edge.dependencyRequest()));
-      if (!dependencyTrace.isEmpty()) {
-        appendComponentPathUnlessAtRoot(message, source(getLast(dependencyTrace)));
-      }
-    }
-
-    // Print any dependency requests that aren't shown as part of the dependency trace.
-    ImmutableSet<Element> requestsToPrint =
-        requests.stream()
-            // if printing entry points, skip entry points and the traced request
-            .filter(
-                request ->
-                    graph.isFullBindingGraph()
-                        || (!request.isEntryPoint() && !isTracedRequest(dependencyTrace, request)))
-            .map(request -> request.dependencyRequest().requestElement())
-            .flatMap(presentValues())
-            .collect(toImmutableSet());
-    if (!requestsToPrint.isEmpty()) {
-      message
-          .append("\nIt is")
-          .append(graph.isFullBindingGraph() ? " " : " also ")
-          .append("requested at:");
-      elementFormatter.formatIndentedList(message, requestsToPrint, 1);
-    }
-
-    // Print the remaining entry points, showing which component they're in, unless it's a full
-    // binding graph
-    if (!graph.isFullBindingGraph() && entryPoints.size() > 1) {
-      message.append("\nThe following other entry points also depend on it:");
-      entryPointFormatter.formatIndentedList(
-          message,
-          entryPoints.stream()
-              .filter(entryPoint -> !entryPoint.equals(getLast(dependencyTrace)))
-              .sorted(
-                  // 1. List entry points in components closest to the root first.
-                  // 2. List entry points declared in a component before those in a supertype.
-                  // 3. List entry points in declaration order in their declaring type.
-                  rootComponentFirst()
-                      .thenComparing(nearestComponentSupertypeFirst())
-                      .thenComparing(requestElementDeclarationOrder()))
-              .collect(toImmutableList()),
-          1);
-    }
-    return message.toString();
-  }
-
-  public void appendComponentPathUnlessAtRoot(StringBuilder message, Node node) {
-    if (!node.componentPath().equals(graph.rootComponentNode().componentPath())) {
-      message.append(String.format(" [%s]", node.componentPath()));
-    }
-  }
-
-  private final Formatter<DependencyEdge> entryPointFormatter =
-      new Formatter<DependencyEdge>() {
-        @Override
-        public String format(DependencyEdge object) {
-          Element requestElement = object.dependencyRequest().requestElement().get();
-          StringBuilder element = new StringBuilder(elementToString(requestElement));
-
-          // For entry points declared in subcomponents or supertypes of the root component,
-          // append the component path to make clear to the user which component it's in.
-          ComponentPath componentPath = source(object).componentPath();
-          if (!componentPath.atRoot()
-              || !requestElement.getEnclosingElement().equals(componentPath.rootComponent())) {
-            element.append(String.format(" [%s]", componentPath));
-          }
-          return element.toString();
-        }
-      };
-
-  private static boolean isTracedRequest(
-      ImmutableList<DependencyEdge> dependencyTrace, DependencyEdge request) {
-    return !dependencyTrace.isEmpty() && request.equals(dependencyTrace.get(0));
-  }
-
-  /**
-   * Returns the dependency trace from one of the {@code entryPoints} to {@code binding} to {@code
-   * message} as a list <i>ending with</i> the entry point.
-   */
-  // TODO(ronshapiro): Adding a DependencyPath type to dagger.model could be useful, i.e.
-  // bindingGraph.shortestPathFromEntryPoint(DependencyEdge, MaybeBindingNode)
-  ImmutableList<DependencyEdge> dependencyTrace(
-      MaybeBinding binding, ImmutableSet<DependencyEdge> entryPoints) {
-    // Module binding graphs may have bindings unreachable from any entry points. If there are
-    // no entry points for this DiagnosticInfo, don't try to print a dependency trace.
-    if (entryPoints.isEmpty()) {
-      return ImmutableList.of();
-    }
-    // Show the full dependency trace for one entry point.
-    DependencyEdge entryPointForTrace =
-        min(
-            entryPoints,
-            // prefer entry points in components closest to the root
-            rootComponentFirst()
-                // then prefer entry points with a short dependency path to the error
-                .thenComparing(shortestDependencyPathFirst(binding))
-                // then prefer entry points declared in the component to those declared in a
-                // supertype
-                .thenComparing(nearestComponentSupertypeFirst())
-                // finally prefer entry points declared first in their enclosing type
-                .thenComparing(requestElementDeclarationOrder()));
-
-    ImmutableList<Node> shortestBindingPath =
-        shortestPathFromEntryPoint(entryPointForTrace, binding);
-    verify(
-        !shortestBindingPath.isEmpty(),
-        "no dependency path from %s to %s in %s",
-        entryPointForTrace,
-        binding,
-        graph);
-
-    ImmutableList.Builder<DependencyEdge> dependencyTrace = ImmutableList.builder();
-    dependencyTrace.add(entryPointForTrace);
-    for (int i = 0; i < shortestBindingPath.size() - 1; i++) {
-      Set<Edge> dependenciesBetween =
-          graph
-              .network()
-              .edgesConnecting(shortestBindingPath.get(i), shortestBindingPath.get(i + 1));
-      // If a binding requests a key more than once, any of them should be fine to get to the
-      // shortest path
-      dependencyTrace.add((DependencyEdge) Iterables.get(dependenciesBetween, 0));
-    }
-    return dependencyTrace.build().reverse();
-  }
-
-  /** Returns all the nonsynthetic dependency requests for a binding. */
-  ImmutableSet<DependencyEdge> requests(MaybeBinding binding) {
-    return graph.network().inEdges(binding).stream()
-        .flatMap(instancesOf(DependencyEdge.class))
-        .filter(edge -> edge.dependencyRequest().requestElement().isPresent())
-        .sorted(requestEnclosingTypeName().thenComparing(requestElementDeclarationOrder()))
-        .collect(toImmutableSet());
-  }
-
-  /**
-   * Returns a comparator that sorts entry points in components whose paths from the root are
-   * shorter first.
-   */
-  Comparator<DependencyEdge> rootComponentFirst() {
-    return comparingInt(entryPoint -> source(entryPoint).componentPath().components().size());
-  }
-
-  /**
-   * Returns a comparator that puts entry points whose shortest dependency path to {@code binding}
-   * is shortest first.
-   */
-  Comparator<DependencyEdge> shortestDependencyPathFirst(MaybeBinding binding) {
-    return comparing(entryPoint -> shortestPathFromEntryPoint(entryPoint, binding).size());
-  }
-
-  ImmutableList<Node> shortestPathFromEntryPoint(DependencyEdge entryPoint, MaybeBinding binding) {
-    return shortestPaths
-        .row(binding)
-        .computeIfAbsent(
-            entryPoint,
-            ep ->
-                shortestPath(
-                    node ->
-                        filter(graph.network().successors(node), MaybeBinding.class::isInstance),
-                    graph.network().incidentNodes(ep).target(),
-                    binding));
-  }
-
-  /**
-   * Returns a comparator that sorts entry points in by the distance of the type that declares them
-   * from the type of the component that contains them.
-   *
-   * <p>For instance, an entry point declared directly in the component type would sort before one
-   * declared in a direct supertype, which would sort before one declared in a supertype of a
-   * supertype.
-   */
-  Comparator<DependencyEdge> nearestComponentSupertypeFirst() {
-    return comparingInt(
-        entryPoint ->
-            indexOf(
-                supertypes.apply(componentContainingEntryPoint(entryPoint)),
-                equalTo(typeDeclaringEntryPoint(entryPoint))));
-  }
-
-  TypeElement componentContainingEntryPoint(DependencyEdge entryPoint) {
-    return source(entryPoint).componentPath().currentComponent();
-  }
-
-  TypeElement typeDeclaringEntryPoint(DependencyEdge entryPoint) {
-    return MoreElements.asType(
-        entryPoint.dependencyRequest().requestElement().get().getEnclosingElement());
-  }
-
-  /**
-   * Returns a comparator that sorts dependency edges lexicographically by the qualified name of the
-   * type that contains them. Only appropriate for edges with request elements.
-   */
-  Comparator<DependencyEdge> requestEnclosingTypeName() {
-    return comparing(
-        edge ->
-            closestEnclosingTypeElement(edge.dependencyRequest().requestElement().get())
-                .getQualifiedName()
-                .toString());
-  }
-
-  /**
-   * Returns a comparator that sorts edges in the order in which their request elements were
-   * declared in their declaring type.
-   *
-   * <p>Only useful to compare edges whose request elements were declared in the same type.
-   */
-  Comparator<DependencyEdge> requestElementDeclarationOrder() {
-    return comparing(edge -> edge.dependencyRequest().requestElement().get(), DECLARATION_ORDER);
-  }
-
-  private Node source(Edge edge) {
-    return graph.network().incidentNodes(edge).source();
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/DiagnosticReporterFactory.java b/java/dagger/internal/codegen/validation/DiagnosticReporterFactory.java
deleted file mode 100644
index 35ae7c7..0000000
--- a/java/dagger/internal/codegen/validation/DiagnosticReporterFactory.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.validation;
-
-import static com.google.common.collect.Lists.asList;
-import static dagger.internal.codegen.base.ElementFormatter.elementToString;
-import static dagger.internal.codegen.langmodel.DaggerElements.elementEncloses;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.errorprone.annotations.FormatMethod;
-import dagger.model.BindingGraph;
-import dagger.model.BindingGraph.ChildFactoryMethodEdge;
-import dagger.model.BindingGraph.ComponentNode;
-import dagger.model.BindingGraph.DependencyEdge;
-import dagger.model.BindingGraph.MaybeBinding;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic;
-import org.checkerframework.checker.nullness.compatqual.NullableDecl;
-
-/** A factory for {@link DiagnosticReporter}s. */
-// TODO(ronshapiro): If multiple plugins print errors on the same node/edge, should we condense the
-// messages and only print the dependency trace once?
-final class DiagnosticReporterFactory {
-  private final Messager messager;
-  private final DiagnosticMessageGenerator.Factory diagnosticMessageGeneratorFactory;
-
-  @Inject
-  DiagnosticReporterFactory(
-      Messager messager, DiagnosticMessageGenerator.Factory diagnosticMessageGeneratorFactory) {
-    this.messager = messager;
-    this.diagnosticMessageGeneratorFactory = diagnosticMessageGeneratorFactory;
-  }
-
-  /** Creates a reporter for a binding graph and a plugin. */
-  DiagnosticReporterImpl reporter(
-      BindingGraph graph, BindingGraphPlugin plugin, boolean reportErrorsAsWarnings) {
-    return new DiagnosticReporterImpl(graph, plugin.pluginName(), reportErrorsAsWarnings);
-  }
-
-  /**
-   * A {@link DiagnosticReporter} that keeps track of which {@linkplain Diagnostic.Kind kinds} of
-   * diagnostics were reported.
-   */
-  final class DiagnosticReporterImpl implements DiagnosticReporter {
-    private final String plugin;
-    private final TypeElement rootComponent;
-    private final boolean reportErrorsAsWarnings;
-    private final ImmutableSet.Builder<Diagnostic.Kind> reportedDiagnosticKinds =
-        ImmutableSet.builder();
-    private final DiagnosticMessageGenerator diagnosticMessageGenerator;
-
-    DiagnosticReporterImpl(BindingGraph graph, String plugin, boolean reportErrorsAsWarnings) {
-      this.plugin = plugin;
-      this.reportErrorsAsWarnings = reportErrorsAsWarnings;
-      this.rootComponent = graph.rootComponentNode().componentPath().currentComponent();
-      this.diagnosticMessageGenerator = diagnosticMessageGeneratorFactory.create(graph);
-    }
-
-    /** Returns which {@linkplain Diagnostic.Kind kinds} of diagnostics were reported. */
-    ImmutableSet<Diagnostic.Kind> reportedDiagnosticKinds() {
-      return reportedDiagnosticKinds.build();
-    }
-
-    @Override
-    public void reportComponent(
-        Diagnostic.Kind diagnosticKind, ComponentNode componentNode, String messageFormat) {
-      StringBuilder message = new StringBuilder(messageFormat);
-      diagnosticMessageGenerator.appendComponentPathUnlessAtRoot(message, componentNode);
-      // TODO(dpb): Report at the component node component.
-      printMessage(diagnosticKind, message, rootComponent);
-    }
-
-    @Override
-    @FormatMethod
-    public void reportComponent(
-        Diagnostic.Kind diagnosticKind,
-        ComponentNode componentNode,
-        String messageFormat,
-        Object firstArg,
-        Object... moreArgs) {
-      reportComponent(
-          diagnosticKind, componentNode, formatMessage(messageFormat, firstArg, moreArgs));
-    }
-
-    // TODO(ronshapiro): should this also include the binding element?
-    @Override
-    public void reportBinding(
-        Diagnostic.Kind diagnosticKind, MaybeBinding binding, String message) {
-      printMessage(
-          diagnosticKind, message + diagnosticMessageGenerator.getMessage(binding), rootComponent);
-    }
-
-    @Override
-    public void reportBinding(
-        Diagnostic.Kind diagnosticKind,
-        MaybeBinding binding,
-        String messageFormat,
-        Object firstArg,
-        Object... moreArgs) {
-      reportBinding(diagnosticKind, binding, formatMessage(messageFormat, firstArg, moreArgs));
-    }
-
-    @Override
-    public void reportDependency(
-        Diagnostic.Kind diagnosticKind, DependencyEdge dependencyEdge, String message) {
-      printMessage(
-          diagnosticKind,
-          message + diagnosticMessageGenerator.getMessage(dependencyEdge),
-          rootComponent);
-    }
-
-    @Override
-    public void reportDependency(
-        Diagnostic.Kind diagnosticKind,
-        DependencyEdge dependencyEdge,
-        String messageFormat,
-        Object firstArg,
-        Object... moreArgs) {
-      reportDependency(
-          diagnosticKind, dependencyEdge, formatMessage(messageFormat, firstArg, moreArgs));
-    }
-
-    @Override
-    public void reportSubcomponentFactoryMethod(
-        Diagnostic.Kind diagnosticKind,
-        ChildFactoryMethodEdge childFactoryMethodEdge,
-        String message) {
-      printMessage(diagnosticKind, 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());
-    }
-
-    void printMessage(
-        Diagnostic.Kind diagnosticKind,
-        CharSequence message,
-        @NullableDecl Element elementToReport) {
-      if (diagnosticKind.equals(ERROR) && reportErrorsAsWarnings) {
-        diagnosticKind = Diagnostic.Kind.WARNING;
-      }
-      reportedDiagnosticKinds.add(diagnosticKind);
-      StringBuilder fullMessage = new StringBuilder();
-      appendBracketPrefix(fullMessage, plugin);
-
-      // TODO(ronshapiro): should we create a HashSet out of elementEncloses() so we don't
-      // need to do an O(n) contains() each time?
-      if (elementToReport != null && !elementEncloses(rootComponent, elementToReport)) {
-        appendBracketPrefix(fullMessage, elementToString(elementToReport));
-        elementToReport = rootComponent;
-      }
-
-      messager.printMessage(diagnosticKind, fullMessage.append(message), elementToReport);
-    }
-
-    private void appendBracketPrefix(StringBuilder message, String prefix) {
-      message.append(String.format("[%s] ", prefix));
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java b/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java
deleted file mode 100644
index 06f68f6..0000000
--- a/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Copyright (C) 2014 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.validation;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static dagger.internal.codegen.base.Keys.isValidImplicitProvisionKey;
-import static dagger.internal.codegen.base.Keys.isValidMembersInjectionKey;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedInjectedConstructors;
-import static dagger.internal.codegen.binding.InjectionAnnotations.injectedConstructors;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import dagger.Component;
-import dagger.MembersInjector;
-import dagger.Provides;
-import dagger.internal.codegen.base.SourceFileGenerationException;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.Binding;
-import dagger.internal.codegen.binding.BindingFactory;
-import dagger.internal.codegen.binding.InjectBindingRegistry;
-import dagger.internal.codegen.binding.KeyFactory;
-import dagger.internal.codegen.binding.MembersInjectionBinding;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.inject.Singleton;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.tools.Diagnostic.Kind;
-
-/**
- * Maintains the collection of provision bindings from {@link Inject} constructors and members
- * injection bindings from {@link Inject} fields and methods known to the annotation processor.
- * Note that this registry <b>does not</b> handle any explicit bindings (those from {@link Provides}
- * methods, {@link Component} dependencies, etc.).
- */
-@Singleton
-final class InjectBindingRegistryImpl implements InjectBindingRegistry {
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final Messager messager;
-  private final InjectValidator injectValidator;
-  private final InjectValidator injectValidatorWhenGeneratingCode;
-  private final KeyFactory keyFactory;
-  private final BindingFactory bindingFactory;
-  private final CompilerOptions compilerOptions;
-
-  final class BindingsCollection<B extends Binding> {
-    private final Class<?> factoryClass;
-    private final Map<Key, B> bindingsByKey = Maps.newLinkedHashMap();
-    private final Deque<B> bindingsRequiringGeneration = new ArrayDeque<>();
-    private final Set<Key> materializedBindingKeys = Sets.newLinkedHashSet();
-
-    BindingsCollection(Class<?> factoryClass) {
-      this.factoryClass = factoryClass;
-    }
-
-    void generateBindings(SourceFileGenerator<B> generator) throws SourceFileGenerationException {
-      for (B binding = bindingsRequiringGeneration.poll();
-          binding != null;
-          binding = bindingsRequiringGeneration.poll()) {
-        checkState(!binding.unresolved().isPresent());
-        if (injectValidatorWhenGeneratingCode.isValidType(binding.key().type())) {
-          generator.generate(binding);
-        }
-        materializedBindingKeys.add(binding.key());
-      }
-      // Because Elements instantiated across processing rounds are not guaranteed to be equals() to
-      // the logically same element, clear the cache after generating
-      bindingsByKey.clear();
-    }
-
-    /** Returns a previously cached binding. */
-    B getBinding(Key key) {
-      return bindingsByKey.get(key);
-    }
-
-    /** Caches the binding and generates it if it needs generation. */
-    void tryRegisterBinding(B binding, boolean warnIfNotAlreadyGenerated) {
-      tryToCacheBinding(binding);
-      tryToGenerateBinding(binding, warnIfNotAlreadyGenerated);
-    }
-
-    /**
-     * Tries to generate a binding, not generating if it already is generated. For resolved
-     * bindings, this will try to generate the unresolved version of the binding.
-     */
-    void tryToGenerateBinding(B binding, boolean warnIfNotAlreadyGenerated) {
-      if (shouldGenerateBinding(binding)) {
-        bindingsRequiringGeneration.offer(binding);
-        if (compilerOptions.warnIfInjectionFactoryNotGeneratedUpstream()
-            && warnIfNotAlreadyGenerated) {
-          messager.printMessage(
-              Kind.NOTE,
-              String.format(
-                  "Generating a %s for %s. "
-                      + "Prefer to run the dagger processor over that class instead.",
-                  factoryClass.getSimpleName(),
-                  types.erasure(binding.key().type()))); // erasure to strip <T> from msgs.
-        }
-      }
-    }
-
-    /** Returns true if the binding needs to be generated. */
-    private boolean shouldGenerateBinding(B binding) {
-      return !binding.unresolved().isPresent()
-          && !materializedBindingKeys.contains(binding.key())
-          && !bindingsRequiringGeneration.contains(binding)
-          && elements.getTypeElement(generatedClassNameForBinding(binding)) == null;
-    }
-
-    /** Caches the binding for future lookups by key. */
-    private void tryToCacheBinding(B binding) {
-      // We only cache resolved bindings or unresolved bindings w/o type arguments.
-      // Unresolved bindings w/ type arguments aren't valid for the object graph.
-      if (binding.unresolved().isPresent()
-          || binding.bindingTypeElement().get().getTypeParameters().isEmpty()) {
-        Key key = binding.key();
-        Binding previousValue = bindingsByKey.put(key, binding);
-        checkState(previousValue == null || binding.equals(previousValue),
-            "couldn't register %s. %s was already registered for %s",
-            binding, previousValue, key);
-      }
-    }
-  }
-
-  private final BindingsCollection<ProvisionBinding> provisionBindings =
-      new BindingsCollection<>(Provider.class);
-  private final BindingsCollection<MembersInjectionBinding> membersInjectionBindings =
-      new BindingsCollection<>(MembersInjector.class);
-
-  @Inject
-  InjectBindingRegistryImpl(
-      DaggerElements elements,
-      DaggerTypes types,
-      Messager messager,
-      InjectValidator injectValidator,
-      KeyFactory keyFactory,
-      BindingFactory bindingFactory,
-      CompilerOptions compilerOptions) {
-    this.elements = elements;
-    this.types = types;
-    this.messager = messager;
-    this.injectValidator = injectValidator;
-    this.injectValidatorWhenGeneratingCode = injectValidator.whenGeneratingCode();
-    this.keyFactory = keyFactory;
-    this.bindingFactory = bindingFactory;
-    this.compilerOptions = compilerOptions;
-  }
-
-
-  // TODO(dpb): make the SourceFileGenerators fields so they don't have to be passed in
-  @Override
-  public void generateSourcesForRequiredBindings(
-      SourceFileGenerator<ProvisionBinding> factoryGenerator,
-      SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator)
-      throws SourceFileGenerationException {
-    provisionBindings.generateBindings(factoryGenerator);
-    membersInjectionBindings.generateBindings(membersInjectorGenerator);
-  }
-
-  /**
-   * Registers the binding for generation and later lookup. If the binding is resolved, we also
-   * attempt to register an unresolved version of it.
-   */
-  private void registerBinding(ProvisionBinding binding, boolean warnIfNotAlreadyGenerated) {
-    provisionBindings.tryRegisterBinding(binding, warnIfNotAlreadyGenerated);
-    if (binding.unresolved().isPresent()) {
-      provisionBindings.tryToGenerateBinding(binding.unresolved().get(), warnIfNotAlreadyGenerated);
-    }
-  }
-
-  /**
-   * Registers the binding for generation and later lookup. If the binding is resolved, we also
-   * attempt to register an unresolved version of it.
-   */
-  private void registerBinding(MembersInjectionBinding binding, boolean warnIfNotAlreadyGenerated) {
-    /*
-     * We generate MembersInjector classes for types with @Inject constructors only if they have any
-     * injection sites.
-     *
-     * We generate MembersInjector classes for types without @Inject constructors only if they have
-     * local (non-inherited) injection sites.
-     *
-     * Warn only when registering bindings post-hoc for those types.
-     */
-    if (warnIfNotAlreadyGenerated) {
-      boolean hasInjectConstructor =
-          !(injectedConstructors(binding.membersInjectedType()).isEmpty()
-              && assistedInjectedConstructors(binding.membersInjectedType()).isEmpty());
-      warnIfNotAlreadyGenerated =
-          hasInjectConstructor
-              ? !binding.injectionSites().isEmpty()
-              : binding.hasLocalInjectionSites();
-    }
-
-    membersInjectionBindings.tryRegisterBinding(binding, warnIfNotAlreadyGenerated);
-    if (binding.unresolved().isPresent()) {
-      membersInjectionBindings.tryToGenerateBinding(
-          binding.unresolved().get(), warnIfNotAlreadyGenerated);
-    }
-  }
-
-  @Override
-  public Optional<ProvisionBinding> tryRegisterConstructor(ExecutableElement constructorElement) {
-    return tryRegisterConstructor(constructorElement, Optional.empty(), false);
-  }
-
-  @CanIgnoreReturnValue
-  private Optional<ProvisionBinding> tryRegisterConstructor(
-      ExecutableElement constructorElement,
-      Optional<TypeMirror> resolvedType,
-      boolean warnIfNotAlreadyGenerated) {
-    TypeElement typeElement = MoreElements.asType(constructorElement.getEnclosingElement());
-    DeclaredType type = MoreTypes.asDeclared(typeElement.asType());
-    Key key = keyFactory.forInjectConstructorWithResolvedType(type);
-    ProvisionBinding cachedBinding = provisionBindings.getBinding(key);
-    if (cachedBinding != null) {
-      return Optional.of(cachedBinding);
-    }
-
-    ValidationReport<TypeElement> report = injectValidator.validateConstructor(constructorElement);
-    report.printMessagesTo(messager);
-    if (report.isClean()) {
-      ProvisionBinding binding = bindingFactory.injectionBinding(constructorElement, resolvedType);
-      registerBinding(binding, warnIfNotAlreadyGenerated);
-      if (!binding.injectionSites().isEmpty()) {
-        tryRegisterMembersInjectedType(typeElement, resolvedType, warnIfNotAlreadyGenerated);
-      }
-      return Optional.of(binding);
-    }
-    return Optional.empty();
-  }
-
-  @Override
-  public Optional<MembersInjectionBinding> tryRegisterMembersInjectedType(TypeElement typeElement) {
-    return tryRegisterMembersInjectedType(typeElement, Optional.empty(), false);
-  }
-
-  @CanIgnoreReturnValue
-  private Optional<MembersInjectionBinding> tryRegisterMembersInjectedType(
-      TypeElement typeElement,
-      Optional<TypeMirror> resolvedType,
-      boolean warnIfNotAlreadyGenerated) {
-    DeclaredType type = MoreTypes.asDeclared(typeElement.asType());
-    Key key = keyFactory.forInjectConstructorWithResolvedType(type);
-    MembersInjectionBinding cachedBinding = membersInjectionBindings.getBinding(key);
-    if (cachedBinding != null) {
-      return Optional.of(cachedBinding);
-    }
-
-    ValidationReport<TypeElement> report =
-        injectValidator.validateMembersInjectionType(typeElement);
-    report.printMessagesTo(messager);
-    if (report.isClean()) {
-      MembersInjectionBinding binding = bindingFactory.membersInjectionBinding(type, resolvedType);
-      registerBinding(binding, warnIfNotAlreadyGenerated);
-      for (Optional<DeclaredType> supertype = types.nonObjectSuperclass(type);
-          supertype.isPresent();
-          supertype = types.nonObjectSuperclass(supertype.get())) {
-        getOrFindMembersInjectionBinding(keyFactory.forMembersInjectedType(supertype.get()));
-      }
-      return Optional.of(binding);
-    }
-    return Optional.empty();
-  }
-
-  @CanIgnoreReturnValue
-  @Override
-  public Optional<ProvisionBinding> getOrFindProvisionBinding(Key key) {
-    checkNotNull(key);
-    if (!isValidImplicitProvisionKey(key, types)) {
-      return Optional.empty();
-    }
-    ProvisionBinding binding = provisionBindings.getBinding(key);
-    if (binding != null) {
-      return Optional.of(binding);
-    }
-
-    // ok, let's see if we can find an @Inject constructor
-    TypeElement element = MoreElements.asType(types.asElement(key.type()));
-    ImmutableSet<ExecutableElement> injectConstructors =
-        ImmutableSet.<ExecutableElement>builder()
-            .addAll(injectedConstructors(element))
-            .addAll(assistedInjectedConstructors(element))
-            .build();
-    switch (injectConstructors.size()) {
-      case 0:
-        // No constructor found.
-        return Optional.empty();
-      case 1:
-        return tryRegisterConstructor(
-            Iterables.getOnlyElement(injectConstructors), Optional.of(key.type()), true);
-      default:
-        throw new IllegalStateException("Found multiple @Inject constructors: "
-            + injectConstructors);
-    }
-  }
-
-  @CanIgnoreReturnValue
-  @Override
-  public Optional<MembersInjectionBinding> getOrFindMembersInjectionBinding(Key key) {
-    checkNotNull(key);
-    // TODO(gak): is checking the kind enough?
-    checkArgument(isValidMembersInjectionKey(key));
-    MembersInjectionBinding binding = membersInjectionBindings.getBinding(key);
-    if (binding != null) {
-      return Optional.of(binding);
-    }
-    Optional<MembersInjectionBinding> newBinding =
-        tryRegisterMembersInjectedType(
-            MoreTypes.asTypeElement(key.type()), Optional.of(key.type()), true);
-    return newBinding;
-  }
-
-  @Override
-  public Optional<ProvisionBinding> getOrFindMembersInjectorProvisionBinding(Key key) {
-    if (!isValidMembersInjectionKey(key)) {
-      return Optional.empty();
-    }
-    Key membersInjectionKey = keyFactory.forMembersInjectedType(types.unwrapType(key.type()));
-    return getOrFindMembersInjectionBinding(membersInjectionKey)
-        .map(binding -> bindingFactory.membersInjectorBinding(key, binding));
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/InjectBindingRegistryModule.java b/java/dagger/internal/codegen/validation/InjectBindingRegistryModule.java
deleted file mode 100644
index 3a164ca..0000000
--- a/java/dagger/internal/codegen/validation/InjectBindingRegistryModule.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.validation;
-
-import dagger.Binds;
-import dagger.Module;
-import dagger.internal.codegen.binding.InjectBindingRegistry;
-
-/** Binds the {@link InjectBindingRegistry} implementation. */
-@Module
-public interface InjectBindingRegistryModule {
-  @Binds InjectBindingRegistry injectBindingRegistry(InjectBindingRegistryImpl impl);
-}
diff --git a/java/dagger/internal/codegen/validation/InjectValidator.java b/java/dagger/internal/codegen/validation/InjectValidator.java
deleted file mode 100644
index 240f9d0..0000000
--- a/java/dagger/internal/codegen/validation/InjectValidator.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright (C) 2014 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.validation;
-
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static dagger.internal.codegen.base.Scopes.scopesOf;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedInjectedConstructors;
-import static dagger.internal.codegen.binding.InjectionAnnotations.injectedConstructors;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.type.TypeKind.DECLARED;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSet;
-import dagger.assisted.AssistedInject;
-import dagger.internal.codegen.base.ClearableCache;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.Accessibility;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Scope;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.lang.model.element.AnnotationMirror;
-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.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-import javax.tools.Diagnostic;
-import javax.tools.Diagnostic.Kind;
-
-/**
- * A {@linkplain ValidationReport validator} for {@link Inject}-annotated elements and the types
- * that contain them.
- */
-@Singleton
-public final class InjectValidator implements ClearableCache {
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-  private final CompilerOptions compilerOptions;
-  private final DependencyRequestValidator dependencyRequestValidator;
-  private final Optional<Diagnostic.Kind> privateAndStaticInjectionDiagnosticKind;
-  private final InjectionAnnotations injectionAnnotations;
-  private final KotlinMetadataUtil metadataUtil;
-  private final Map<ExecutableElement, ValidationReport<TypeElement>> reports = new HashMap<>();
-
-  @Inject
-  InjectValidator(
-      DaggerTypes types,
-      DaggerElements elements,
-      DependencyRequestValidator dependencyRequestValidator,
-      CompilerOptions compilerOptions,
-      InjectionAnnotations injectionAnnotations,
-      KotlinMetadataUtil metadataUtil) {
-    this(
-        types,
-        elements,
-        compilerOptions,
-        dependencyRequestValidator,
-        Optional.empty(),
-        injectionAnnotations,
-        metadataUtil);
-  }
-
-  private InjectValidator(
-      DaggerTypes types,
-      DaggerElements elements,
-      CompilerOptions compilerOptions,
-      DependencyRequestValidator dependencyRequestValidator,
-      Optional<Kind> privateAndStaticInjectionDiagnosticKind,
-      InjectionAnnotations injectionAnnotations,
-      KotlinMetadataUtil metadataUtil) {
-    this.types = types;
-    this.elements = elements;
-    this.compilerOptions = compilerOptions;
-    this.dependencyRequestValidator = dependencyRequestValidator;
-    this.privateAndStaticInjectionDiagnosticKind = privateAndStaticInjectionDiagnosticKind;
-    this.injectionAnnotations = injectionAnnotations;
-    this.metadataUtil = metadataUtil;
-  }
-
-  @Override
-  public void clearCache() {
-    reports.clear();
-  }
-
-  /**
-   * Returns a new validator that performs the same validation as this one, but is strict about
-   * rejecting optionally-specified JSR 330 behavior that Dagger doesn't support (unless {@code
-   * -Adagger.ignorePrivateAndStaticInjectionForComponent=enabled} was set in the javac options).
-   */
-  public InjectValidator whenGeneratingCode() {
-    return compilerOptions.ignorePrivateAndStaticInjectionForComponent()
-        ? this
-        : new InjectValidator(
-            types,
-            elements,
-            compilerOptions,
-            dependencyRequestValidator,
-            Optional.of(Diagnostic.Kind.ERROR),
-            injectionAnnotations,
-            metadataUtil);
-  }
-
-  public ValidationReport<TypeElement> validateConstructor(ExecutableElement constructorElement) {
-    return reentrantComputeIfAbsent(reports, constructorElement, this::validateConstructorUncached);
-  }
-
-  private ValidationReport<TypeElement> validateConstructorUncached(
-      ExecutableElement constructorElement) {
-    ValidationReport.Builder<TypeElement> builder =
-        ValidationReport.about(asType(constructorElement.getEnclosingElement()));
-
-    if (isAnnotationPresent(constructorElement, Inject.class)
-        && isAnnotationPresent(constructorElement, AssistedInject.class)) {
-      builder.addError("Constructors cannot be annotated with both @Inject and @AssistedInject");
-    }
-
-    Class<?> injectAnnotation =
-        isAnnotationPresent(constructorElement, Inject.class) ? Inject.class : AssistedInject.class;
-
-    if (constructorElement.getModifiers().contains(PRIVATE)) {
-      builder.addError(
-          "Dagger does not support injection into private constructors", constructorElement);
-    }
-
-    for (AnnotationMirror qualifier : injectionAnnotations.getQualifiers(constructorElement)) {
-      builder.addError(
-          String.format(
-              "@Qualifier annotations are not allowed on @%s constructors",
-              injectAnnotation.getSimpleName()),
-          constructorElement,
-          qualifier);
-    }
-
-    String scopeErrorMsg =
-        String.format(
-            "@Scope annotations are not allowed on @%s constructors",
-            injectAnnotation.getSimpleName());
-
-    if (injectAnnotation == Inject.class) {
-      scopeErrorMsg += "; annotate the class instead";
-    }
-
-    for (Scope scope : scopesOf(constructorElement)) {
-      builder.addError(scopeErrorMsg, constructorElement, scope.scopeAnnotation());
-    }
-
-    for (VariableElement parameter : constructorElement.getParameters()) {
-      validateDependencyRequest(builder, parameter);
-    }
-
-    if (throwsCheckedExceptions(constructorElement)) {
-      builder.addItem(
-          String.format(
-              "Dagger does not support checked exceptions on @%s constructors",
-              injectAnnotation.getSimpleName()),
-          privateMemberDiagnosticKind(),
-          constructorElement);
-    }
-
-    checkInjectIntoPrivateClass(constructorElement, builder);
-
-    TypeElement enclosingElement =
-        MoreElements.asType(constructorElement.getEnclosingElement());
-
-    Set<Modifier> typeModifiers = enclosingElement.getModifiers();
-    if (typeModifiers.contains(ABSTRACT)) {
-      builder.addError(
-          String.format(
-              "@%s is nonsense on the constructor of an abstract class",
-              injectAnnotation.getSimpleName()),
-          constructorElement);
-    }
-
-    if (enclosingElement.getNestingKind().isNested()
-        && !typeModifiers.contains(STATIC)) {
-      builder.addError(
-          String.format(
-              "@%s constructors are invalid on inner classes. "
-                  + "Did you mean to make the class static?",
-              injectAnnotation.getSimpleName()),
-          constructorElement);
-    }
-
-    // This is computationally expensive, but probably preferable to a giant index
-    ImmutableSet<ExecutableElement> injectConstructors =
-        ImmutableSet.<ExecutableElement>builder()
-            .addAll(injectedConstructors(enclosingElement))
-            .addAll(assistedInjectedConstructors(enclosingElement))
-            .build();
-
-    if (injectConstructors.size() > 1) {
-      builder.addError("Types may only contain one injected constructor", constructorElement);
-    }
-
-    ImmutableSet<Scope> scopes = scopesOf(enclosingElement);
-    if (injectAnnotation == AssistedInject.class) {
-      for (Scope scope : scopes) {
-        builder.addError(
-            "A type with an @AssistedInject-annotated constructor cannot be scoped",
-            enclosingElement,
-            scope.scopeAnnotation());
-      }
-    } else if (scopes.size() > 1) {
-      for (Scope scope : scopes) {
-        builder.addError(
-            "A single binding may not declare more than one @Scope",
-            enclosingElement,
-            scope.scopeAnnotation());
-      }
-    }
-
-    return builder.build();
-  }
-
-  private ValidationReport<VariableElement> validateField(VariableElement fieldElement) {
-    ValidationReport.Builder<VariableElement> builder = ValidationReport.about(fieldElement);
-    Set<Modifier> modifiers = fieldElement.getModifiers();
-    if (modifiers.contains(FINAL)) {
-      builder.addError("@Inject fields may not be final", fieldElement);
-    }
-
-    if (modifiers.contains(PRIVATE)) {
-      builder.addItem(
-          "Dagger does not support injection into private fields",
-          privateMemberDiagnosticKind(),
-          fieldElement);
-    }
-
-    if (modifiers.contains(STATIC)) {
-      builder.addItem(
-          "Dagger does not support injection into static fields",
-          staticMemberDiagnosticKind(),
-          fieldElement);
-    }
-
-    validateDependencyRequest(builder, fieldElement);
-
-    return builder.build();
-  }
-
-  private ValidationReport<ExecutableElement> validateMethod(ExecutableElement methodElement) {
-    ValidationReport.Builder<ExecutableElement> builder = ValidationReport.about(methodElement);
-    Set<Modifier> modifiers = methodElement.getModifiers();
-    if (modifiers.contains(ABSTRACT)) {
-      builder.addError("Methods with @Inject may not be abstract", methodElement);
-    }
-
-    if (modifiers.contains(PRIVATE)) {
-      builder.addItem(
-          "Dagger does not support injection into private methods",
-          privateMemberDiagnosticKind(),
-          methodElement);
-    }
-
-    if (modifiers.contains(STATIC)) {
-      builder.addItem(
-          "Dagger does not support injection into static methods",
-          staticMemberDiagnosticKind(),
-          methodElement);
-    }
-
-    if (!methodElement.getTypeParameters().isEmpty()) {
-      builder.addError("Methods with @Inject may not declare type parameters", methodElement);
-    }
-
-    if (!methodElement.getThrownTypes().isEmpty()) {
-      builder.addError("Methods with @Inject may not throw checked exceptions. "
-          + "Please wrap your exceptions in a RuntimeException instead.", methodElement);
-    }
-
-    for (VariableElement parameter : methodElement.getParameters()) {
-      validateDependencyRequest(builder, parameter);
-    }
-
-    return builder.build();
-  }
-
-  private void validateDependencyRequest(
-      ValidationReport.Builder<?> builder, VariableElement parameter) {
-    dependencyRequestValidator.validateDependencyRequest(builder, parameter, parameter.asType());
-    dependencyRequestValidator.checkNotProducer(builder, parameter);
-  }
-
-  public ValidationReport<TypeElement> validateMembersInjectionType(TypeElement typeElement) {
-    // TODO(beder): This element might not be currently compiled, so this error message could be
-    // left in limbo. Find an appropriate way to display the error message in that case.
-    ValidationReport.Builder<TypeElement> builder = ValidationReport.about(typeElement);
-    boolean hasInjectedMembers = false;
-    for (VariableElement element : ElementFilter.fieldsIn(typeElement.getEnclosedElements())) {
-      if (MoreElements.isAnnotationPresent(element, Inject.class)) {
-        hasInjectedMembers = true;
-        ValidationReport<VariableElement> report = validateField(element);
-        if (!report.isClean()) {
-          builder.addSubreport(report);
-        }
-      }
-    }
-    for (ExecutableElement element : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
-      if (MoreElements.isAnnotationPresent(element, Inject.class)) {
-        hasInjectedMembers = true;
-        ValidationReport<ExecutableElement> report = validateMethod(element);
-        if (!report.isClean()) {
-          builder.addSubreport(report);
-        }
-      }
-    }
-
-    if (hasInjectedMembers) {
-      checkInjectIntoPrivateClass(typeElement, builder);
-      checkInjectIntoKotlinObject(typeElement, builder);
-    }
-    TypeMirror superclass = typeElement.getSuperclass();
-    if (!superclass.getKind().equals(TypeKind.NONE)) {
-      ValidationReport<TypeElement> report = validateType(MoreTypes.asTypeElement(superclass));
-      if (!report.isClean()) {
-        builder.addSubreport(report);
-      }
-    }
-    return builder.build();
-  }
-
-  public ValidationReport<TypeElement> validateType(TypeElement typeElement) {
-    ValidationReport.Builder<TypeElement> builder = ValidationReport.about(typeElement);
-    ValidationReport<TypeElement> membersInjectionReport =
-        validateMembersInjectionType(typeElement);
-    if (!membersInjectionReport.isClean()) {
-      builder.addSubreport(membersInjectionReport);
-    }
-    for (ExecutableElement element :
-        ElementFilter.constructorsIn(typeElement.getEnclosedElements())) {
-      if (isAnnotationPresent(element, Inject.class)
-          || isAnnotationPresent(element, AssistedInject.class)) {
-        ValidationReport<TypeElement> report = validateConstructor(element);
-        if (!report.isClean()) {
-          builder.addSubreport(report);
-        }
-      }
-    }
-    return builder.build();
-  }
-
-  public boolean isValidType(TypeMirror type) {
-    if (!type.getKind().equals(DECLARED)) {
-      return true;
-    }
-    return validateType(MoreTypes.asTypeElement(type)).isClean();
-  }
-
-  /** Returns true if the given method element declares a checked exception. */
-  private boolean throwsCheckedExceptions(ExecutableElement methodElement) {
-    TypeMirror runtimeExceptionType = elements.getTypeElement(RuntimeException.class).asType();
-    TypeMirror errorType = elements.getTypeElement(Error.class).asType();
-    for (TypeMirror thrownType : methodElement.getThrownTypes()) {
-      if (!types.isSubtype(thrownType, runtimeExceptionType)
-          && !types.isSubtype(thrownType, errorType)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private void checkInjectIntoPrivateClass(
-      Element element, ValidationReport.Builder<TypeElement> builder) {
-    if (!Accessibility.isElementAccessibleFromOwnPackage(
-        DaggerElements.closestEnclosingTypeElement(element))) {
-      builder.addItem(
-          "Dagger does not support injection into private classes",
-          privateMemberDiagnosticKind(),
-          element);
-    }
-  }
-
-  private void checkInjectIntoKotlinObject(
-      TypeElement element, ValidationReport.Builder<TypeElement> builder) {
-    if (metadataUtil.isObjectClass(element) || metadataUtil.isCompanionObjectClass(element)) {
-      builder.addError("Dagger does not support injection into Kotlin objects", element);
-    }
-  }
-
-  private Diagnostic.Kind privateMemberDiagnosticKind() {
-    return privateAndStaticInjectionDiagnosticKind.orElse(
-        compilerOptions.privateMemberValidationKind());
-  }
-
-  private Diagnostic.Kind staticMemberDiagnosticKind() {
-    return privateAndStaticInjectionDiagnosticKind.orElse(
-        compilerOptions.staticMemberValidationKind());
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/MapKeyValidator.java b/java/dagger/internal/codegen/validation/MapKeyValidator.java
deleted file mode 100644
index 6aa5147..0000000
--- a/java/dagger/internal/codegen/validation/MapKeyValidator.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2014 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.validation;
-
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import dagger.MapKey;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.List;
-import javax.inject.Inject;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeKind;
-
-/**
- * A validator for {@link MapKey} annotations.
- */
-// TODO(dpb,gak): Should unwrapped MapKeys be required to have their single member be named "value"?
-public final class MapKeyValidator {
-  private final DaggerElements elements;
-
-  @Inject
-  MapKeyValidator(DaggerElements elements) {
-    this.elements = elements;
-  }
-
-  public ValidationReport<Element> validate(Element element) {
-    ValidationReport.Builder<Element> builder = ValidationReport.about(element);
-    List<ExecutableElement> members = methodsIn(((TypeElement) element).getEnclosedElements());
-    if (members.isEmpty()) {
-      builder.addError("Map key annotations must have members", element);
-    } else if (element.getAnnotation(MapKey.class).unwrapValue()) {
-      if (members.size() > 1) {
-        builder.addError(
-            "Map key annotations with unwrapped values must have exactly one member", element);
-      } else if (members.get(0).getReturnType().getKind() == TypeKind.ARRAY) {
-        builder.addError("Map key annotations with unwrapped values cannot use arrays", element);
-      }
-    } else if (autoAnnotationIsMissing()) {
-      builder.addError(
-          "@AutoAnnotation is a necessary dependency if @MapKey(unwrapValue = false). Add a "
-              + "dependency on com.google.auto.value:auto-value:<current version>");
-    }
-    return builder.build();
-  }
-
-  private boolean autoAnnotationIsMissing() {
-    return elements.getTypeElement("com.google.auto.value.AutoAnnotation") == null;
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/MembersInjectionValidator.java b/java/dagger/internal/codegen/validation/MembersInjectionValidator.java
deleted file mode 100644
index afa6270..0000000
--- a/java/dagger/internal/codegen/validation/MembersInjectionValidator.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.validation;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.auto.common.MoreElements;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import javax.inject.Inject;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.PrimitiveType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVisitor;
-import javax.lang.model.util.SimpleTypeVisitor8;
-
-/**
- * Validates members injection requests (members injection methods on components and requests for
- * {@code MembersInjector<Foo>}).
- */
-final class MembersInjectionValidator {
-  private final InjectionAnnotations injectionAnnotations;
-
-  @Inject
-  MembersInjectionValidator(InjectionAnnotations injectionAnnotations) {
-    this.injectionAnnotations = injectionAnnotations;
-  }
-
-  /** Reports errors if a request for a {@code MembersInjector<Foo>}) is invalid. */
-  ValidationReport<Element> validateMembersInjectionRequest(
-      Element requestElement, TypeMirror membersInjectedType) {
-    ValidationReport.Builder<Element> report = ValidationReport.about(requestElement);
-    checkQualifiers(report, requestElement);
-    membersInjectedType.accept(VALIDATE_MEMBERS_INJECTED_TYPE, report);
-    return report.build();
-  }
-
-  /**
-   * Reports errors if a members injection method on a component is invalid.
-   *
-   * @throws IllegalArgumentException if the method doesn't have exactly one parameter
-   */
-  ValidationReport<ExecutableElement> validateMembersInjectionMethod(
-      ExecutableElement method, TypeMirror membersInjectedType) {
-    checkArgument(
-        method.getParameters().size() == 1, "expected a method with one parameter: %s", method);
-
-    ValidationReport.Builder<ExecutableElement> report = ValidationReport.about(method);
-    checkQualifiers(report, method);
-    checkQualifiers(report, method.getParameters().get(0));
-    membersInjectedType.accept(VALIDATE_MEMBERS_INJECTED_TYPE, report);
-    return report.build();
-  }
-
-  private void checkQualifiers(ValidationReport.Builder<?> report, Element element) {
-    for (AnnotationMirror qualifier : injectionAnnotations.getQualifiers(element)) {
-      report.addError("Cannot inject members into qualified types", element, qualifier);
-      break; // just report on the first qualifier, in case there is more than one
-    }
-  }
-
-  private static final TypeVisitor<Void, ValidationReport.Builder<?>>
-      VALIDATE_MEMBERS_INJECTED_TYPE =
-          new SimpleTypeVisitor8<Void, ValidationReport.Builder<?>>() {
-            // Only declared types can be members-injected.
-            @Override
-            protected Void defaultAction(TypeMirror type, ValidationReport.Builder<?> report) {
-              report.addError("Cannot inject members into " + type);
-              return null;
-            }
-
-            @Override
-            public Void visitDeclared(DeclaredType type, ValidationReport.Builder<?> report) {
-              if (type.getTypeArguments().isEmpty()) {
-                // If the type is the erasure of a generic type, that means the user referred to
-                // Foo<T> as just 'Foo', which we don't allow.  (This is a judgement call; we
-                // *could* allow it and instantiate the type bounds, but we don't.)
-                if (!MoreElements.asType(type.asElement()).getTypeParameters().isEmpty()) {
-                  report.addError("Cannot inject members into raw type " + type);
-                }
-              } else {
-                // If the type has arguments, validate that each type argument is declared.
-                // Otherwise the type argument may be a wildcard (or other type), and we can't
-                // resolve that to actual types.  For array type arguments, validate the type of the
-                // array.
-                for (TypeMirror arg : type.getTypeArguments()) {
-                  if (!arg.accept(DECLARED_OR_ARRAY, null)) {
-                    report.addError(
-                        "Cannot inject members into types with unbounded type arguments: " + type);
-                  }
-                }
-              }
-              return null;
-            }
-          };
-
-  // TODO(dpb): Can this be inverted so it explicitly rejects wildcards or type variables?
-  // This logic is hard to describe.
-  private static final TypeVisitor<Boolean, Void> DECLARED_OR_ARRAY =
-      new SimpleTypeVisitor8<Boolean, Void>(false) {
-        @Override
-        public Boolean visitArray(ArrayType arrayType, Void p) {
-          return arrayType
-              .getComponentType()
-              .accept(
-                  new SimpleTypeVisitor8<Boolean, Void>(false) {
-                    @Override
-                    public Boolean visitDeclared(DeclaredType declaredType, Void p) {
-                      for (TypeMirror arg : declaredType.getTypeArguments()) {
-                        if (!arg.accept(this, null)) {
-                          return false;
-                        }
-                      }
-                      return true;
-                    }
-
-                    @Override
-                    public Boolean visitArray(ArrayType arrayType, Void p) {
-                      return arrayType.getComponentType().accept(this, null);
-                    }
-
-                    @Override
-                    public Boolean visitPrimitive(PrimitiveType primitiveType, Void p) {
-                      return true;
-                    }
-                  },
-                  null);
-        }
-
-        @Override
-        public Boolean visitDeclared(DeclaredType t, Void p) {
-          return true;
-        }
-      };
-}
diff --git a/java/dagger/internal/codegen/validation/ModuleValidator.java b/java/dagger/internal/codegen/validation/ModuleValidator.java
deleted file mode 100644
index 02ac06a..0000000
--- a/java/dagger/internal/codegen/validation/ModuleValidator.java
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Copyright (C) 2014 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.validation;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotatedAnnotations;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static com.google.auto.common.MoreTypes.asTypeElement;
-import static com.google.auto.common.Visibility.PRIVATE;
-import static com.google.auto.common.Visibility.PUBLIC;
-import static com.google.auto.common.Visibility.effectiveVisibilityOfElement;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.ComponentAnnotation.componentAnnotation;
-import static dagger.internal.codegen.base.ComponentAnnotation.isComponentAnnotation;
-import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotation;
-import static dagger.internal.codegen.base.ModuleAnnotation.isModuleAnnotation;
-import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
-import static dagger.internal.codegen.base.MoreAnnotationMirrors.simpleName;
-import static dagger.internal.codegen.base.MoreAnnotationValues.asType;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.getCreatorAnnotations;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.getSubcomponentCreator;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
-import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
-import static java.util.stream.Collectors.joining;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.auto.common.Visibility;
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.Sets;
-import com.google.errorprone.annotations.FormatMethod;
-import dagger.Module;
-import dagger.Subcomponent;
-import dagger.internal.codegen.base.ModuleAnnotation;
-import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.ComponentCreatorAnnotation;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
-import dagger.internal.codegen.binding.MethodSignatureFormatter;
-import dagger.internal.codegen.binding.ModuleKind;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingGraph;
-import dagger.producers.ProducerModule;
-import dagger.producers.ProductionSubcomponent;
-import java.lang.annotation.Annotation;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Scope;
-import javax.inject.Singleton;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleAnnotationValueVisitor8;
-import javax.lang.model.util.SimpleTypeVisitor8;
-
-/** A {@linkplain ValidationReport validator} for {@link Module}s or {@link ProducerModule}s. */
-@Singleton
-public final class ModuleValidator {
-  private static final ImmutableSet<Class<? extends Annotation>> SUBCOMPONENT_TYPES =
-      ImmutableSet.of(Subcomponent.class, ProductionSubcomponent.class);
-  private static final ImmutableSet<Class<? extends Annotation>> SUBCOMPONENT_CREATOR_TYPES =
-      ImmutableSet.of(
-          Subcomponent.Builder.class,
-          Subcomponent.Factory.class,
-          ProductionSubcomponent.Builder.class,
-          ProductionSubcomponent.Factory.class);
-  private static final Optional<Class<?>> ANDROID_PROCESSOR;
-  private static final String CONTRIBUTES_ANDROID_INJECTOR_NAME =
-      "dagger.android.ContributesAndroidInjector";
-  private static final String ANDROID_PROCESSOR_NAME = "dagger.android.processor.AndroidProcessor";
-
-  static {
-    Class<?> clazz;
-    try {
-      clazz = Class.forName(ANDROID_PROCESSOR_NAME, false, ModuleValidator.class.getClassLoader());
-    } catch (ClassNotFoundException ignored) {
-      clazz = null;
-    }
-    ANDROID_PROCESSOR = Optional.ofNullable(clazz);
-  }
-
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-  private final AnyBindingMethodValidator anyBindingMethodValidator;
-  private final MethodSignatureFormatter methodSignatureFormatter;
-  private final ComponentDescriptorFactory componentDescriptorFactory;
-  private final BindingGraphFactory bindingGraphFactory;
-  private final BindingGraphValidator bindingGraphValidator;
-  private final KotlinMetadataUtil metadataUtil;
-  private final Map<TypeElement, ValidationReport<TypeElement>> cache = new HashMap<>();
-  private final Set<TypeElement> knownModules = new HashSet<>();
-
-  @Inject
-  ModuleValidator(
-      DaggerTypes types,
-      DaggerElements elements,
-      AnyBindingMethodValidator anyBindingMethodValidator,
-      MethodSignatureFormatter methodSignatureFormatter,
-      ComponentDescriptorFactory componentDescriptorFactory,
-      BindingGraphFactory bindingGraphFactory,
-      BindingGraphValidator bindingGraphValidator,
-      KotlinMetadataUtil metadataUtil) {
-    this.types = types;
-    this.elements = elements;
-    this.anyBindingMethodValidator = anyBindingMethodValidator;
-    this.methodSignatureFormatter = methodSignatureFormatter;
-    this.componentDescriptorFactory = componentDescriptorFactory;
-    this.bindingGraphFactory = bindingGraphFactory;
-    this.bindingGraphValidator = bindingGraphValidator;
-    this.metadataUtil = metadataUtil;
-  }
-
-  /**
-   * Adds {@code modules} to the set of module types that will be validated during this compilation
-   * step. If a component or module includes a module that is not in this set, that included module
-   * is assumed to be valid because it was processed in a previous compilation step. If it were
-   * invalid, that previous compilation step would have failed and blocked this one.
-   *
-   * <p>This logic depends on this method being called before {@linkplain #validate(TypeElement)
-   * validating} any module or {@linkplain #validateReferencedModules(TypeElement, AnnotationMirror,
-   * ImmutableSet, Set) component}.
-   */
-  public void addKnownModules(Collection<TypeElement> modules) {
-    knownModules.addAll(modules);
-  }
-
-  /** Returns a validation report for a module type. */
-  public ValidationReport<TypeElement> validate(TypeElement module) {
-    return validate(module, new HashSet<>());
-  }
-
-  private ValidationReport<TypeElement> validate(
-      TypeElement module, Set<TypeElement> visitedModules) {
-    if (visitedModules.add(module)) {
-      return reentrantComputeIfAbsent(cache, module, m -> validateUncached(module, visitedModules));
-    }
-    return ValidationReport.about(module).build();
-  }
-
-  private ValidationReport<TypeElement> validateUncached(
-      TypeElement module, Set<TypeElement> visitedModules) {
-    ValidationReport.Builder<TypeElement> builder = ValidationReport.about(module);
-    ModuleKind moduleKind = ModuleKind.forAnnotatedElement(module).get();
-    TypeElement contributesAndroidInjectorElement =
-        elements.getTypeElement(CONTRIBUTES_ANDROID_INJECTOR_NAME);
-    TypeMirror contributesAndroidInjector =
-        contributesAndroidInjectorElement != null
-            ? contributesAndroidInjectorElement.asType()
-            : null;
-    List<ExecutableElement> moduleMethods = methodsIn(module.getEnclosedElements());
-    List<ExecutableElement> bindingMethods = new ArrayList<>();
-    for (ExecutableElement moduleMethod : moduleMethods) {
-      if (anyBindingMethodValidator.isBindingMethod(moduleMethod)) {
-        builder.addSubreport(anyBindingMethodValidator.validate(moduleMethod));
-        bindingMethods.add(moduleMethod);
-      }
-
-      for (AnnotationMirror annotation : moduleMethod.getAnnotationMirrors()) {
-        if (!ANDROID_PROCESSOR.isPresent()
-            && MoreTypes.equivalence()
-                .equivalent(contributesAndroidInjector, annotation.getAnnotationType())) {
-          builder.addSubreport(
-              ValidationReport.about(moduleMethod)
-                  .addError(
-                      String.format(
-                          "@%s was used, but %s was not found on the processor path",
-                          CONTRIBUTES_ANDROID_INJECTOR_NAME, ANDROID_PROCESSOR_NAME))
-                  .build());
-          break;
-        }
-      }
-    }
-
-    if (bindingMethods.stream()
-        .map(ModuleMethodKind::ofMethod)
-        .collect(toImmutableSet())
-        .containsAll(
-            EnumSet.of(ModuleMethodKind.ABSTRACT_DECLARATION, ModuleMethodKind.INSTANCE_BINDING))) {
-      builder.addError(
-          String.format(
-              "A @%s may not contain both non-static and abstract binding methods",
-              moduleKind.annotation().getSimpleName()));
-    }
-
-    validateModuleVisibility(module, moduleKind, builder);
-
-    ImmutableListMultimap<Name, ExecutableElement> bindingMethodsByName =
-        Multimaps.index(bindingMethods, ExecutableElement::getSimpleName);
-
-    validateMethodsWithSameName(builder, bindingMethodsByName);
-    if (module.getKind() != ElementKind.INTERFACE) {
-      validateBindingMethodOverrides(
-          module,
-          builder,
-          Multimaps.index(moduleMethods, ExecutableElement::getSimpleName),
-          bindingMethodsByName);
-    }
-    validateModifiers(module, builder);
-    validateReferencedModules(module, moduleKind, visitedModules, builder);
-    validateReferencedSubcomponents(module, moduleKind, builder);
-    validateNoScopeAnnotationsOnModuleElement(module, moduleKind, builder);
-    validateSelfCycles(module, builder);
-    if (metadataUtil.hasEnclosedCompanionObject(module)) {
-      validateCompanionModule(module, builder);
-    }
-
-    if (builder.build().isClean()
-        && bindingGraphValidator.shouldDoFullBindingGraphValidation(module)) {
-      validateModuleBindings(module, builder);
-    }
-
-    return builder.build();
-  }
-
-  private void validateReferencedSubcomponents(
-      final TypeElement subject,
-      ModuleKind moduleKind,
-      final ValidationReport.Builder<TypeElement> builder) {
-    // TODO(ronshapiro): use validateTypesAreDeclared when it is checked in
-    ModuleAnnotation moduleAnnotation = moduleAnnotation(moduleKind.getModuleAnnotation(subject));
-    for (AnnotationValue subcomponentAttribute :
-        moduleAnnotation.subcomponentsAsAnnotationValues()) {
-      asType(subcomponentAttribute)
-          .accept(
-              new SimpleTypeVisitor8<Void, Void>() {
-                @Override
-                protected Void defaultAction(TypeMirror e, Void aVoid) {
-                  builder.addError(
-                      e + " is not a valid subcomponent type",
-                      subject,
-                      moduleAnnotation.annotation(),
-                      subcomponentAttribute);
-                  return null;
-                }
-
-                @Override
-                public Void visitDeclared(DeclaredType declaredType, Void aVoid) {
-                  TypeElement attributeType = asTypeElement(declaredType);
-                  if (isAnyAnnotationPresent(attributeType, SUBCOMPONENT_TYPES)) {
-                    validateSubcomponentHasBuilder(
-                        attributeType, moduleAnnotation.annotation(), builder);
-                  } else {
-                    builder.addError(
-                        isAnyAnnotationPresent(attributeType, SUBCOMPONENT_CREATOR_TYPES)
-                            ? moduleSubcomponentsIncludesCreator(attributeType)
-                            : moduleSubcomponentsIncludesNonSubcomponent(attributeType),
-                        subject,
-                        moduleAnnotation.annotation(),
-                        subcomponentAttribute);
-                  }
-
-                  return null;
-                }
-              },
-              null);
-    }
-  }
-
-  private static String moduleSubcomponentsIncludesNonSubcomponent(TypeElement notSubcomponent) {
-    return notSubcomponent.getQualifiedName()
-        + " is not a @Subcomponent or @ProductionSubcomponent";
-  }
-
-  private static String moduleSubcomponentsIncludesCreator(
-      TypeElement moduleSubcomponentsAttribute) {
-    TypeElement subcomponentType =
-        MoreElements.asType(moduleSubcomponentsAttribute.getEnclosingElement());
-    ComponentCreatorAnnotation creatorAnnotation =
-        getOnlyElement(getCreatorAnnotations(moduleSubcomponentsAttribute));
-    return String.format(
-        "%s is a @%s.%s. Did you mean to use %s?",
-        moduleSubcomponentsAttribute.getQualifiedName(),
-        subcomponentAnnotation(subcomponentType).get().simpleName(),
-        creatorAnnotation.creatorKind().typeName(),
-        subcomponentType.getQualifiedName());
-  }
-
-  private static void validateSubcomponentHasBuilder(
-      TypeElement subcomponentAttribute,
-      AnnotationMirror moduleAnnotation,
-      ValidationReport.Builder<TypeElement> builder) {
-    if (getSubcomponentCreator(subcomponentAttribute).isPresent()) {
-      return;
-    }
-    builder.addError(
-        moduleSubcomponentsDoesntHaveCreator(subcomponentAttribute, moduleAnnotation),
-        builder.getSubject(),
-        moduleAnnotation);
-  }
-
-  private static String moduleSubcomponentsDoesntHaveCreator(
-      TypeElement subcomponent, AnnotationMirror moduleAnnotation) {
-    return String.format(
-        "%1$s doesn't have a @%2$s.Builder or @%2$s.Factory, which is required when used with "
-            + "@%3$s.subcomponents",
-        subcomponent.getQualifiedName(),
-        subcomponentAnnotation(subcomponent).get().simpleName(),
-        simpleName(moduleAnnotation));
-  }
-
-  enum ModuleMethodKind {
-    ABSTRACT_DECLARATION,
-    INSTANCE_BINDING,
-    STATIC_BINDING,
-    ;
-
-    static ModuleMethodKind ofMethod(ExecutableElement moduleMethod) {
-      if (moduleMethod.getModifiers().contains(STATIC)) {
-        return STATIC_BINDING;
-      } else if (moduleMethod.getModifiers().contains(ABSTRACT)) {
-        return ABSTRACT_DECLARATION;
-      } else {
-        return INSTANCE_BINDING;
-      }
-    }
-  }
-
-  private void validateModifiers(
-      TypeElement subject, ValidationReport.Builder<TypeElement> builder) {
-    // This coupled with the check for abstract modules in ComponentValidator guarantees that
-    // only modules without type parameters are referenced from @Component(modules={...}).
-    if (!subject.getTypeParameters().isEmpty() && !subject.getModifiers().contains(ABSTRACT)) {
-      builder.addError("Modules with type parameters must be abstract", subject);
-    }
-  }
-
-  private void validateMethodsWithSameName(
-      ValidationReport.Builder<TypeElement> builder,
-      ListMultimap<Name, ExecutableElement> bindingMethodsByName) {
-    for (Entry<Name, Collection<ExecutableElement>> entry :
-        bindingMethodsByName.asMap().entrySet()) {
-      if (entry.getValue().size() > 1) {
-        for (ExecutableElement offendingMethod : entry.getValue()) {
-          builder.addError(
-              String.format(
-                  "Cannot have more than one binding method with the same name in a single module"),
-              offendingMethod);
-        }
-      }
-    }
-  }
-
-  private void validateReferencedModules(
-      TypeElement subject,
-      ModuleKind moduleKind,
-      Set<TypeElement> visitedModules,
-      ValidationReport.Builder<TypeElement> builder) {
-    // Validate that all the modules we include are valid for inclusion.
-    AnnotationMirror mirror = moduleKind.getModuleAnnotation(subject);
-    builder.addSubreport(
-        validateReferencedModules(
-            subject, mirror, moduleKind.legalIncludedModuleKinds(), visitedModules));
-  }
-
-  /**
-   * Validates modules included in a given module or installed in a given component.
-   *
-   * <p>Checks that the referenced modules are non-generic types annotated with {@code @Module} or
-   * {@code @ProducerModule}.
-   *
-   * <p>If the referenced module is in the {@linkplain #addKnownModules(Collection) known modules
-   * set} and has errors, reports an error at that module's inclusion.
-   *
-   * @param annotatedType the annotated module or component
-   * @param annotation the annotation specifying the referenced modules ({@code @Component},
-   *     {@code @ProductionComponent}, {@code @Subcomponent}, {@code @ProductionSubcomponent},
-   *     {@code @Module}, or {@code @ProducerModule})
-   * @param validModuleKinds the module kinds that the annotated type is permitted to include
-   */
-  ValidationReport<TypeElement> validateReferencedModules(
-      TypeElement annotatedType,
-      AnnotationMirror annotation,
-      ImmutableSet<ModuleKind> validModuleKinds,
-      Set<TypeElement> visitedModules) {
-    ValidationReport.Builder<TypeElement> subreport = ValidationReport.about(annotatedType);
-    ImmutableSet<? extends Class<? extends Annotation>> validModuleAnnotations =
-        validModuleKinds.stream().map(ModuleKind::annotation).collect(toImmutableSet());
-
-    for (AnnotationValue includedModule : getModules(annotation)) {
-      asType(includedModule)
-          .accept(
-              new SimpleTypeVisitor8<Void, Void>() {
-                @Override
-                protected Void defaultAction(TypeMirror mirror, Void p) {
-                  reportError("%s is not a valid module type.", mirror);
-                  return null;
-                }
-
-                @Override
-                public Void visitDeclared(DeclaredType t, Void p) {
-                  TypeElement module = MoreElements.asType(t.asElement());
-                  if (!t.getTypeArguments().isEmpty()) {
-                    reportError(
-                        "%s is listed as a module, but has type parameters",
-                        module.getQualifiedName());
-                  }
-                  if (!isAnyAnnotationPresent(module, validModuleAnnotations)) {
-                    reportError(
-                        "%s is listed as a module, but is not annotated with %s",
-                        module.getQualifiedName(),
-                        (validModuleAnnotations.size() > 1 ? "one of " : "")
-                            + validModuleAnnotations.stream()
-                                .map(otherClass -> "@" + otherClass.getSimpleName())
-                                .collect(joining(", ")));
-                  } else if (knownModules.contains(module)
-                      && !validate(module, visitedModules).isClean()) {
-                    reportError("%s has errors", module.getQualifiedName());
-                  }
-                  if (metadataUtil.isCompanionObjectClass(module)) {
-                    reportError(
-                        "%s is listed as a module, but it is a companion object class. "
-                            + "Add @Module to the enclosing class and reference that instead.",
-                        module.getQualifiedName());
-                  }
-                  return null;
-                }
-
-                @FormatMethod
-                private void reportError(String format, Object... args) {
-                  subreport.addError(
-                      String.format(format, args), annotatedType, annotation, includedModule);
-                }
-              },
-              null);
-    }
-    return subreport.build();
-  }
-
-  private static ImmutableList<AnnotationValue> getModules(AnnotationMirror annotation) {
-    if (isModuleAnnotation(annotation)) {
-      return moduleAnnotation(annotation).includesAsAnnotationValues();
-    }
-    if (isComponentAnnotation(annotation)) {
-      return componentAnnotation(annotation).moduleValues();
-    }
-    throw new IllegalArgumentException(String.format("unsupported annotation: %s", annotation));
-  }
-
-  private void validateBindingMethodOverrides(
-      TypeElement subject,
-      ValidationReport.Builder<TypeElement> builder,
-      ImmutableListMultimap<Name, ExecutableElement> moduleMethodsByName,
-      ImmutableListMultimap<Name, ExecutableElement> bindingMethodsByName) {
-    // For every binding method, confirm it overrides nothing *and* nothing overrides it.
-    // Consider the following hierarchy:
-    // class Parent {
-    //    @Provides Foo a() {}
-    //    @Provides Foo b() {}
-    //    Foo c() {}
-    // }
-    // class Child extends Parent {
-    //    @Provides Foo a() {}
-    //    Foo b() {}
-    //    @Provides Foo c() {}
-    // }
-    // In each of those cases, we want to fail.  "a" is clear, "b" because Child is overriding
-    // a binding method in Parent, and "c" because Child is defining a binding method that overrides
-    // Parent.
-    TypeElement currentClass = subject;
-    TypeMirror objectType = elements.getTypeElement(Object.class).asType();
-    // We keep track of methods that failed so we don't spam with multiple failures.
-    Set<ExecutableElement> failedMethods = Sets.newHashSet();
-    ListMultimap<Name, ExecutableElement> allMethodsByName =
-        MultimapBuilder.hashKeys().arrayListValues().build(moduleMethodsByName);
-
-    while (!types.isSameType(currentClass.getSuperclass(), objectType)) {
-      currentClass = MoreElements.asType(types.asElement(currentClass.getSuperclass()));
-      List<ExecutableElement> superclassMethods = methodsIn(currentClass.getEnclosedElements());
-      for (ExecutableElement superclassMethod : superclassMethods) {
-        Name name = superclassMethod.getSimpleName();
-        // For each method in the superclass, confirm our binding methods don't override it
-        for (ExecutableElement bindingMethod : bindingMethodsByName.get(name)) {
-          if (failedMethods.add(bindingMethod)
-              && elements.overrides(bindingMethod, superclassMethod, subject)) {
-            builder.addError(
-                String.format(
-                    "Binding methods may not override another method. Overrides: %s",
-                    methodSignatureFormatter.format(superclassMethod)),
-                bindingMethod);
-          }
-        }
-        // For each binding method in superclass, confirm our methods don't override it.
-        if (anyBindingMethodValidator.isBindingMethod(superclassMethod)) {
-          for (ExecutableElement method : allMethodsByName.get(name)) {
-            if (failedMethods.add(method)
-                && elements.overrides(method, superclassMethod, subject)) {
-              builder.addError(
-                  String.format(
-                      "Binding methods may not be overridden in modules. Overrides: %s",
-                      methodSignatureFormatter.format(superclassMethod)),
-                  method);
-            }
-          }
-        }
-        allMethodsByName.put(superclassMethod.getSimpleName(), superclassMethod);
-      }
-    }
-  }
-
-  private void validateModuleVisibility(
-      final TypeElement moduleElement,
-      ModuleKind moduleKind,
-      final ValidationReport.Builder<?> reportBuilder) {
-    ModuleAnnotation moduleAnnotation =
-        moduleAnnotation(getAnnotationMirror(moduleElement, moduleKind.annotation()).get());
-    Visibility moduleVisibility = Visibility.ofElement(moduleElement);
-    Visibility moduleEffectiveVisibility = effectiveVisibilityOfElement(moduleElement);
-    if (moduleVisibility.equals(PRIVATE)) {
-      reportBuilder.addError("Modules cannot be private.", moduleElement);
-    } else if (moduleEffectiveVisibility.equals(PRIVATE)) {
-      reportBuilder.addError("Modules cannot be enclosed in private types.", moduleElement);
-    }
-
-    switch (moduleElement.getNestingKind()) {
-      case ANONYMOUS:
-        throw new IllegalStateException("Can't apply @Module to an anonymous class");
-      case LOCAL:
-        throw new IllegalStateException("Local classes shouldn't show up in the processor");
-      case MEMBER:
-      case TOP_LEVEL:
-        if (moduleEffectiveVisibility.equals(PUBLIC)) {
-          ImmutableSet<TypeElement> invalidVisibilityIncludes =
-              getModuleIncludesWithInvalidVisibility(moduleAnnotation);
-          if (!invalidVisibilityIncludes.isEmpty()) {
-            reportBuilder.addError(
-                String.format(
-                    "This module is public, but it includes non-public (or effectively non-public) "
-                        + "modules (%s) that have non-static, non-abstract binding methods. Either "
-                        + "reduce the visibility of this module, make the included modules "
-                        + "public, or make all of the binding methods on the included modules "
-                        + "abstract or static.",
-                    formatListForErrorMessage(invalidVisibilityIncludes.asList())),
-                moduleElement);
-          }
-        }
-    }
-  }
-
-  private ImmutableSet<TypeElement> getModuleIncludesWithInvalidVisibility(
-      ModuleAnnotation moduleAnnotation) {
-    return moduleAnnotation.includes().stream()
-        .filter(include -> !effectiveVisibilityOfElement(include).equals(PUBLIC))
-        .filter(this::requiresModuleInstance)
-        .collect(toImmutableSet());
-  }
-
-  /**
-   * Returns {@code true} if a module instance is needed for any of the binding methods on the given
-   * {@code module}. This is the case when the module has any binding methods that are neither
-   * {@code abstract} nor {@code static}. Alternatively, if the module is a Kotlin Object then the
-   * binding methods are considered {@code static}, requiring no module instance.
-   */
-  private boolean requiresModuleInstance(TypeElement module) {
-    // Note elements.getAllMembers(module) rather than module.getEnclosedElements() here: we need to
-    // include binding methods declared in supertypes because unlike most other validations being
-    // done in this class, which assume that supertype binding methods will be validated in a
-    // separate call to the validator since the supertype itself must be a @Module, we need to look
-    // at all the binding methods in the module's type hierarchy here.
-    boolean isKotlinObject =
-        metadataUtil.isObjectClass(module) || metadataUtil.isCompanionObjectClass(module);
-    if (isKotlinObject) {
-      return false;
-    }
-    return methodsIn(elements.getAllMembers(module)).stream()
-        .filter(anyBindingMethodValidator::isBindingMethod)
-        .map(ExecutableElement::getModifiers)
-        .anyMatch(modifiers -> !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC));
-  }
-
-  private void validateNoScopeAnnotationsOnModuleElement(
-      TypeElement module, ModuleKind moduleKind, ValidationReport.Builder<TypeElement> report) {
-    for (AnnotationMirror scope : getAnnotatedAnnotations(module, Scope.class)) {
-      report.addError(
-          String.format(
-              "@%ss cannot be scoped. Did you mean to scope a method instead?",
-              moduleKind.annotation().getSimpleName()),
-          module,
-          scope);
-    }
-  }
-
-  private void validateSelfCycles(
-      TypeElement module, ValidationReport.Builder<TypeElement> builder) {
-    ModuleAnnotation moduleAnnotation = moduleAnnotation(module).get();
-    moduleAnnotation
-        .includesAsAnnotationValues()
-        .forEach(
-            value ->
-                value.accept(
-                    new SimpleAnnotationValueVisitor8<Void, Void>() {
-                      @Override
-                      public Void visitType(TypeMirror includedModule, Void aVoid) {
-                        if (MoreTypes.equivalence().equivalent(module.asType(), includedModule)) {
-                          String moduleKind = moduleAnnotation.annotationName();
-                          builder.addError(
-                              String.format("@%s cannot include themselves.", moduleKind),
-                              module,
-                              moduleAnnotation.annotation(),
-                              value);
-                        }
-                        return null;
-                      }
-                    },
-                    null));
-  }
-
-  private void validateCompanionModule(
-      TypeElement module, ValidationReport.Builder<TypeElement> builder) {
-    checkArgument(metadataUtil.hasEnclosedCompanionObject(module));
-    TypeElement companionModule = metadataUtil.getEnclosedCompanionObject(module);
-    List<ExecutableElement> companionModuleMethods =
-        methodsIn(companionModule.getEnclosedElements());
-    List<ExecutableElement> companionBindingMethods = new ArrayList<>();
-    for (ExecutableElement companionModuleMethod : companionModuleMethods) {
-      if (anyBindingMethodValidator.isBindingMethod(companionModuleMethod)) {
-        builder.addSubreport(anyBindingMethodValidator.validate(companionModuleMethod));
-        companionBindingMethods.add(companionModuleMethod);
-      }
-
-      // On normal modules only overriding other binding methods is disallowed, but for companion
-      // objects we are prohibiting any override. For this can rely on checking the @Override
-      // annotation since the Kotlin compiler will always produce them for overriding methods.
-      if (isAnnotationPresent(companionModuleMethod, Override.class)) {
-        builder.addError(
-            "Binding method in companion object may not override another method.",
-            companionModuleMethod);
-      }
-
-      // TODO(danysantiago): Be strict about the usage of @JvmStatic, i.e. tell user to remove it.
-    }
-
-    ImmutableListMultimap<Name, ExecutableElement> bindingMethodsByName =
-        Multimaps.index(companionBindingMethods, ExecutableElement::getSimpleName);
-    validateMethodsWithSameName(builder, bindingMethodsByName);
-
-    // If there are provision methods, then check the visibility. Companion objects are composed by
-    // an inner class and a static field, it is not enough to check the visibility on the type
-    // element or the field, therefore we check the metadata.
-    if (!companionBindingMethods.isEmpty() && metadataUtil.isVisibilityPrivate(companionModule)) {
-      builder.addError(
-          "A Companion Module with binding methods cannot be private.", companionModule);
-    }
-  }
-
-  private void validateModuleBindings(
-      TypeElement module, ValidationReport.Builder<TypeElement> report) {
-    BindingGraph bindingGraph =
-        bindingGraphFactory.create(
-                componentDescriptorFactory.moduleComponentDescriptor(module), true)
-            .topLevelBindingGraph();
-    if (!bindingGraphValidator.isValid(bindingGraph)) {
-      // Since the validator uses a DiagnosticReporter to report errors, the ValdiationReport won't
-      // have any Items for them. We have to tell the ValidationReport that some errors were
-      // reported for the subject.
-      report.markDirty();
-    }
-  }
-
-  private static String formatListForErrorMessage(List<?> things) {
-    switch (things.size()) {
-      case 0:
-        return "";
-      case 1:
-        return things.get(0).toString();
-      default:
-        StringBuilder output = new StringBuilder();
-        Joiner.on(", ").appendTo(output, things.subList(0, things.size() - 1));
-        output.append(" and ").append(things.get(things.size() - 1));
-        return output.toString();
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/MonitoringModuleGenerator.java b/java/dagger/internal/codegen/validation/MonitoringModuleGenerator.java
deleted file mode 100644
index 2c72e5f..0000000
--- a/java/dagger/internal/codegen/validation/MonitoringModuleGenerator.java
+++ /dev/null
@@ -1,102 +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.validation;
-
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.javapoet.TypeNames.PRODUCTION_COMPONENT_MONITOR_FACTORY;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
-import static dagger.internal.codegen.javapoet.TypeNames.setOf;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.Module;
-import dagger.Provides;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.SourceFiles;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.multibindings.Multibinds;
-import dagger.producers.ProductionScope;
-import dagger.producers.monitoring.ProductionComponentMonitor;
-import dagger.producers.monitoring.internal.Monitors;
-import java.util.Optional;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-/** Generates a monitoring module for use with production components. */
-final class MonitoringModuleGenerator extends SourceFileGenerator<TypeElement> {
-
-  @Inject
-  MonitoringModuleGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
-    super(filer, elements, sourceVersion);
-  }
-
-  @Override
-  public ClassName nameGeneratedType(TypeElement componentElement) {
-    return SourceFiles.generatedMonitoringModuleName(componentElement);
-  }
-
-  @Override
-  public Element originatingElement(TypeElement componentElement) {
-    return componentElement;
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(TypeElement componentElement) {
-    return Optional.of(
-        classBuilder(nameGeneratedType(componentElement))
-            .addAnnotation(Module.class)
-            .addModifiers(ABSTRACT)
-            .addMethod(privateConstructor())
-            .addMethod(setOfFactories())
-            .addMethod(monitor(componentElement)));
-  }
-
-  private MethodSpec privateConstructor() {
-    return constructorBuilder().addModifiers(PRIVATE).build();
-  }
-
-  private MethodSpec setOfFactories() {
-    return methodBuilder("setOfFactories")
-        .addAnnotation(Multibinds.class)
-        .addModifiers(ABSTRACT)
-        .returns(setOf(PRODUCTION_COMPONENT_MONITOR_FACTORY))
-        .build();
-  }
-
-  private MethodSpec monitor(TypeElement componentElement) {
-    return methodBuilder("monitor")
-        .returns(ProductionComponentMonitor.class)
-        .addModifiers(STATIC)
-        .addAnnotation(Provides.class)
-        .addAnnotation(ProductionScope.class)
-        .addParameter(providerOf(ClassName.get(componentElement.asType())), "component")
-        .addParameter(
-            providerOf(setOf(PRODUCTION_COMPONENT_MONITOR_FACTORY)), "factories")
-        .addStatement(
-            "return $T.createMonitorForComponent(component, factories)", Monitors.class)
-        .build();
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/MonitoringModuleProcessingStep.java b/java/dagger/internal/codegen/validation/MonitoringModuleProcessingStep.java
deleted file mode 100644
index 5d4c64e..0000000
--- a/java/dagger/internal/codegen/validation/MonitoringModuleProcessingStep.java
+++ /dev/null
@@ -1,55 +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.validation;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSet;
-import dagger.producers.ProductionComponent;
-import dagger.producers.ProductionSubcomponent;
-import java.lang.annotation.Annotation;
-import java.util.Set;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.element.TypeElement;
-
-/**
- * A processing step that is responsible for generating a special module for a {@link
- * ProductionComponent} or {@link ProductionSubcomponent}.
- */
-public final class MonitoringModuleProcessingStep extends TypeCheckingProcessingStep<TypeElement> {
-  private final Messager messager;
-  private final MonitoringModuleGenerator monitoringModuleGenerator;
-
-  @Inject
-  MonitoringModuleProcessingStep(
-      Messager messager, MonitoringModuleGenerator monitoringModuleGenerator) {
-    super(MoreElements::asType);
-    this.messager = messager;
-    this.monitoringModuleGenerator = monitoringModuleGenerator;
-  }
-
-  @Override
-  public Set<? extends Class<? extends Annotation>> annotations() {
-    return ImmutableSet.of(ProductionComponent.class, ProductionSubcomponent.class);
-  }
-
-  @Override
-  protected void process(
-      TypeElement element, ImmutableSet<Class<? extends Annotation>> annotations) {
-      monitoringModuleGenerator.generate(MoreElements.asType(element), messager);
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/MultibindingAnnotationsProcessingStep.java b/java/dagger/internal/codegen/validation/MultibindingAnnotationsProcessingStep.java
deleted file mode 100644
index fd75eac..0000000
--- a/java/dagger/internal/codegen/validation/MultibindingAnnotationsProcessingStep.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSet;
-import dagger.multibindings.ElementsIntoSet;
-import dagger.multibindings.IntoMap;
-import dagger.multibindings.IntoSet;
-import java.lang.annotation.Annotation;
-import java.util.Set;
-import javax.annotation.processing.Messager;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-
-/**
- * Processing step that verifies that {@link IntoSet}, {@link ElementsIntoSet} and {@link IntoMap}
- * are not present on non-binding methods.
- */
-public final class MultibindingAnnotationsProcessingStep
-    extends TypeCheckingProcessingStep<ExecutableElement> {
-  private final AnyBindingMethodValidator anyBindingMethodValidator;
-  private final Messager messager;
-
-  @Inject
-  MultibindingAnnotationsProcessingStep(
-      AnyBindingMethodValidator anyBindingMethodValidator, Messager messager) {
-    super(MoreElements::asExecutable);
-    this.anyBindingMethodValidator = anyBindingMethodValidator;
-    this.messager = messager;
-  }
-
-  @Override
-  public Set<? extends Class<? extends Annotation>> annotations() {
-    return ImmutableSet.of(IntoSet.class, ElementsIntoSet.class, IntoMap.class);
-  }
-
-  @Override
-  protected void process(
-      ExecutableElement method, ImmutableSet<Class<? extends Annotation>> annotations) {
-    if (!anyBindingMethodValidator.isBindingMethod(method)) {
-      annotations.forEach(
-          annotation ->
-              messager.printMessage(
-                  ERROR,
-                  "Multibinding annotations may only be on @Provides, @Produces, or @Binds methods",
-                  method,
-                  getAnnotationMirror(method, annotation).get()));
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/MultibindsMethodValidator.java b/java/dagger/internal/codegen/validation/MultibindsMethodValidator.java
deleted file mode 100644
index 8829667..0000000
--- a/java/dagger/internal/codegen/validation/MultibindsMethodValidator.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2016 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.validation;
-
-import static dagger.internal.codegen.base.FrameworkTypes.isFrameworkType;
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS;
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.NO_SCOPING;
-import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
-import static dagger.internal.codegen.validation.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableSet;
-import dagger.Module;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.multibindings.Multibinds;
-import dagger.producers.ProducerModule;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.TypeMirror;
-
-/** A validator for {@link Multibinds} methods. */
-class MultibindsMethodValidator extends BindingMethodValidator {
-
-  /** Creates a validator for {@link Multibinds @Multibinds} methods. */
-  @Inject
-  MultibindsMethodValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil kotlinMetadataUtil,
-      DependencyRequestValidator dependencyRequestValidator,
-      InjectionAnnotations injectionAnnotations) {
-    super(
-        elements,
-        types,
-        kotlinMetadataUtil,
-        Multibinds.class,
-        ImmutableSet.of(Module.class, ProducerModule.class),
-        dependencyRequestValidator,
-        MUST_BE_ABSTRACT,
-        NO_EXCEPTIONS,
-        NO_MULTIBINDINGS,
-        NO_SCOPING,
-        injectionAnnotations);
-  }
-
-  @Override
-  protected ElementValidator elementValidator(ExecutableElement element) {
-    return new Validator(element);
-  }
-
-  private class Validator extends MethodValidator {
-    Validator(ExecutableElement element) {
-      super(element);
-    }
-
-    @Override
-    protected void checkParameters() {
-      if (!element.getParameters().isEmpty()) {
-        report.addError(bindingMethods("cannot have parameters"));
-      }
-    }
-
-    /** Adds an error unless the method returns a {@code Map<K, V>} or {@code Set<T>}. */
-    @Override
-    protected void checkType() {
-      if (!isPlainMap(element.getReturnType())
-          && !isPlainSet(element.getReturnType())) {
-        report.addError(bindingMethods("must return Map<K, V> or Set<T>"));
-      }
-    }
-
-    private boolean isPlainMap(TypeMirror returnType) {
-      if (!MapType.isMap(returnType)) {
-        return false;
-      }
-      MapType mapType = MapType.from(returnType);
-      return !mapType.isRawType()
-          && MoreTypes.isType(mapType.valueType()) // No wildcards.
-          && !isFrameworkType(mapType.valueType());
-    }
-
-    private boolean isPlainSet(TypeMirror returnType) {
-      if (!SetType.isSet(returnType)) {
-        return false;
-      }
-      SetType setType = SetType.from(returnType);
-      return !setType.isRawType()
-          && MoreTypes.isType(setType.elementType()) // No wildcards.
-          && !isFrameworkType(setType.elementType());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/PackageNameCompressor.java b/java/dagger/internal/codegen/validation/PackageNameCompressor.java
deleted file mode 100644
index 6b7c720..0000000
--- a/java/dagger/internal/codegen/validation/PackageNameCompressor.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2020 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.validation;
-
-import static java.util.Comparator.comparing;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Munges an error message to remove/shorten package names and adds a legend at the end.
- */
-final class PackageNameCompressor {
-
-  static final String LEGEND_HEADER =
-      "\n\n======================\nFull classname legend:\n======================\n";
-  static final String LEGEND_FOOTER =
-      "========================\nEnd of classname legend:\n========================\n";
-
-  private static final ImmutableSet<String> PACKAGES_SKIPPED_IN_LEGEND = ImmutableSet.of(
-      "java.lang.",
-      "java.util.");
-
-  private static final Splitter PACKAGE_SPLITTER = Splitter.on('.');
-
-  private static final Joiner PACKAGE_JOINER = Joiner.on('.');
-
-  // TODO(erichang): Consider validating this regex by also passing in all of the known types from
-  // keys, module names, component names, etc and checking against that list. This may have some
-  // extra complications with taking apart types like List<Foo> to get the inner class names.
-  private static final Pattern CLASSNAME_PATTERN =
-      // Match lowercase package names with trailing dots. Start with a non-word character so we
-      // don't match substrings in like Bar.Foo and match the ar.Foo. Start a group to not include
-      // the non-word character.
-      Pattern.compile("[\\W](([a-z_0-9]++[.])++"
-          // Then match a name starting with an uppercase letter. This is the outer class name.
-          + "[A-Z][\\w$]++)");
-
-  /**
-   * Compresses an error message by stripping the packages out of class names and adding them
-   * to a legend at the bottom of the error.
-   */
-  static String compressPackagesInMessage(String input) {
-    Matcher matcher = CLASSNAME_PATTERN.matcher(input);
-
-    Set<String> names = new HashSet<>();
-    // Find all classnames in the error. Note that if our regex isn't complete, it just means the
-    // classname is left in the full form, which is a fine fallback.
-    while (matcher.find()) {
-      String name = matcher.group(1);
-      names.add(name);
-    }
-    // Now dedupe any conflicts. Use a TreeMap since we're going to need the legend sorted anyway.
-    // This map is from short name to full name.
-    Map<String, String> replacementMap = shortenNames(names);
-
-    // If we have nothing to replace, just return the original.
-    if (replacementMap.isEmpty()) {
-      return input;
-    }
-
-    // Find the longest key for building the legend
-    int longestKey = replacementMap.keySet().stream().max(comparing(String::length)).get().length();
-
-    String replacedString = input;
-    StringBuilder legendBuilder = new StringBuilder();
-    for (Map.Entry<String, String> entry : replacementMap.entrySet()) {
-      String shortName = entry.getKey();
-      String fullName = entry.getValue();
-      // Do the replacements in the message
-      replacedString = replacedString.replace(fullName, shortName);
-
-      // Skip certain prefixes. We need to check the shortName for a . though in case
-      // there was some type of conflict like java.util.concurrent.Future and
-      // java.util.foo.Future that got shortened to concurrent.Future and foo.Future.
-      // In those cases we do not want to skip the legend. We only skip if the class
-      // is directly in that package.
-      String prefix = fullName.substring(0, fullName.length() - shortName.length());
-      if (PACKAGES_SKIPPED_IN_LEGEND.contains(prefix) && !shortName.contains(".")) {
-        continue;
-      }
-
-      // Add to the legend
-      legendBuilder
-          .append(shortName)
-          .append(": ")
-          // Add enough spaces to adjust the columns
-          .append(Strings.repeat(" ", longestKey - shortName.length()))
-          .append(fullName)
-          .append("\n");
-    }
-
-    return legendBuilder.length() == 0 ? replacedString
-        : replacedString + LEGEND_HEADER + legendBuilder + LEGEND_FOOTER;
-  }
-
-  /**
-   * Returns a map from short name to full name after resolving conflicts. This resolves conflicts
-   * by adding on segments of the package name until they are unique. For example, com.foo.Baz and
-   * com.bar.Baz will conflict on Baz and then resolve with foo.Baz and bar.Baz as replacements.
-   */
-  private static Map<String, String> shortenNames(Collection<String> names) {
-    HashMultimap<String, List<String>> shortNameToPartsMap = HashMultimap.create();
-    for (String name : names) {
-      List<String> parts = new ArrayList<>(PACKAGE_SPLITTER.splitToList(name));
-      // Start with the just the class name as the simple name
-      String className = parts.remove(parts.size() - 1);
-      shortNameToPartsMap.put(className, parts);
-    }
-
-    // Iterate through looking for conflicts adding the next part of the package until there are no
-    // more conflicts
-    while (true) {
-      // Save the keys with conflicts to avoid concurrent modification issues
-      List<String> conflictingShortNames = new ArrayList<>();
-      for (Map.Entry<String, Collection<List<String>>> entry
-          : shortNameToPartsMap.asMap().entrySet()) {
-        if (entry.getValue().size() > 1) {
-          conflictingShortNames.add(entry.getKey());
-        }
-      }
-
-      if (conflictingShortNames.isEmpty()) {
-        break;
-      }
-
-      // For all conflicts, add in the next part of the package
-      for (String conflictingShortName : conflictingShortNames) {
-        Set<List<String>> partsCollection = shortNameToPartsMap.removeAll(conflictingShortName);
-        for (List<String> parts : partsCollection) {
-          String newShortName = parts.remove(parts.size() - 1) + "." + conflictingShortName;
-          // If we've removed the last part of the package, then just skip it entirely because
-          // now we're not shortening it at all.
-          if (!parts.isEmpty()) {
-            shortNameToPartsMap.put(newShortName, parts);
-          }
-        }
-      }
-    }
-
-    // Turn the multimap into a regular map now that conflicts have been resolved. Use a TreeMap
-    // since we're going to need the legend sorted anyway. This map is from short name to full name.
-    Map<String, String> replacementMap = new TreeMap<>();
-    for (Map.Entry<String, Collection<List<String>>> entry
-        : shortNameToPartsMap.asMap().entrySet()) {
-      replacementMap.put(
-          entry.getKey(),
-          PACKAGE_JOINER.join(Iterables.getOnlyElement(entry.getValue())) + "." + entry.getKey());
-    }
-    return replacementMap;
-  }
-
-  private PackageNameCompressor() {}
-}
diff --git a/java/dagger/internal/codegen/validation/ProducesMethodValidator.java b/java/dagger/internal/codegen/validation/ProducesMethodValidator.java
deleted file mode 100644
index 1606ebe..0000000
--- a/java/dagger/internal/codegen/validation/ProducesMethodValidator.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2014 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.validation;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.NO_SCOPING;
-import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_CONCRETE;
-import static dagger.internal.codegen.validation.BindingMethodValidator.ExceptionSuperclass.EXCEPTION;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.util.concurrent.ListenableFuture;
-import dagger.internal.codegen.binding.ConfigurationAnnotations;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.multibindings.ElementsIntoSet;
-import dagger.producers.ProducerModule;
-import dagger.producers.Produces;
-import java.util.Optional;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/** A validator for {@link Produces} methods. */
-final class ProducesMethodValidator extends BindingMethodValidator {
-
-  @Inject
-  ProducesMethodValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil kotlinMetadataUtil,
-      DependencyRequestValidator dependencyRequestValidator,
-      InjectionAnnotations injectionAnnotations) {
-    super(
-        elements,
-        types,
-        kotlinMetadataUtil,
-        dependencyRequestValidator,
-        Produces.class,
-        ProducerModule.class,
-        MUST_BE_CONCRETE,
-        EXCEPTION,
-        ALLOWS_MULTIBINDINGS,
-        NO_SCOPING,
-        injectionAnnotations);
-  }
-
-  @Override
-  protected String elementsIntoSetNotASetMessage() {
-    return "@Produces methods of type set values must return a Set or ListenableFuture of Set";
-  }
-
-  @Override
-  protected String badTypeMessage() {
-    return "@Produces methods can return only a primitive, an array, a type variable, "
-        + "a declared type, or a ListenableFuture of one of those types";
-  }
-
-  @Override
-  protected ElementValidator elementValidator(ExecutableElement element) {
-    return new Validator(element);
-  }
-
-  private class Validator extends MethodValidator {
-    Validator(ExecutableElement element) {
-      super(element);
-    }
-
-    @Override
-    protected void checkAdditionalMethodProperties() {
-      checkNullable();
-    }
-
-    /** Adds a warning if a {@link Produces @Produces} method is declared nullable. */
-    // TODO(beder): Properly handle nullable with producer methods.
-    private void checkNullable() {
-      if (ConfigurationAnnotations.getNullableType(element).isPresent()) {
-        report.addWarning("@Nullable on @Produces methods does not do anything");
-      }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>Allows {@code keyType} to be a {@link ListenableFuture} of an otherwise-valid key type.
-     */
-    @Override
-    protected void checkKeyType(TypeMirror keyType) {
-      Optional<TypeMirror> typeToCheck = unwrapListenableFuture(keyType);
-      if (typeToCheck.isPresent()) {
-        super.checkKeyType(typeToCheck.get());
-      }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>Allows an {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} method to return
-     * a {@link ListenableFuture} of a {@link Set} as well.
-     */
-    @Override
-    protected void checkSetValuesType() {
-      Optional<TypeMirror> typeToCheck = unwrapListenableFuture(element.getReturnType());
-      if (typeToCheck.isPresent()) {
-        checkSetValuesType(typeToCheck.get());
-      }
-    }
-
-    private Optional<TypeMirror> unwrapListenableFuture(TypeMirror type) {
-      if (MoreTypes.isType(type) && MoreTypes.isTypeOf(ListenableFuture.class, type)) {
-        DeclaredType declaredType = MoreTypes.asDeclared(type);
-        if (declaredType.getTypeArguments().isEmpty()) {
-          report.addError("@Produces methods cannot return a raw ListenableFuture");
-          return Optional.empty();
-        } else {
-          return Optional.of((TypeMirror) getOnlyElement(declaredType.getTypeArguments()));
-        }
-      }
-      return Optional.of(type);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/ProvidesMethodValidator.java b/java/dagger/internal/codegen/validation/ProvidesMethodValidator.java
deleted file mode 100644
index 6b4f303..0000000
--- a/java/dagger/internal/codegen/validation/ProvidesMethodValidator.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2014 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.validation;
-
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
-import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.ALLOWS_SCOPING;
-import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_CONCRETE;
-import static dagger.internal.codegen.validation.BindingMethodValidator.ExceptionSuperclass.RUNTIME_EXCEPTION;
-
-import com.google.common.collect.ImmutableSet;
-import dagger.Module;
-import dagger.Provides;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.producers.ProducerModule;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.VariableElement;
-
-/** A validator for {@link Provides} methods. */
-final class ProvidesMethodValidator extends BindingMethodValidator {
-
-  private final DependencyRequestValidator dependencyRequestValidator;
-
-  @Inject
-  ProvidesMethodValidator(
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil kotlinMetadataUtil,
-      DependencyRequestValidator dependencyRequestValidator,
-      InjectionAnnotations injectionAnnotations) {
-    super(
-        elements,
-        types,
-        kotlinMetadataUtil,
-        Provides.class,
-        ImmutableSet.of(Module.class, ProducerModule.class),
-        dependencyRequestValidator,
-        MUST_BE_CONCRETE,
-        RUNTIME_EXCEPTION,
-        ALLOWS_MULTIBINDINGS,
-        ALLOWS_SCOPING,
-        injectionAnnotations);
-    this.dependencyRequestValidator = dependencyRequestValidator;
-  }
-
-  @Override
-  protected ElementValidator elementValidator(ExecutableElement element) {
-    return new Validator(element);
-  }
-
-  private class Validator extends MethodValidator {
-    Validator(ExecutableElement element) {
-      super(element);
-    }
-
-    @Override
-    protected void checkAdditionalMethodProperties() {
-    }
-
-    /** Adds an error if a {@link Provides @Provides} method depends on a producer type. */
-    @Override
-    protected void checkParameter(VariableElement parameter) {
-      super.checkParameter(parameter);
-      dependencyRequestValidator.checkNotProducer(report, parameter);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/TypeCheckingProcessingStep.java b/java/dagger/internal/codegen/validation/TypeCheckingProcessingStep.java
deleted file mode 100644
index 57867f1..0000000
--- a/java/dagger/internal/codegen/validation/TypeCheckingProcessingStep.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.validation;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.SetMultimap;
-import java.lang.annotation.Annotation;
-import java.util.function.Function;
-import javax.lang.model.element.Element;
-
-/**
- * A {@link ProcessingStep} that processes one element at a time and defers any for which {@link
- * TypeNotPresentException} is thrown.
- */
-// TODO(dpb): Contribute to auto-common.
-public abstract class TypeCheckingProcessingStep<E extends Element> implements ProcessingStep {
-  private final Function<Element, E> downcaster;
-
-  protected TypeCheckingProcessingStep(Function<Element, E> downcaster) {
-    this.downcaster = checkNotNull(downcaster);
-  }
-
-  @Override
-  public ImmutableSet<Element> process(
-      SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
-    ImmutableSet.Builder<Element> deferredElements = ImmutableSet.builder();
-    ImmutableSetMultimap.copyOf(elementsByAnnotation)
-        .inverse()
-        .asMap()
-        .forEach(
-            (element, annotations) -> {
-              try {
-                process(downcaster.apply(element), ImmutableSet.copyOf(annotations));
-              } catch (TypeNotPresentException e) {
-                deferredElements.add(element);
-              }
-            });
-    return deferredElements.build();
-  }
-
-  /**
-   * Processes one element. If this method throws {@link TypeNotPresentException}, the element will
-   * be deferred until the next round of processing.
-   *
-   * @param annotations the subset of {@link ProcessingStep#annotations()} that annotate {@code
-   *     element}
-   */
-  protected abstract void process(E element, ImmutableSet<Class<? extends Annotation>> annotations);
-}
diff --git a/java/dagger/internal/codegen/validation/TypeHierarchyValidator.java b/java/dagger/internal/codegen/validation/TypeHierarchyValidator.java
deleted file mode 100644
index 5fa0270..0000000
--- a/java/dagger/internal/codegen/validation/TypeHierarchyValidator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2020 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.validation;
-
-import com.google.auto.common.MoreTypes;
-import com.google.auto.common.SuperficialValidation;
-import com.google.common.base.Equivalence;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.util.ArrayDeque;
-import java.util.HashSet;
-import java.util.Queue;
-import java.util.Set;
-import javax.lang.model.type.TypeMirror;
-
-/** Utility methods for validating the type hierarchy of a given type. */
-final class TypeHierarchyValidator {
-  private TypeHierarchyValidator() {}
-
-  /**
-   * Validate the type hierarchy of the given type including all super classes, interfaces, and
-   * type parameters.
-   *
-   * @throws TypeNotPresentException if an type in the hierarchy is not valid.
-   */
-  public static void validateTypeHierarchy(TypeMirror type, DaggerTypes types) {
-    Queue<TypeMirror> queue = new ArrayDeque<>();
-    Set<Equivalence.Wrapper<TypeMirror>> queued = new HashSet<>();
-    queue.add(type);
-    queued.add(MoreTypes.equivalence().wrap(type));
-    while (!queue.isEmpty()) {
-      TypeMirror currType = queue.remove();
-      if (!SuperficialValidation.validateType(currType)) {
-        throw new TypeNotPresentException(currType.toString(), null);
-      }
-      for (TypeMirror superType : types.directSupertypes(currType)) {
-        if (queued.add(MoreTypes.equivalence().wrap(superType))) {
-          queue.add(superType);
-        }
-      }
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/validation/Validation.java b/java/dagger/internal/codegen/validation/Validation.java
deleted file mode 100644
index 620b0f0..0000000
--- a/java/dagger/internal/codegen/validation/Validation.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.validation;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import javax.inject.Qualifier;
-
-/**
- * Qualifier annotation for the {@link dagger.spi.BindingGraphPlugin}s that are used to implement
- * core Dagger validation.
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Qualifier
-public @interface Validation {}
diff --git a/java/dagger/internal/codegen/validation/ValidationReport.java b/java/dagger/internal/codegen/validation/ValidationReport.java
deleted file mode 100644
index 7f37375..0000000
--- a/java/dagger/internal/codegen/validation/ValidationReport.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2014 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.validation;
-
-import static dagger.internal.codegen.base.ElementFormatter.elementToString;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static javax.tools.Diagnostic.Kind.ERROR;
-import static javax.tools.Diagnostic.Kind.NOTE;
-import static javax.tools.Diagnostic.Kind.WARNING;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.graph.Traverser;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import com.google.errorprone.annotations.CheckReturnValue;
-import java.util.Optional;
-import javax.annotation.processing.Messager;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.tools.Diagnostic;
-import javax.tools.Diagnostic.Kind;
-
-/** A collection of issues to report for source code. */
-public final class ValidationReport<T extends Element> {
-  private static final Traverser<ValidationReport<?>> SUBREPORTS =
-      Traverser.forTree(report -> report.subreports);
-
-  private final T subject;
-  private final ImmutableSet<Item> items;
-  private final ImmutableSet<ValidationReport<?>> subreports;
-  private final boolean markedDirty;
-  private boolean hasPrintedErrors;
-
-  private ValidationReport(
-      T subject,
-      ImmutableSet<Item> items,
-      ImmutableSet<ValidationReport<?>> subreports,
-      boolean markedDirty) {
-    this.subject = subject;
-    this.items = items;
-    this.subreports = subreports;
-    this.markedDirty = markedDirty;
-  }
-
-  /** Returns the items from this report and all transitive subreports. */
-  public ImmutableSet<Item> allItems() {
-    return ImmutableSet.copyOf(SUBREPORTS.depthFirstPreOrder(this))
-        .stream()
-        .flatMap(report -> report.items.stream())
-        .collect(toImmutableSet());
-  }
-
-  /**
-   * Returns {@code true} if there are no errors in this report or any subreports and markedDirty is
-   * {@code false}.
-   */
-  public boolean isClean() {
-    if (markedDirty) {
-      return false;
-    }
-    for (Item item : items) {
-      switch (item.kind()) {
-        case ERROR:
-          return false;
-        default:
-          break;
-      }
-    }
-    for (ValidationReport<?> subreport : subreports) {
-      if (!subreport.isClean()) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Prints all messages to {@code messager} (and recurs for subreports). If a
-   * message's {@linkplain Item#element() element} is contained within the report's subject,
-   * associates the message with the message's element. Otherwise, since {@link Diagnostic}
-   * reporting is expected to be associated with elements that are currently being compiled,
-   * associates the message with the subject itself and prepends a reference to the item's element.
-   */
-  public void printMessagesTo(Messager messager) {
-    if (hasPrintedErrors) {
-      // Avoid printing the errors from this validation report more than once.
-      return;
-    }
-    hasPrintedErrors = true;
-    for (Item item : items) {
-      if (isEnclosedIn(subject, item.element())) {
-        if (item.annotation().isPresent()) {
-          if (item.annotationValue().isPresent()) {
-            messager.printMessage(
-                item.kind(),
-                item.message(),
-                item.element(),
-                item.annotation().get(),
-                item.annotationValue().get());
-          } else {
-            messager.printMessage(
-                item.kind(), item.message(), item.element(), item.annotation().get());
-          }
-        } else {
-          messager.printMessage(item.kind(), item.message(), item.element());
-        }
-      } else {
-        String message = String.format("[%s] %s", elementToString(item.element()), item.message());
-        messager.printMessage(item.kind(), message, subject);
-      }
-    }
-    for (ValidationReport<?> subreport : subreports) {
-      subreport.printMessagesTo(messager);
-    }
-  }
-
-  private static boolean isEnclosedIn(Element parent, Element child) {
-    Element current = child;
-    while (current != null) {
-      if (current.equals(parent)) {
-        return true;
-      }
-      current = current.getEnclosingElement();
-    }
-    return false;
-  }
-
-  /** Metadata about a {@link ValidationReport} item. */
-  @AutoValue
-  public abstract static class Item {
-    public abstract String message();
-    public abstract Kind kind();
-    public abstract Element element();
-    public abstract Optional<AnnotationMirror> annotation();
-    abstract Optional<AnnotationValue> annotationValue();
-  }
-
-  public static <T extends Element> Builder<T> about(T subject) {
-    return new Builder<>(subject);
-  }
-
-  /** A {@link ValidationReport} builder. */
-  @CanIgnoreReturnValue
-  public static final class Builder<T extends Element> {
-    private final T subject;
-    private final ImmutableSet.Builder<Item> items = ImmutableSet.builder();
-    private final ImmutableSet.Builder<ValidationReport<?>> subreports = ImmutableSet.builder();
-    private boolean markedDirty;
-
-    private Builder(T subject) {
-      this.subject = subject;
-    }
-
-    @CheckReturnValue
-    T getSubject() {
-      return subject;
-    }
-
-    Builder<T> addItems(Iterable<Item> newItems) {
-      items.addAll(newItems);
-      return this;
-    }
-
-    public Builder<T> addError(String message) {
-      return addError(message, subject);
-    }
-
-    public Builder<T> addError(String message, Element element) {
-      return addItem(message, ERROR, element);
-    }
-
-    public Builder<T> addError(String message, Element element, AnnotationMirror annotation) {
-      return addItem(message, ERROR, element, annotation);
-    }
-
-    public Builder<T> addError(
-        String message,
-        Element element,
-        AnnotationMirror annotation,
-        AnnotationValue annotationValue) {
-      return addItem(message, ERROR, element, annotation, annotationValue);
-    }
-
-    Builder<T> addWarning(String message) {
-      return addWarning(message, subject);
-    }
-
-    Builder<T> addWarning(String message, Element element) {
-      return addItem(message, WARNING, element);
-    }
-
-    Builder<T> addWarning(String message, Element element, AnnotationMirror annotation) {
-      return addItem(message, WARNING, element, annotation);
-    }
-
-    Builder<T> addWarning(
-        String message,
-        Element element,
-        AnnotationMirror annotation,
-        AnnotationValue annotationValue) {
-      return addItem(message, WARNING, element, annotation, annotationValue);
-    }
-
-    Builder<T> addNote(String message) {
-      return addNote(message, subject);
-    }
-
-    Builder<T> addNote(String message, Element element) {
-      return addItem(message, NOTE, element);
-    }
-
-    Builder<T> addNote(String message, Element element, AnnotationMirror annotation) {
-      return addItem(message, NOTE, element, annotation);
-    }
-
-    Builder<T> addNote(
-        String message,
-        Element element,
-        AnnotationMirror annotation,
-        AnnotationValue annotationValue) {
-      return addItem(message, NOTE, element, annotation, annotationValue);
-    }
-
-    Builder<T> addItem(String message, Kind kind, Element element) {
-      return addItem(message, kind, element, Optional.empty(), Optional.empty());
-    }
-
-    Builder<T> addItem(String message, Kind kind, Element element, AnnotationMirror annotation) {
-      return addItem(message, kind, element, Optional.of(annotation), Optional.empty());
-    }
-
-    Builder<T> addItem(
-        String message,
-        Kind kind,
-        Element element,
-        AnnotationMirror annotation,
-        AnnotationValue annotationValue) {
-      return addItem(message, kind, element, Optional.of(annotation), Optional.of(annotationValue));
-    }
-
-    private Builder<T> addItem(
-        String message,
-        Kind kind,
-        Element element,
-        Optional<AnnotationMirror> annotation,
-        Optional<AnnotationValue> annotationValue) {
-      items.add(
-          new AutoValue_ValidationReport_Item(message, kind, element, annotation, annotationValue));
-      return this;
-    }
-
-    /**
-     * If called, then {@link #isClean()} will return {@code false} even if there are no error items
-     * in the report.
-     */
-    void markDirty() {
-      this.markedDirty = true;
-    }
-
-    public Builder<T> addSubreport(ValidationReport<?> subreport) {
-      subreports.add(subreport);
-      return this;
-    }
-
-    @CheckReturnValue
-    public ValidationReport<T> build() {
-      return new ValidationReport<>(subject, items.build(), subreports.build(), markedDirty);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/AnnotationCreatorGenerator.java b/java/dagger/internal/codegen/writing/AnnotationCreatorGenerator.java
deleted file mode 100644
index 96e6340..0000000
--- a/java/dagger/internal/codegen/writing/AnnotationCreatorGenerator.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2014 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.writing;
-
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.binding.AnnotationExpression.createMethodName;
-import static dagger.internal.codegen.binding.AnnotationExpression.getAnnotationCreatorClassName;
-import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.LinkedHashSet;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.util.SimpleTypeVisitor6;
-
-/**
- * Generates classes that create annotation instances for an annotation type. The generated class
- * will have a private empty constructor, a static method that creates the annotation type itself,
- * and a static method that creates each annotation type that is nested in the top-level annotation
- * type.
- *
- * <p>So for an example annotation:
- *
- * <pre>
- *   {@literal @interface} Foo {
- *     String s();
- *     int i();
- *     Bar bar(); // an annotation defined elsewhere
- *   }
- * </pre>
- *
- * the generated class will look like:
- *
- * <pre>
- *   public final class FooCreator {
- *     private FooCreator() {}
- *
- *     public static Foo createFoo(String s, int i, Bar bar) { … }
- *     public static Bar createBar(…) { … }
- *   }
- * </pre>
- */
-public class AnnotationCreatorGenerator extends SourceFileGenerator<TypeElement> {
-  private static final ClassName AUTO_ANNOTATION =
-      ClassName.get("com.google.auto.value", "AutoAnnotation");
-
-  @Inject
-  AnnotationCreatorGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
-    super(filer, elements, sourceVersion);
-  }
-
-  @Override
-  public ClassName nameGeneratedType(TypeElement annotationType) {
-    return getAnnotationCreatorClassName(annotationType);
-  }
-
-  @Override
-  public Element originatingElement(TypeElement annotationType) {
-    return annotationType;
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(TypeElement annotationType) {
-    ClassName generatedTypeName = nameGeneratedType(annotationType);
-    TypeSpec.Builder annotationCreatorBuilder =
-        classBuilder(generatedTypeName)
-            .addModifiers(PUBLIC, FINAL)
-            .addMethod(constructorBuilder().addModifiers(PRIVATE).build());
-
-    for (TypeElement annotationElement : annotationsToCreate(annotationType)) {
-      annotationCreatorBuilder.addMethod(buildCreateMethod(generatedTypeName, annotationElement));
-    }
-
-    return Optional.of(annotationCreatorBuilder);
-  }
-
-  private MethodSpec buildCreateMethod(ClassName generatedTypeName, TypeElement annotationElement) {
-    String createMethodName = createMethodName(annotationElement);
-    MethodSpec.Builder createMethod =
-        methodBuilder(createMethodName)
-            .addAnnotation(AUTO_ANNOTATION)
-            .addModifiers(PUBLIC, STATIC)
-            .returns(TypeName.get(annotationElement.asType()));
-
-    ImmutableList.Builder<CodeBlock> parameters = ImmutableList.builder();
-    for (ExecutableElement annotationMember : methodsIn(annotationElement.getEnclosedElements())) {
-      String parameterName = annotationMember.getSimpleName().toString();
-      TypeName parameterType = TypeName.get(annotationMember.getReturnType());
-      createMethod.addParameter(parameterType, parameterName);
-      parameters.add(CodeBlock.of("$L", parameterName));
-    }
-
-    ClassName autoAnnotationClass =
-        generatedTypeName.peerClass(
-            "AutoAnnotation_" + generatedTypeName.simpleName() + "_" + createMethodName);
-    createMethod.addStatement(
-        "return new $T($L)", autoAnnotationClass, makeParametersCodeBlock(parameters.build()));
-    return createMethod.build();
-  }
-
-  /**
-   * Returns the annotation types for which {@code @AutoAnnotation static Foo createFoo(…)} methods
-   * should be written.
-   */
-  protected Set<TypeElement> annotationsToCreate(TypeElement annotationElement) {
-    return nestedAnnotationElements(annotationElement, new LinkedHashSet<>());
-  }
-
-  @CanIgnoreReturnValue
-  private static Set<TypeElement> nestedAnnotationElements(
-      TypeElement annotationElement, Set<TypeElement> annotationElements) {
-    if (annotationElements.add(annotationElement)) {
-      for (ExecutableElement method : methodsIn(annotationElement.getEnclosedElements())) {
-        TRAVERSE_NESTED_ANNOTATIONS.visit(method.getReturnType(), annotationElements);
-      }
-    }
-    return annotationElements;
-  }
-
-  private static final SimpleTypeVisitor6<Void, Set<TypeElement>> TRAVERSE_NESTED_ANNOTATIONS =
-      new SimpleTypeVisitor6<Void, Set<TypeElement>>() {
-        @Override
-        public Void visitDeclared(DeclaredType t, Set<TypeElement> p) {
-          TypeElement typeElement = MoreTypes.asTypeElement(t);
-          if (typeElement.getKind() == ElementKind.ANNOTATION_TYPE) {
-            nestedAnnotationElements(typeElement, p);
-          }
-          return null;
-        }
-      };
-}
diff --git a/java/dagger/internal/codegen/writing/AnonymousProviderCreationExpression.java b/java/dagger/internal/codegen/writing/AnonymousProviderCreationExpression.java
deleted file mode 100644
index b1237ca..0000000
--- a/java/dagger/internal/codegen/writing/AnonymousProviderCreationExpression.java
+++ /dev/null
@@ -1,60 +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.writing;
-
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.javapoet.CodeBlocks.anonymousProvider;
-import static dagger.model.RequestKind.INSTANCE;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-
-/**
- * A {@link javax.inject.Provider} creation expression for an anonymous inner class whose
- * {@code get()} method returns the expression for an instance binding request for its key.
- */
-final class AnonymousProviderCreationExpression
-    implements FrameworkInstanceCreationExpression {
-  private final ContributionBinding binding;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final ClassName requestingClass;
-
-  AnonymousProviderCreationExpression(
-      ContributionBinding binding,
-      ComponentBindingExpressions componentBindingExpressions,
-      ClassName requestingClass) {
-    this.binding = binding;
-    this.componentBindingExpressions = componentBindingExpressions;
-    this.requestingClass = requestingClass;
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    BindingRequest instanceExpressionRequest = bindingRequest(binding.key(), INSTANCE);
-    Expression instanceExpression =
-        componentBindingExpressions.getDependencyExpression(
-            instanceExpressionRequest,
-            // Not a real class name, but the actual requestingClass is an inner class within the
-            // given class, not that class itself.
-            requestingClass.nestedClass("Anonymous"));
-    return anonymousProvider(instanceExpression);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/AssistedFactoryBindingExpression.java b/java/dagger/internal/codegen/writing/AssistedFactoryBindingExpression.java
deleted file mode 100644
index d0c481c..0000000
--- a/java/dagger/internal/codegen/writing/AssistedFactoryBindingExpression.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2020 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.writing;
-
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedFactoryMethod;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedFactoryParameterSpecs;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import dagger.model.RequestKind;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-
-/**
- * A {@link dagger.internal.codegen.writing.BindingExpression} for {@link
- * dagger.assisted.AssistedFactory} methods.
- */
-final class AssistedFactoryBindingExpression extends SimpleInvocationBindingExpression {
-  private final ProvisionBinding binding;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-
-  AssistedFactoryBindingExpression(
-      ProvisionBinding binding,
-      ComponentBindingExpressions componentBindingExpressions,
-      DaggerTypes types,
-      DaggerElements elements) {
-    super(binding);
-    this.binding = checkNotNull(binding);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-    this.elements = checkNotNull(elements);
-    this.types = checkNotNull(types);
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    // An assisted factory binding should have a single request for an assisted injection type.
-    DependencyRequest assistedInjectionRequest = getOnlyElement(binding.provisionDependencies());
-    Expression assistedInjectionExpression =
-        componentBindingExpressions.getDependencyExpression(
-            BindingRequest.bindingRequest(assistedInjectionRequest.key(), RequestKind.INSTANCE),
-            // This is kind of gross because the anonymous class doesn't really have a name we can
-            // reference. The requesting class name is really only needed to determine if we need to
-            // append "OwningClass.this." to the method call or not.
-            // TODO(bcorso): We should probably use a non-anonymous class here instead so that we
-            // actually have a proper class name.
-            requestingClass.peerClass(""));
-    return Expression.create(
-        assistedInjectionExpression.type(),
-        CodeBlock.of("$L", anonymousfactoryImpl(assistedInjectionExpression)));
-  }
-
-  private TypeSpec anonymousfactoryImpl(Expression assistedInjectionExpression) {
-    TypeElement factory = asType(binding.bindingElement().get());
-    DeclaredType factoryType = asDeclared(binding.key().type());
-    ExecutableElement factoryMethod = assistedFactoryMethod(factory, elements, types);
-
-    // We can't use MethodSpec.overriding directly because we need to control the parameter names.
-    MethodSpec factoryOverride = MethodSpec.overriding(factoryMethod, factoryType, types).build();
-    TypeSpec.Builder builder =
-        TypeSpec.anonymousClassBuilder("")
-            .addMethod(
-                MethodSpec.methodBuilder(factoryMethod.getSimpleName().toString())
-                    .addModifiers(factoryOverride.modifiers)
-                    .addTypeVariables(factoryOverride.typeVariables)
-                    .returns(factoryOverride.returnType)
-                    .addAnnotations(factoryOverride.annotations)
-                    .addExceptions(factoryOverride.exceptions)
-                    .addParameters(assistedFactoryParameterSpecs(binding, elements, types))
-                    .addStatement("return $L", assistedInjectionExpression.codeBlock())
-                    .build());
-
-    if (factory.getKind() == ElementKind.INTERFACE) {
-      builder.addSuperinterface(TypeName.get(factoryType));
-    } else {
-      builder.superclass(TypeName.get(factoryType));
-    }
-
-    return builder.build();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/BUILD b/java/dagger/internal/codegen/writing/BUILD
deleted file mode 100644
index dcb88b3..0000000
--- a/java/dagger/internal/codegen/writing/BUILD
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Classes that assemble the model of the generated code and write to the Filer
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "writing",
-    srcs = glob(["*.java"]),
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    tags = ["maven:merged"],
-    deps = [
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/error_prone:annotations",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
diff --git a/java/dagger/internal/codegen/writing/BindingExpression.java b/java/dagger/internal/codegen/writing/BindingExpression.java
deleted file mode 100644
index bd45f60..0000000
--- a/java/dagger/internal/codegen/writing/BindingExpression.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.javapoet.Expression;
-
-/** A factory of code expressions used to access a single request for a binding in a component. */
-// TODO(bcorso): Rename this to RequestExpression?
-abstract class BindingExpression {
-
-  /**
-   * Returns an expression that evaluates to the value of a request based on the given requesting
-   * class.
-   *
-   * @param requestingClass the class that will contain the expression
-   */
-  abstract Expression getDependencyExpression(ClassName requestingClass);
-
-  /**
-   * Equivalent to {@link #getDependencyExpression} that is used only when the request is for an
-   * implementation of a component method. By default, just delegates to {@link
-   * #getDependencyExpression}.
-   */
-  Expression getDependencyExpressionForComponentMethod(
-      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
-    return getDependencyExpression(component.name());
-  }
-
-  /** Returns {@code true} if this binding expression should be encapsulated in a method. */
-  boolean requiresMethodEncapsulation() {
-    return false;
-  }
-
-  /**
-   * Returns an expression for the implementation of a component method with the given request.
-   *
-   * @param component the component that will contain the implemented method
-   */
-  CodeBlock getComponentMethodImplementation(
-      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
-    // By default, just delegate to #getDependencyExpression().
-    return CodeBlock.of(
-        "return $L;",
-        getDependencyExpressionForComponentMethod(componentMethod, component).codeBlock());
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentBindingExpressions.java b/java/dagger/internal/codegen/writing/ComponentBindingExpressions.java
deleted file mode 100644
index 5f1f0bd..0000000
--- a/java/dagger/internal/codegen/writing/ComponentBindingExpressions.java
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * Copyright (C) 2016 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.writing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Verify.verify;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
-import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeNames.DOUBLE_CHECK;
-import static dagger.internal.codegen.javapoet.TypeNames.SINGLE_CHECK;
-import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.writing.DelegateBindingExpression.isBindsScopeStrongerThanDependencyScope;
-import static dagger.internal.codegen.writing.MemberSelect.staticFactoryCreation;
-import static dagger.model.BindingKind.DELEGATE;
-import static dagger.model.BindingKind.MULTIBOUND_MAP;
-import static dagger.model.BindingKind.MULTIBOUND_SET;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import dagger.internal.codegen.binding.Binding;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.BindingNode;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.BindingType;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.binding.FrameworkTypeMapper;
-import dagger.internal.codegen.binding.MembersInjectionBinding;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import dagger.internal.codegen.writing.MethodBindingExpression.MethodImplementationStrategy;
-import dagger.model.BindingKind;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.type.TypeMirror;
-
-/** A central repository of code expressions used to access any binding available to a component. */
-@PerComponentImplementation
-public final class ComponentBindingExpressions {
-  // TODO(dpb,ronshapiro): refactor this and ComponentRequirementExpressions into a
-  // HierarchicalComponentMap<K, V>, or perhaps this use a flattened ImmutableMap, built from its
-  // parents? If so, maybe make BindingExpression.Factory create it.
-
-  private final Optional<ComponentBindingExpressions> parent;
-  private final BindingGraph graph;
-  private final ComponentImplementation componentImplementation;
-  private final ComponentImplementation topLevelComponentImplementation;
-  private final ComponentRequirementExpressions componentRequirementExpressions;
-  private final OptionalFactories optionalFactories;
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-  private final SourceVersion sourceVersion;
-  private final CompilerOptions compilerOptions;
-  private final MembersInjectionMethods membersInjectionMethods;
-  private final InnerSwitchingProviders innerSwitchingProviders;
-  private final Map<BindingRequest, BindingExpression> expressions = new HashMap<>();
-  private final KotlinMetadataUtil metadataUtil;
-
-  @Inject
-  ComponentBindingExpressions(
-      @ParentComponent Optional<ComponentBindingExpressions> parent,
-      BindingGraph graph,
-      ComponentImplementation componentImplementation,
-      @TopLevel ComponentImplementation topLevelComponentImplementation,
-      ComponentRequirementExpressions componentRequirementExpressions,
-      OptionalFactories optionalFactories,
-      DaggerTypes types,
-      DaggerElements elements,
-      SourceVersion sourceVersion,
-      CompilerOptions compilerOptions,
-      KotlinMetadataUtil metadataUtil) {
-    this.parent = parent;
-    this.graph = graph;
-    this.componentImplementation = componentImplementation;
-    this.topLevelComponentImplementation = topLevelComponentImplementation;
-    this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
-    this.optionalFactories = checkNotNull(optionalFactories);
-    this.types = checkNotNull(types);
-    this.elements = checkNotNull(elements);
-    this.sourceVersion = checkNotNull(sourceVersion);
-    this.compilerOptions = checkNotNull(compilerOptions);
-    this.membersInjectionMethods =
-        new MembersInjectionMethods(
-            componentImplementation, this, graph, elements, types, metadataUtil);
-    this.innerSwitchingProviders =
-        new InnerSwitchingProviders(componentImplementation, this, types);
-    this.metadataUtil = metadataUtil;
-  }
-
-  /**
-   * Returns an expression that evaluates to the value of a binding request for a binding owned by
-   * this component or an ancestor.
-   *
-   * @param requestingClass the class that will contain the expression
-   * @throws IllegalStateException if there is no binding expression that satisfies the request
-   */
-  public Expression getDependencyExpression(BindingRequest request, ClassName requestingClass) {
-    return getBindingExpression(request).getDependencyExpression(requestingClass);
-  }
-
-  /**
-   * Equivalent to {@link #getDependencyExpression(BindingRequest, ClassName)} that is used only
-   * when the request is for implementation of a component method.
-   *
-   * @throws IllegalStateException if there is no binding expression that satisfies the request
-   */
-  Expression getDependencyExpressionForComponentMethod(
-      BindingRequest request,
-      ComponentMethodDescriptor componentMethod,
-      ComponentImplementation componentImplementation) {
-    return getBindingExpression(request)
-        .getDependencyExpressionForComponentMethod(componentMethod, componentImplementation);
-  }
-
-  /**
-   * Returns the {@link CodeBlock} for the method arguments used with the factory {@code create()}
-   * method for the given {@link ContributionBinding binding}.
-   */
-  CodeBlock getCreateMethodArgumentsCodeBlock(ContributionBinding binding) {
-    return makeParametersCodeBlock(getCreateMethodArgumentsCodeBlocks(binding));
-  }
-
-  private ImmutableList<CodeBlock> getCreateMethodArgumentsCodeBlocks(ContributionBinding binding) {
-    ImmutableList.Builder<CodeBlock> arguments = ImmutableList.builder();
-
-    if (binding.requiresModuleInstance()) {
-      arguments.add(
-          componentRequirementExpressions.getExpressionDuringInitialization(
-              ComponentRequirement.forModule(binding.contributingModule().get().asType()),
-              componentImplementation.name()));
-    }
-
-    binding.dependencies().stream()
-        .map(dependency -> frameworkRequest(binding, dependency))
-        .map(request -> getDependencyExpression(request, componentImplementation.name()))
-        .map(Expression::codeBlock)
-        .forEach(arguments::add);
-
-    return arguments.build();
-  }
-
-  private static BindingRequest frameworkRequest(
-      ContributionBinding binding, DependencyRequest dependency) {
-    // TODO(bcorso): See if we can get rid of FrameworkTypeMatcher
-    FrameworkType frameworkType =
-        FrameworkTypeMapper.forBindingType(binding.bindingType())
-            .getFrameworkType(dependency.kind());
-    return BindingRequest.bindingRequest(dependency.key(), frameworkType);
-  }
-
-  /**
-   * Returns an expression that evaluates to the value of a dependency request, for passing to a
-   * binding method, an {@code @Inject}-annotated constructor or member, or a proxy for one.
-   *
-   * <p>If the method is a generated static {@link InjectionMethods injection method}, each
-   * parameter will be {@link Object} if the dependency's raw type is inaccessible. If that is the
-   * case for this dependency, the returned expression will use a cast to evaluate to the raw type.
-   *
-   * @param requestingClass the class that will contain the expression
-   */
-  Expression getDependencyArgumentExpression(
-      DependencyRequest dependencyRequest, ClassName requestingClass) {
-
-    TypeMirror dependencyType = dependencyRequest.key().type();
-    BindingRequest bindingRequest = bindingRequest(dependencyRequest);
-    Expression dependencyExpression = getDependencyExpression(bindingRequest, requestingClass);
-
-    if (dependencyRequest.kind().equals(RequestKind.INSTANCE)
-        && !isTypeAccessibleFrom(dependencyType, requestingClass.packageName())
-        && isRawTypeAccessible(dependencyType, requestingClass.packageName())) {
-      return dependencyExpression.castTo(types.erasure(dependencyType));
-    }
-
-    return dependencyExpression;
-  }
-
-  /** Returns the implementation of a component method. */
-  public MethodSpec getComponentMethod(ComponentMethodDescriptor componentMethod) {
-    checkArgument(componentMethod.dependencyRequest().isPresent());
-    BindingRequest request = bindingRequest(componentMethod.dependencyRequest().get());
-    MethodSpec.Builder method =
-        MethodSpec.overriding(
-            componentMethod.methodElement(),
-            MoreTypes.asDeclared(graph.componentTypeElement().asType()),
-            types);
-    // Even though this is not used if the method is abstract, we need to invoke the binding
-    // expression in order for the side of effect of the method being added to the
-    // ComponentImplementation
-    CodeBlock methodBody =
-        getBindingExpression(request)
-            .getComponentMethodImplementation(componentMethod, componentImplementation);
-
-    return method.addCode(methodBody).build();
-  }
-
-  /** Returns the {@link BindingExpression} for the given {@link BindingRequest}. */
-  BindingExpression getBindingExpression(BindingRequest request) {
-    if (expressions.containsKey(request)) {
-      return expressions.get(request);
-    }
-
-    Optional<Binding> optionalBinding =
-        graph.bindingNodes(request.key()).stream()
-            // Filter out nodes we don't own.
-            .filter(bindingNode -> bindingNode.componentPath().equals(graph.componentPath()))
-            // Filter out nodes that don't match the request kind
-            .filter(
-                bindingNode ->
-                    // The binding used for the binding expression depends on the request:
-                    //   1. MembersInjectionBinding: satisfies MEMBERS_INJECTION requests
-                    //   2. ContributionBindings: satisfies all other requests.
-                    request.isRequestKind(RequestKind.MEMBERS_INJECTION)
-                        ? bindingNode.delegate().bindingType() == BindingType.MEMBERS_INJECTION
-                        : bindingNode.delegate().bindingType() == BindingType.PROVISION
-                            || bindingNode.delegate().bindingType() == BindingType.PRODUCTION)
-            .map(BindingNode::delegate)
-            // We expect at most one binding to match since this graph is already validated.
-            .collect(toOptional());
-
-    if (optionalBinding.isPresent()) {
-      BindingExpression expression = createBindingExpression(optionalBinding.get(), request);
-      expressions.put(request, expression);
-      return expression;
-    }
-
-    checkArgument(parent.isPresent(), "no expression found for %s", request);
-    return parent.get().getBindingExpression(request);
-  }
-
-  /** Creates a binding expression. */
-  private BindingExpression createBindingExpression(Binding binding, BindingRequest request) {
-    switch (binding.bindingType()) {
-      case MEMBERS_INJECTION:
-        checkArgument(request.isRequestKind(RequestKind.MEMBERS_INJECTION));
-        return new MembersInjectionBindingExpression(
-            (MembersInjectionBinding) binding, membersInjectionMethods);
-
-      case PROVISION:
-        return provisionBindingExpression((ContributionBinding) binding, request);
-
-      case PRODUCTION:
-        return productionBindingExpression((ContributionBinding) binding, request);
-    }
-    throw new AssertionError(binding);
-  }
-
-  /**
-   * Returns a binding expression that uses a {@link javax.inject.Provider} for provision bindings
-   * or a {@link dagger.producers.Producer} for production bindings.
-   */
-  private BindingExpression frameworkInstanceBindingExpression(ContributionBinding binding) {
-    // TODO(bcorso): Consider merging the static factory creation logic into CreationExpressions?
-    Optional<MemberSelect> staticMethod =
-        useStaticFactoryCreation(binding) ? staticFactoryCreation(binding) : Optional.empty();
-    FrameworkInstanceSupplier frameworkInstanceSupplier =
-        staticMethod.isPresent()
-            ? staticMethod::get
-            : new FrameworkFieldInitializer(
-                  componentImplementation,
-                  binding,
-                  binding.scope().isPresent()
-                      ? scope(binding, frameworkInstanceCreationExpression(binding))
-                      : frameworkInstanceCreationExpression(binding));
-
-    switch (binding.bindingType()) {
-      case PROVISION:
-        return new ProviderInstanceBindingExpression(
-            binding, frameworkInstanceSupplier, types, elements);
-      case PRODUCTION:
-        return new ProducerNodeInstanceBindingExpression(
-            binding, frameworkInstanceSupplier, types, elements, componentImplementation);
-      default:
-        throw new AssertionError("invalid binding type: " + binding.bindingType());
-    }
-  }
-
-  private FrameworkInstanceCreationExpression scope(
-      ContributionBinding binding, FrameworkInstanceCreationExpression unscoped) {
-    return () ->
-        CodeBlock.of(
-            "$T.provider($L)",
-            binding.scope().get().isReusable() ? SINGLE_CHECK : DOUBLE_CHECK,
-            unscoped.creationExpression());
-  }
-
-  /**
-   * Returns a creation expression for a {@link javax.inject.Provider} for provision bindings or a
-   * {@link dagger.producers.Producer} for production bindings.
-   */
-  private FrameworkInstanceCreationExpression frameworkInstanceCreationExpression(
-      ContributionBinding binding) {
-    switch (binding.kind()) {
-      case COMPONENT:
-        // The cast can be removed when we drop java 7 source support
-        return new InstanceFactoryCreationExpression(
-            () -> CodeBlock.of("($T) this", binding.key().type()));
-
-      case BOUND_INSTANCE:
-        return instanceFactoryCreationExpression(
-            binding, ComponentRequirement.forBoundInstance(binding));
-
-      case COMPONENT_DEPENDENCY:
-        return instanceFactoryCreationExpression(
-            binding, ComponentRequirement.forDependency(binding.key().type()));
-
-      case COMPONENT_PROVISION:
-        return new DependencyMethodProviderCreationExpression(
-            binding,
-            componentImplementation,
-            componentRequirementExpressions,
-            compilerOptions,
-            graph);
-
-      case SUBCOMPONENT_CREATOR:
-        return new AnonymousProviderCreationExpression(
-            binding, this, componentImplementation.name());
-
-      case ASSISTED_FACTORY:
-      case ASSISTED_INJECTION:
-      case INJECTION:
-      case PROVISION:
-        return new InjectionOrProvisionProviderCreationExpression(binding, this);
-
-      case COMPONENT_PRODUCTION:
-        return new DependencyMethodProducerCreationExpression(
-            binding, componentImplementation, componentRequirementExpressions, graph);
-
-      case PRODUCTION:
-        return new ProducerCreationExpression(binding, this);
-
-      case MULTIBOUND_SET:
-        return new SetFactoryCreationExpression(binding, componentImplementation, this, graph);
-
-      case MULTIBOUND_MAP:
-        return new MapFactoryCreationExpression(
-            binding, componentImplementation, this, graph, elements);
-
-      case DELEGATE:
-        return new DelegatingFrameworkInstanceCreationExpression(
-            binding, componentImplementation, this);
-
-      case OPTIONAL:
-        return new OptionalFactoryInstanceCreationExpression(
-            optionalFactories, binding, componentImplementation, this);
-
-      case MEMBERS_INJECTOR:
-        return new MembersInjectorProviderCreationExpression((ProvisionBinding) binding, this);
-
-      default:
-        throw new AssertionError(binding);
-    }
-  }
-
-  private InstanceFactoryCreationExpression instanceFactoryCreationExpression(
-      ContributionBinding binding, ComponentRequirement componentRequirement) {
-    return new InstanceFactoryCreationExpression(
-        binding.nullableType().isPresent(),
-        () ->
-            componentRequirementExpressions.getExpressionDuringInitialization(
-                componentRequirement, componentImplementation.name()));
-  }
-
-  /** Returns a binding expression for a provision binding. */
-  private BindingExpression provisionBindingExpression(
-      ContributionBinding binding, BindingRequest request) {
-    if (!request.requestKind().isPresent()) {
-      verify(
-          request.frameworkType().get().equals(FrameworkType.PRODUCER_NODE),
-          "expected a PRODUCER_NODE: %s",
-          request);
-      return producerFromProviderBindingExpression(binding);
-    }
-    RequestKind requestKind = request.requestKind().get();
-    Key key = request.key();
-    switch (requestKind) {
-      case INSTANCE:
-        return instanceBindingExpression(binding);
-
-      case PROVIDER:
-        return providerBindingExpression(binding);
-
-      case LAZY:
-      case PRODUCED:
-      case PROVIDER_OF_LAZY:
-        return new DerivedFromFrameworkInstanceBindingExpression(
-            key, FrameworkType.PROVIDER, requestKind, this, types);
-
-      case PRODUCER:
-        return producerFromProviderBindingExpression(binding);
-
-      case FUTURE:
-        return new ImmediateFutureBindingExpression(key, this, types, sourceVersion);
-
-      case MEMBERS_INJECTION:
-        throw new IllegalArgumentException();
-    }
-
-    throw new AssertionError();
-  }
-
-  /** Returns a binding expression for a production binding. */
-  private BindingExpression productionBindingExpression(
-      ContributionBinding binding, BindingRequest request) {
-    if (request.frameworkType().isPresent()) {
-      return frameworkInstanceBindingExpression(binding);
-    } else {
-      // If no FrameworkType is present, a RequestKind is guaranteed to be present.
-      RequestKind requestKind = request.requestKind().get();
-      return new DerivedFromFrameworkInstanceBindingExpression(
-          request.key(), FrameworkType.PRODUCER_NODE, requestKind, this, types);
-    }
-  }
-
-  /**
-   * Returns a binding expression for {@link RequestKind#PROVIDER} requests.
-   *
-   * <p>{@code @Binds} bindings that don't {@linkplain #needsCaching(ContributionBinding) need to be
-   * cached} can use a {@link DelegateBindingExpression}.
-   *
-   * <p>In fastInit mode, use an {@link InnerSwitchingProviders inner switching provider} unless
-   * that provider's case statement will simply call {@code get()} on another {@link Provider} (in
-   * which case, just use that Provider directly).
-   *
-   * <p>Otherwise, return a {@link FrameworkInstanceBindingExpression}.
-   */
-  private BindingExpression providerBindingExpression(ContributionBinding binding) {
-    if (binding.kind().equals(DELEGATE) && !needsCaching(binding)) {
-      return new DelegateBindingExpression(binding, RequestKind.PROVIDER, this, types, elements);
-    } else if (compilerOptions.fastInit(
-            topLevelComponentImplementation.componentDescriptor().typeElement())
-        && frameworkInstanceCreationExpression(binding).useInnerSwitchingProvider()
-        && !(instanceBindingExpression(binding)
-            instanceof DerivedFromFrameworkInstanceBindingExpression)) {
-      return wrapInMethod(
-          binding,
-          bindingRequest(binding.key(), RequestKind.PROVIDER),
-          innerSwitchingProviders.newBindingExpression(binding));
-    }
-    return frameworkInstanceBindingExpression(binding);
-  }
-
-  /**
-   * Returns a binding expression that uses a {@link dagger.producers.Producer} field for a
-   * provision binding.
-   */
-  private FrameworkInstanceBindingExpression producerFromProviderBindingExpression(
-      ContributionBinding binding) {
-    checkArgument(binding.bindingType().equals(BindingType.PROVISION));
-    return new ProducerNodeInstanceBindingExpression(
-        binding,
-        new FrameworkFieldInitializer(
-            componentImplementation,
-            binding,
-            new ProducerFromProviderCreationExpression(binding, componentImplementation, this)),
-        types,
-        elements,
-        componentImplementation);
-  }
-
-  /**
-   * Returns a binding expression for {@link RequestKind#INSTANCE} requests.
-   *
-   * <p>If there is a direct expression (not calling {@link Provider#get()}) we can use for an
-   * instance of this binding, return it, wrapped in a method if the binding {@linkplain
-   * #needsCaching(ContributionBinding) needs to be cached} or the expression has dependencies.
-   *
-   * <p>In fastInit mode, we can use direct expressions unless the binding needs to be cached.
-   */
-  private BindingExpression instanceBindingExpression(ContributionBinding binding) {
-    Optional<BindingExpression> maybeDirectInstanceExpression =
-        unscopedDirectInstanceExpression(binding);
-    if (canUseDirectInstanceExpression(binding) && maybeDirectInstanceExpression.isPresent()) {
-      BindingExpression directInstanceExpression = maybeDirectInstanceExpression.get();
-      return directInstanceExpression.requiresMethodEncapsulation() || needsCaching(binding)
-          ? wrapInMethod(
-              binding,
-              bindingRequest(binding.key(), RequestKind.INSTANCE),
-              directInstanceExpression)
-          : directInstanceExpression;
-    }
-    return new DerivedFromFrameworkInstanceBindingExpression(
-        binding.key(), FrameworkType.PROVIDER, RequestKind.INSTANCE, this, types);
-  }
-
-  /**
-   * Returns an unscoped binding expression for an {@link RequestKind#INSTANCE} that does not call
-   * {@code get()} on its provider, if there is one.
-   */
-  private Optional<BindingExpression> unscopedDirectInstanceExpression(
-      ContributionBinding binding) {
-    switch (binding.kind()) {
-      case DELEGATE:
-        return Optional.of(
-            new DelegateBindingExpression(binding, RequestKind.INSTANCE, this, types, elements));
-
-      case COMPONENT:
-        return Optional.of(
-            new ComponentInstanceBindingExpression(binding, componentImplementation.name()));
-
-      case COMPONENT_DEPENDENCY:
-        return Optional.of(
-            new ComponentRequirementBindingExpression(
-                binding,
-                ComponentRequirement.forDependency(binding.key().type()),
-                componentRequirementExpressions));
-
-      case COMPONENT_PROVISION:
-        return Optional.of(
-            new ComponentProvisionBindingExpression(
-                (ProvisionBinding) binding,
-                graph,
-                componentRequirementExpressions,
-                compilerOptions));
-
-      case SUBCOMPONENT_CREATOR:
-        return Optional.of(
-            new SubcomponentCreatorBindingExpression(
-                binding, componentImplementation.getSubcomponentCreatorSimpleName(binding.key())));
-
-      case MULTIBOUND_SET:
-        return Optional.of(
-            new SetBindingExpression((ProvisionBinding) binding, graph, this, types, elements));
-
-      case MULTIBOUND_MAP:
-        return Optional.of(
-            new MapBindingExpression((ProvisionBinding) binding, graph, this, types, elements));
-
-      case OPTIONAL:
-        return Optional.of(
-            new OptionalBindingExpression((ProvisionBinding) binding, this, types, sourceVersion));
-
-      case BOUND_INSTANCE:
-        return Optional.of(
-            new ComponentRequirementBindingExpression(
-                binding,
-                ComponentRequirement.forBoundInstance(binding),
-                componentRequirementExpressions));
-
-      case ASSISTED_FACTORY:
-        return Optional.of(
-            new AssistedFactoryBindingExpression(
-                (ProvisionBinding) binding, this, types, elements));
-
-      case ASSISTED_INJECTION:
-      case INJECTION:
-      case PROVISION:
-        return Optional.of(
-            new SimpleMethodBindingExpression(
-                (ProvisionBinding) binding,
-                compilerOptions,
-                this,
-                membersInjectionMethods,
-                componentRequirementExpressions,
-                elements,
-                sourceVersion,
-                metadataUtil));
-
-      case MEMBERS_INJECTOR:
-        return Optional.empty();
-
-      case MEMBERS_INJECTION:
-      case COMPONENT_PRODUCTION:
-      case PRODUCTION:
-        throw new IllegalArgumentException(binding.kind().toString());
-      default:
-        throw new AssertionError("Unexpected binding kind: " + binding.kind());
-    }
-  }
-
-  /**
-   * Returns {@code true} if the binding should use the static factory creation strategy.
-   *
-   * <p>In default mode, we always use the static factory creation strategy. In fastInit mode, we
-   * prefer to use a SwitchingProvider instead of static factories in order to reduce class loading;
-   * however, we allow static factories that can reused across multiple bindings, e.g. {@code
-   * MapFactory} or {@code SetFactory}.
-   */
-  private boolean useStaticFactoryCreation(ContributionBinding binding) {
-    return !compilerOptions.fastInit(
-            topLevelComponentImplementation.componentDescriptor().typeElement())
-        || binding.kind().equals(MULTIBOUND_MAP)
-        || binding.kind().equals(MULTIBOUND_SET);
-  }
-
-  /**
-   * Returns {@code true} if we can use a direct (not {@code Provider.get()}) expression for this
-   * binding. If the binding doesn't {@linkplain #needsCaching(ContributionBinding) need to be
-   * cached} and the binding is not an {@link BindingKind.ASSISTED_FACTORY}, we can.
-   *
-   * <p>In fastInit mode, we can use a direct expression even if the binding {@linkplain
-   * #needsCaching(ContributionBinding) needs to be cached}.
-   */
-  private boolean canUseDirectInstanceExpression(ContributionBinding binding) {
-    return (!needsCaching(binding) && binding.kind() != BindingKind.ASSISTED_FACTORY)
-        || compilerOptions.fastInit(
-            topLevelComponentImplementation.componentDescriptor().typeElement());
-  }
-
-  /**
-   * Returns a binding expression that uses a given one as the body of a method that users call. If
-   * a component provision method matches it, it will be the method implemented. If it does not
-   * match a component provision method and the binding is modifiable, then a new public modifiable
-   * binding method will be written. If the binding doesn't match a component method and is not
-   * modifiable, then a new private method will be written.
-   */
-  BindingExpression wrapInMethod(
-      ContributionBinding binding, BindingRequest request, BindingExpression bindingExpression) {
-    // If we've already wrapped the expression, then use the delegate.
-    if (bindingExpression instanceof MethodBindingExpression) {
-      return bindingExpression;
-    }
-
-    MethodImplementationStrategy methodImplementationStrategy =
-        methodImplementationStrategy(binding, request);
-    Optional<ComponentMethodDescriptor> matchingComponentMethod =
-        graph.componentDescriptor().firstMatchingComponentMethod(request);
-
-    ComponentImplementation shard = componentImplementation.shardImplementation(binding.key());
-
-    // Consider the case of a request from a component method like:
-    //
-    //   DaggerMyComponent extends MyComponent {
-    //     @Overrides
-    //     Foo getFoo() {
-    //       <FOO_BINDING_REQUEST>
-    //     }
-    //   }
-    //
-    // Normally, in this case we would return a ComponentMethodBindingExpression rather than a
-    // PrivateMethodBindingExpression so that #getFoo() can inline the implementation rather than
-    // create an unnecessary private method and return that. However, with sharding we don't want to
-    // inline the implementation because that would defeat some of the class pool savings if those
-    // fields had to communicate across shards. Thus, when a key belongs to a separate shard use a
-    // PrivateMethodBindingExpression and put the private method in the shard.
-    if (matchingComponentMethod.isPresent() && componentImplementation == shard) {
-      ComponentMethodDescriptor componentMethod = matchingComponentMethod.get();
-      return new ComponentMethodBindingExpression(
-          request,
-          binding,
-          methodImplementationStrategy,
-          bindingExpression,
-          componentImplementation,
-          componentMethod,
-          types);
-    } else {
-      return new PrivateMethodBindingExpression(
-          request,
-          binding,
-          methodImplementationStrategy,
-          bindingExpression,
-          shard,
-          types,
-          compilerOptions);
-    }
-  }
-
-  private MethodImplementationStrategy methodImplementationStrategy(
-      ContributionBinding binding, BindingRequest request) {
-    if (compilerOptions.fastInit(
-        topLevelComponentImplementation.componentDescriptor().typeElement())) {
-      if (request.isRequestKind(RequestKind.PROVIDER)) {
-        return MethodImplementationStrategy.SINGLE_CHECK;
-      } else if (request.isRequestKind(RequestKind.INSTANCE) && needsCaching(binding)) {
-        return binding.scope().get().isReusable()
-            ? MethodImplementationStrategy.SINGLE_CHECK
-            : MethodImplementationStrategy.DOUBLE_CHECK;
-      }
-    }
-    return MethodImplementationStrategy.SIMPLE;
-  }
-
-  /**
-   * Returns {@code true} if the component needs to make sure the provided value is cached.
-   *
-   * <p>The component needs to cache the value for scoped bindings except for {@code @Binds}
-   * bindings whose scope is no stronger than their delegate's.
-   */
-  private boolean needsCaching(ContributionBinding binding) {
-    if (!binding.scope().isPresent()) {
-      return false;
-    }
-    if (binding.kind().equals(DELEGATE)) {
-      return isBindsScopeStrongerThanDependencyScope(binding, graph);
-    }
-    return true;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentCreatorImplementation.java b/java/dagger/internal/codegen/writing/ComponentCreatorImplementation.java
deleted file mode 100644
index f9d218b..0000000
--- a/java/dagger/internal/codegen/writing/ComponentCreatorImplementation.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableMap;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.binding.ComponentRequirement;
-
-/** The implementation of a component creator type. */
-@AutoValue
-public abstract class ComponentCreatorImplementation {
-
-  /** Creates a new {@link ComponentCreatorImplementation}. */
-  public static ComponentCreatorImplementation create(
-      TypeSpec spec, ClassName name, ImmutableMap<ComponentRequirement, FieldSpec> fields) {
-    return new AutoValue_ComponentCreatorImplementation(spec, name, fields);
-  }
-
-  /** The type spec for the creator implementation. */
-  public abstract TypeSpec spec();
-
-  /** The name of the creator implementation class. */
-  public abstract ClassName name();
-
-  /** All fields that are present in this implementation. */
-  abstract ImmutableMap<ComponentRequirement, FieldSpec> fields();
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentImplementation.java b/java/dagger/internal/codegen/writing/ComponentImplementation.java
deleted file mode 100644
index ef69124..0000000
--- a/java/dagger/internal/codegen/writing/ComponentImplementation.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2016 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.writing;
-
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.binding.ComponentCreatorKind.BUILDER;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.base.UniqueNameSet;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.ComponentCreatorDescriptor;
-import dagger.internal.codegen.binding.ComponentCreatorKind;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.KeyVariableNamer;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.javapoet.TypeSpecs;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-/** The implementation of a component type. */
-public final class ComponentImplementation {
-  /** A type of field that this component can contain. */
-  public enum FieldSpecKind {
-    /** A field for a component shard. */
-    COMPONENT_SHARD,
-
-    /** A field required by the component, e.g. module instances. */
-    COMPONENT_REQUIREMENT_FIELD,
-
-    /**
-     * A field for the lock and cached value for {@linkplain PrivateMethodBindingExpression
-     * private-method scoped bindings}.
-     */
-    PRIVATE_METHOD_SCOPED_FIELD,
-
-    /** A framework field for type T, e.g. {@code Provider<T>}. */
-    FRAMEWORK_FIELD,
-
-    /** A static field that always returns an absent {@code Optional} value for the binding. */
-    ABSENT_OPTIONAL_FIELD
-  }
-
-  /** A type of method that this component can contain. */
-  // TODO(bcorso, dpb): Change the oder to constructor, initialize, component, then private
-  // (including MIM and AOM—why treat those separately?).
-  public enum MethodSpecKind {
-    /** The component constructor. */
-    CONSTRUCTOR,
-
-    /** A builder method for the component. (Only used by the root component.) */
-    BUILDER_METHOD,
-
-    /** A private method that wraps dependency expressions. */
-    PRIVATE_METHOD,
-
-    /** An initialization method that initializes component requirements and framework types. */
-    INITIALIZE_METHOD,
-
-    /** An implementation of a component interface method. */
-    COMPONENT_METHOD,
-
-    /** A private method that encapsulates members injection logic for a binding. */
-    MEMBERS_INJECTION_METHOD,
-
-    /** A static method that always returns an absent {@code Optional} value for the binding. */
-    ABSENT_OPTIONAL_METHOD,
-
-    /**
-     * The {@link dagger.producers.internal.CancellationListener#onProducerFutureCancelled(boolean)}
-     * method for a production component.
-     */
-    CANCELLATION_LISTENER_METHOD,
-    ;
-  }
-
-  /** A type of nested class that this component can contain. */
-  public enum TypeSpecKind {
-    /** A factory class for a present optional binding. */
-    PRESENT_FACTORY,
-
-    /** A class for the component creator (only used by the root component.) */
-    COMPONENT_CREATOR,
-
-    /** A provider class for a component provision. */
-    COMPONENT_PROVISION_FACTORY,
-
-    /** A class for the subcomponent or subcomponent builder. */
-    SUBCOMPONENT
-  }
-
-  private ComponentImplementation currentShard = this;
-  private final Map<Key, ComponentImplementation> shardsByKey = new HashMap<>();
-  private final Optional<ComponentImplementation> shardOwner;
-  private final BindingGraph graph;
-  private final ClassName name;
-  private final TypeSpec.Builder component;
-  private final SubcomponentNames subcomponentNames;
-  private final CompilerOptions compilerOptions;
-  private final CodeBlock externalReferenceBlock;
-  private final UniqueNameSet componentFieldNames = new UniqueNameSet();
-  private final UniqueNameSet componentMethodNames = new UniqueNameSet();
-  private final List<CodeBlock> initializations = new ArrayList<>();
-  private final List<CodeBlock> componentRequirementInitializations = new ArrayList<>();
-  private final Map<ComponentRequirement, String> componentRequirementParameterNames =
-      new HashMap<>();
-  private final Set<Key> cancellableProducerKeys = new LinkedHashSet<>();
-  private final ListMultimap<FieldSpecKind, FieldSpec> fieldSpecsMap =
-      MultimapBuilder.enumKeys(FieldSpecKind.class).arrayListValues().build();
-  private final ListMultimap<MethodSpecKind, MethodSpec> methodSpecsMap =
-      MultimapBuilder.enumKeys(MethodSpecKind.class).arrayListValues().build();
-  private final ListMultimap<TypeSpecKind, TypeSpec> typeSpecsMap =
-      MultimapBuilder.enumKeys(TypeSpecKind.class).arrayListValues().build();
-  private final List<Supplier<TypeSpec>> typeSuppliers = new ArrayList<>();
-
-  private ComponentImplementation(
-      BindingGraph graph,
-      ClassName name,
-      SubcomponentNames subcomponentNames,
-      CompilerOptions compilerOptions) {
-    this.graph = graph;
-    this.name = name;
-    this.component = classBuilder(name);
-    this.subcomponentNames = subcomponentNames;
-    this.shardOwner = Optional.empty();
-    this.externalReferenceBlock = CodeBlock.of("$T.this", name);
-    this.compilerOptions = compilerOptions;
-  }
-
-  private ComponentImplementation(ComponentImplementation shardOwner, ClassName shardName) {
-    this.graph = shardOwner.graph;
-    this.name = shardName;
-    this.component = classBuilder(shardName);
-    this.subcomponentNames = shardOwner.subcomponentNames;
-    this.compilerOptions = shardOwner.compilerOptions;
-    this.shardOwner = Optional.of(shardOwner);
-    String fieldName = UPPER_CAMEL.to(LOWER_CAMEL, name.simpleName());
-    String uniqueFieldName = shardOwner.getUniqueFieldName(fieldName);
-    this.externalReferenceBlock = CodeBlock.of("$T.this.$N", shardOwner.name, uniqueFieldName);
-    shardOwner.addTypeSupplier(() -> generate().build());
-    shardOwner.addField(
-        FieldSpecKind.COMPONENT_SHARD,
-        FieldSpec.builder(name, uniqueFieldName, PRIVATE, FINAL)
-            .initializer("new $T()", name)
-            .build());
-  }
-
-  /** Returns a component implementation for a top-level component. */
-  public static ComponentImplementation topLevelComponentImplementation(
-      BindingGraph graph,
-      ClassName name,
-      SubcomponentNames subcomponentNames,
-      CompilerOptions compilerOptions) {
-    return new ComponentImplementation(graph, name, subcomponentNames, compilerOptions);
-  }
-
-  /** Returns a component implementation that is a child of the current implementation. */
-  public ComponentImplementation childComponentImplementation(BindingGraph graph) {
-    checkState(!shardOwner.isPresent(), "Shards cannot create child components.");
-    ClassName childName = getSubcomponentName(graph.componentDescriptor());
-    return new ComponentImplementation(graph, childName, subcomponentNames, compilerOptions);
-  }
-
-  /** Returns a component implementation that is a shard of the current implementation. */
-  public ComponentImplementation shardImplementation(Key key) {
-    checkState(!shardOwner.isPresent(), "Shards cannot create other shards.");
-    if (!shardsByKey.containsKey(key)) {
-      int keysPerShard = compilerOptions.keysPerComponentShard(graph.componentTypeElement());
-      if (!shardsByKey.isEmpty() && shardsByKey.size() % keysPerShard == 0) {
-        ClassName shardName = name.nestedClass("Shard" + shardsByKey.size() / keysPerShard);
-        currentShard = new ComponentImplementation(this, shardName);
-      }
-      shardsByKey.put(key, currentShard);
-    }
-    return shardsByKey.get(key);
-  }
-
-  /** Returns a reference to this compenent when called from a class nested in this component. */
-  public CodeBlock externalReferenceBlock() {
-    return externalReferenceBlock;
-  }
-
-  // TODO(ronshapiro): see if we can remove this method and instead inject it in the objects that
-  // need it.
-  /** Returns the binding graph for the component being generated. */
-  public BindingGraph graph() {
-    return graph;
-  }
-
-  /** Returns the descriptor for the component being generated. */
-  public ComponentDescriptor componentDescriptor() {
-    return graph.componentDescriptor();
-  }
-
-  /** Returns the name of the component. */
-  public ClassName name() {
-    return name;
-  }
-
-  /** Returns whether or not the implementation is nested within another class. */
-  public boolean isNested() {
-    return name.enclosingClassName() != null;
-  }
-
-  /**
-   * Returns the kind of this component's creator.
-   *
-   * @throws IllegalStateException if the component has no creator
-   */
-  private ComponentCreatorKind creatorKind() {
-    checkState(componentDescriptor().hasCreator());
-    return componentDescriptor()
-        .creatorDescriptor()
-        .map(ComponentCreatorDescriptor::kind)
-        .orElse(BUILDER);
-  }
-
-  /**
-   * Returns the name of the creator class for this component. It will be a sibling of this
-   * generated class unless this is a top-level component, in which case it will be nested.
-   */
-  public ClassName getCreatorName() {
-    return isNested()
-        ? name.peerClass(subcomponentNames.getCreatorName(componentDescriptor()))
-        : name.nestedClass(creatorKind().typeName());
-  }
-
-  /** Returns the name of the nested implementation class for a child component. */
-  private ClassName getSubcomponentName(ComponentDescriptor childDescriptor) {
-    checkArgument(
-        componentDescriptor().childComponents().contains(childDescriptor),
-        "%s is not a child component of %s",
-        childDescriptor.typeElement(),
-        componentDescriptor().typeElement());
-    return name.nestedClass(subcomponentNames.get(childDescriptor) + "Impl");
-  }
-
-  /**
-   * Returns the simple name of the creator implementation class for the given subcomponent creator
-   * {@link Key}.
-   */
-  String getSubcomponentCreatorSimpleName(Key key) {
-    return subcomponentNames.getCreatorName(key);
-  }
-
-  /** Returns {@code true} if {@code type} is accessible from the generated component. */
-  boolean isTypeAccessible(TypeMirror type) {
-    return isTypeAccessibleFrom(type, name.packageName());
-  }
-
-  /** Adds the given super type to the component. */
-  public void addSupertype(TypeElement supertype) {
-    TypeSpecs.addSupertype(component, supertype);
-  }
-
-  // TODO(dpb): Consider taking FieldSpec, and returning identical FieldSpec with unique name?
-  /** Adds the given field to the component. */
-  public void addField(FieldSpecKind fieldKind, FieldSpec fieldSpec) {
-    fieldSpecsMap.put(fieldKind, fieldSpec);
-  }
-
-  // TODO(dpb): Consider taking MethodSpec, and returning identical MethodSpec with unique name?
-  /** Adds the given method to the component. */
-  public void addMethod(MethodSpecKind methodKind, MethodSpec methodSpec) {
-    methodSpecsMap.put(methodKind, methodSpec);
-  }
-
-  /** Adds the given annotation to the component. */
-  public void addAnnotation(AnnotationSpec annotation) {
-    component.addAnnotation(annotation);
-  }
-
-  /** Adds the given type to the component. */
-  public void addType(TypeSpecKind typeKind, TypeSpec typeSpec) {
-    typeSpecsMap.put(typeKind, typeSpec);
-  }
-
-  /** Adds a {@link Supplier} for the SwitchingProvider for the component. */
-  void addTypeSupplier(Supplier<TypeSpec> typeSpecSupplier) {
-    typeSuppliers.add(typeSpecSupplier);
-  }
-
-  /** Adds the given code block to the initialize methods of the component. */
-  void addInitialization(CodeBlock codeBlock) {
-    initializations.add(codeBlock);
-  }
-
-  /** Adds the given code block that initializes a {@link ComponentRequirement}. */
-  void addComponentRequirementInitialization(CodeBlock codeBlock) {
-    componentRequirementInitializations.add(codeBlock);
-  }
-
-  /**
-   * Marks the given key of a producer as one that should have a cancellation statement in the
-   * cancellation listener method of the component.
-   */
-  void addCancellableProducerKey(Key key) {
-    cancellableProducerKeys.add(key);
-  }
-
-  /** Returns a new, unique field name for the component based on the given name. */
-  String getUniqueFieldName(String name) {
-    return componentFieldNames.getUniqueName(name);
-  }
-
-  /** Returns a new, unique method name for the component based on the given name. */
-  public String getUniqueMethodName(String name) {
-    return componentMethodNames.getUniqueName(name);
-  }
-
-  /** Returns a new, unique method name for a getter method for the given request. */
-  String getUniqueMethodName(BindingRequest request) {
-    return uniqueMethodName(request, KeyVariableNamer.name(request.key()));
-  }
-
-  private String uniqueMethodName(BindingRequest request, String bindingName) {
-    // This name is intentionally made to match the name for fields in fastInit
-    // in order to reduce the constant pool size. b/162004246
-    String baseMethodName = bindingName
-        + (request.isRequestKind(RequestKind.INSTANCE)
-            ? ""
-            : UPPER_UNDERSCORE.to(UPPER_CAMEL, request.kindName()));
-    return getUniqueMethodName(baseMethodName);
-  }
-
-  /**
-   * Gets the parameter name to use for the given requirement for this component, starting with the
-   * given base name if no parameter name has already been selected for the requirement.
-   */
-  public String getParameterName(ComponentRequirement requirement, String baseName) {
-    return componentRequirementParameterNames.computeIfAbsent(
-        requirement, r -> getUniqueFieldName(baseName));
-  }
-
-  /** Claims a new method name for the component. Does nothing if method name already exists. */
-  public void claimMethodName(CharSequence name) {
-    componentMethodNames.claim(name);
-  }
-
-  /** Returns the list of {@link CodeBlock}s that need to go in the initialize method. */
-  public ImmutableList<CodeBlock> getInitializations() {
-    return ImmutableList.copyOf(initializations);
-  }
-
-  /**
-   * Returns a list of {@link CodeBlock}s for initializing {@link ComponentRequirement}s.
-   *
-   * <p>These initializations are kept separate from {@link #getInitializations()} because they must
-   * be executed before the initializations of any framework instance initializations in a
-   * superclass implementation that may depend on the instances. We cannot use the same strategy
-   * that we use for framework instances (i.e. wrap in a {@link dagger.internal.DelegateFactory} or
-   * {@link dagger.producers.internal.DelegateProducer} since the types of these initialized fields
-   * have no interface type that we can write a proxy for.
-   */
-  // TODO(cgdecker): can these be inlined with getInitializations() now that we've turned down
-  // ahead-of-time subcomponents?
-  public ImmutableList<CodeBlock> getComponentRequirementInitializations() {
-    return ImmutableList.copyOf(componentRequirementInitializations);
-  }
-
-  /**
-   * Returns the list of producer {@link Key}s that need cancellation statements in the cancellation
-   * listener method.
-   */
-  public ImmutableList<Key> getCancellableProducerKeys() {
-    return ImmutableList.copyOf(cancellableProducerKeys);
-  }
-
-  /** Generates the component and returns the resulting {@link TypeSpec.Builder}. */
-  public TypeSpec.Builder generate() {
-    modifiers().forEach(component::addModifiers);
-    fieldSpecsMap.asMap().values().forEach(component::addFields);
-    methodSpecsMap.asMap().values().forEach(component::addMethods);
-    typeSpecsMap.asMap().values().forEach(component::addTypes);
-    typeSuppliers.stream().map(Supplier::get).forEach(component::addType);
-    return component;
-  }
-
-  private ImmutableSet<Modifier> modifiers() {
-    if (isNested()) {
-      return ImmutableSet.of(PRIVATE, FINAL);
-    }
-    return graph.componentTypeElement().getModifiers().contains(PUBLIC)
-        // TODO(ronshapiro): perhaps all generated components should be non-public?
-        ? ImmutableSet.of(PUBLIC, FINAL)
-        : ImmutableSet.of(FINAL);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentInstanceBindingExpression.java b/java/dagger/internal/codegen/writing/ComponentInstanceBindingExpression.java
deleted file mode 100644
index 9fa10c6..0000000
--- a/java/dagger/internal/codegen/writing/ComponentInstanceBindingExpression.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-
-/** A binding expression for the instance of the component itself, i.e. {@code this}. */
-final class ComponentInstanceBindingExpression extends SimpleInvocationBindingExpression {
-  private final ClassName componentName;
-  private final ContributionBinding binding;
-
-  ComponentInstanceBindingExpression(ContributionBinding binding, ClassName componentName) {
-    super(binding);
-    this.binding = binding;
-    this.componentName = componentName;
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    return Expression.create(
-        binding.key().type(),
-        componentName.equals(requestingClass)
-            ? CodeBlock.of("this")
-            : CodeBlock.of("$T.this", componentName));
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentMethodBindingExpression.java b/java/dagger/internal/codegen/writing/ComponentMethodBindingExpression.java
deleted file mode 100644
index 7fa9aa3..0000000
--- a/java/dagger/internal/codegen/writing/ComponentMethodBindingExpression.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A binding expression that implements and uses a component method.
- *
- * <p>Dependents of this binding expression will just call the component method.
- */
-final class ComponentMethodBindingExpression extends MethodBindingExpression {
-  private final ComponentImplementation componentImplementation;
-  private final ComponentMethodDescriptor componentMethod;
-
-  ComponentMethodBindingExpression(
-      BindingRequest request,
-      ContributionBinding binding,
-      MethodImplementationStrategy methodImplementationStrategy,
-      BindingExpression wrappedBindingExpression,
-      ComponentImplementation componentImplementation,
-      ComponentMethodDescriptor componentMethod,
-      DaggerTypes types) {
-    super(
-        request,
-        binding,
-        methodImplementationStrategy,
-        wrappedBindingExpression,
-        componentImplementation,
-        types);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.componentMethod = checkNotNull(componentMethod);
-  }
-
-  @Override
-  protected CodeBlock getComponentMethodImplementation(
-      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
-    // There could be several methods on the component for the same request key and kind.
-    // Only one should use the BindingMethodImplementation; the others can delegate that one. So
-    // use methodImplementation.body() only if componentMethod equals the method for this instance.
-
-    // Separately, the method might be defined on a supertype that is also a supertype of some
-    // parent component. In that case, the same ComponentMethodDescriptor will be used to add a CMBE
-    // for the parent and the child. Only the parent's should use the BindingMethodImplementation;
-    // the child's can delegate to the parent. So use methodImplementation.body() only if
-    // componentName equals the component for this instance.
-    return componentMethod.equals(this.componentMethod) && component.equals(componentImplementation)
-        ? methodBodyForComponentMethod(componentMethod)
-        : super.getComponentMethodImplementation(componentMethod, component);
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    // If a component method returns a primitive, update the expression's type which might be boxed.
-    Expression expression = super.getDependencyExpression(requestingClass);
-    TypeMirror methodReturnType = componentMethod.methodElement().getReturnType();
-    return methodReturnType.getKind().isPrimitive()
-        ? Expression.create(methodReturnType, expression.codeBlock())
-        : expression;
-  }
-
-  @Override
-  protected void addMethod() {}
-
-  @Override
-  protected String methodName() {
-    return componentMethod.methodElement().getSimpleName().toString();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentProvisionBindingExpression.java b/java/dagger/internal/codegen/writing/ComponentProvisionBindingExpression.java
deleted file mode 100644
index 53914b6..0000000
--- a/java/dagger/internal/codegen/writing/ComponentProvisionBindingExpression.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.Preconditions;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.javapoet.Expression;
-
-/** A binding expression for component provision methods. */
-final class ComponentProvisionBindingExpression extends SimpleInvocationBindingExpression {
-  private final ProvisionBinding binding;
-  private final BindingGraph bindingGraph;
-  private final ComponentRequirementExpressions componentRequirementExpressions;
-  private final CompilerOptions compilerOptions;
-
-  ComponentProvisionBindingExpression(
-      ProvisionBinding binding,
-      BindingGraph bindingGraph,
-      ComponentRequirementExpressions componentRequirementExpressions,
-      CompilerOptions compilerOptions) {
-    super(binding);
-    this.binding = binding;
-    this.bindingGraph = checkNotNull(bindingGraph);
-    this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
-    this.compilerOptions = checkNotNull(compilerOptions);
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    CodeBlock invocation =
-        CodeBlock.of(
-            "$L.$L()",
-            componentRequirementExpressions.getExpression(componentRequirement(), requestingClass),
-            binding.bindingElement().get().getSimpleName());
-    return Expression.create(
-        binding.contributedPrimitiveType().orElse(binding.key().type()),
-        maybeCheckForNull(binding, compilerOptions, invocation));
-  }
-
-  private ComponentRequirement componentRequirement() {
-    return bindingGraph
-        .componentDescriptor()
-        .getDependencyThatDefinesMethod(binding.bindingElement().get());
-  }
-
-  static CodeBlock maybeCheckForNull(
-      ProvisionBinding binding, CompilerOptions compilerOptions, CodeBlock invocation) {
-    return binding.shouldCheckForNull(compilerOptions)
-        ? CodeBlock.of("$T.checkNotNullFromComponent($L)", Preconditions.class, invocation)
-        : invocation;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentRequirementBindingExpression.java b/java/dagger/internal/codegen/writing/ComponentRequirementBindingExpression.java
deleted file mode 100644
index 299f279..0000000
--- a/java/dagger/internal/codegen/writing/ComponentRequirementBindingExpression.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import com.squareup.javapoet.ClassName;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-
-/**
- * A binding expression for instances bound with {@link dagger.BindsInstance} and instances of
- * {@linkplain dagger.Component#dependencies() component} and {@linkplain
- * dagger.producers.ProductionComponent#dependencies() production component dependencies}.
- */
-final class ComponentRequirementBindingExpression extends SimpleInvocationBindingExpression {
-  private final ComponentRequirement componentRequirement;
-  private final ComponentRequirementExpressions componentRequirementExpressions;
-
-  ComponentRequirementBindingExpression(
-      ContributionBinding binding,
-      ComponentRequirement componentRequirement,
-      ComponentRequirementExpressions componentRequirementExpressions) {
-    super(binding);
-    this.componentRequirement = componentRequirement;
-    this.componentRequirementExpressions = componentRequirementExpressions;
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    return Expression.create(
-        componentRequirement.type(),
-        componentRequirementExpressions.getExpression(componentRequirement, requestingClass));
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentRequirementExpression.java b/java/dagger/internal/codegen/writing/ComponentRequirementExpression.java
deleted file mode 100644
index 13008b8..0000000
--- a/java/dagger/internal/codegen/writing/ComponentRequirementExpression.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ComponentRequirement;
-
-/**
- * A factory for expressions of {@link ComponentRequirement}s in the generated component. This is
- * <em>not</em> a {@link BindingExpression}, since {@link ComponentRequirement}s do not have a
- * {@link dagger.model.Key}. See {@link ComponentRequirementBindingExpression} for binding
- * expressions that are themselves a component requirement.
- */
-interface ComponentRequirementExpression {
-  /**
-   * Returns an expression for the {@link ComponentRequirement} to be used when implementing a
-   * component method. This may add a field or method to the component in order to reference the
-   * component requirement outside of the {@code initialize()} methods.
-   */
-  CodeBlock getExpression(ClassName requestingClass);
-
-  /**
-   * Returns an expression for the {@link ComponentRequirement} to be used only within {@code
-   * initialize()} methods, where the constructor parameters are available.
-   *
-   * <p>When accessing this expression from a subcomponent, this may cause a field to be initialized
-   * or a method to be added in the component that owns this {@link ComponentRequirement}.
-   */
-  default CodeBlock getExpressionDuringInitialization(ClassName requestingClass) {
-    return getExpression(requestingClass);
-  }
-
-  /**
-   * Returns the expression for the {@link ComponentRequirement} to be used when reimplementing a
-   * modifiable module method.
-   */
-  default CodeBlock getModifiableModuleMethodExpression(ClassName requestingClass) {
-    return CodeBlock.of("return $L", getExpression(requestingClass));
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ComponentRequirementExpressions.java b/java/dagger/internal/codegen/writing/ComponentRequirementExpressions.java
deleted file mode 100644
index 653a7a2..0000000
--- a/java/dagger/internal/codegen/writing/ComponentRequirementExpressions.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Suppliers.memoize;
-import static dagger.internal.codegen.writing.ComponentImplementation.FieldSpecKind.COMPONENT_REQUIREMENT_FIELD;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.google.common.base.Supplier;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.inject.Inject;
-import javax.lang.model.element.TypeElement;
-
-/**
- * A central repository of expressions used to access any {@link ComponentRequirement} available to
- * a component.
- */
-@PerComponentImplementation
-public final class ComponentRequirementExpressions {
-
-  // TODO(dpb,ronshapiro): refactor this and ComponentBindingExpressions into a
-  // HierarchicalComponentMap<K, V>, or perhaps this use a flattened ImmutableMap, built from its
-  // parents? If so, maybe make ComponentRequirementExpression.Factory create it.
-
-  private final Optional<ComponentRequirementExpressions> parent;
-  private final Map<ComponentRequirement, ComponentRequirementExpression>
-      componentRequirementExpressions = new HashMap<>();
-  private final BindingGraph graph;
-  private final ComponentImplementation componentImplementation;
-  private final ModuleProxies moduleProxies;
-
-  // TODO(ronshapiro): give ComponentImplementation a graph() method
-  @Inject
-  ComponentRequirementExpressions(
-      @ParentComponent Optional<ComponentRequirementExpressions> parent,
-      BindingGraph graph,
-      ComponentImplementation componentImplementation,
-      DaggerElements elements,
-      ModuleProxies moduleProxies) {
-    this.parent = parent;
-    this.graph = graph;
-    this.componentImplementation = componentImplementation;
-    this.moduleProxies = moduleProxies;
-  }
-
-  /**
-   * Returns an expression for the {@code componentRequirement} to be used when implementing a
-   * component method. This may add a field or method to the component in order to reference the
-   * component requirement outside of the {@code initialize()} methods.
-   */
-  CodeBlock getExpression(ComponentRequirement componentRequirement, ClassName requestingClass) {
-    return getExpression(componentRequirement).getExpression(requestingClass);
-  }
-
-  /**
-   * Returns an expression for the {@code componentRequirement} to be used only within {@code
-   * initialize()} methods, where the component constructor parameters are available.
-   *
-   * <p>When accessing this expression from a subcomponent, this may cause a field to be initialized
-   * or a method to be added in the component that owns this {@link ComponentRequirement}.
-   */
-  CodeBlock getExpressionDuringInitialization(
-      ComponentRequirement componentRequirement, ClassName requestingClass) {
-    return getExpression(componentRequirement).getExpressionDuringInitialization(requestingClass);
-  }
-
-  ComponentRequirementExpression getExpression(ComponentRequirement componentRequirement) {
-    if (graph.componentRequirements().contains(componentRequirement)) {
-      return componentRequirementExpressions.computeIfAbsent(
-          componentRequirement, this::createField);
-    }
-    if (parent.isPresent()) {
-      return parent.get().getExpression(componentRequirement);
-    }
-
-    throw new IllegalStateException(
-        "no component requirement expression found for " + componentRequirement);
-  }
-
-  /** Returns a field for a {@link ComponentRequirement}. */
-  private ComponentRequirementExpression createField(ComponentRequirement requirement) {
-    if (componentImplementation.componentDescriptor().hasCreator()) {
-      return new ComponentParameterField(requirement, componentImplementation, Optional.empty());
-    } else if (graph.factoryMethod().isPresent()
-        && graph.factoryMethodParameters().containsKey(requirement)) {
-      String parameterName =
-          graph.factoryMethodParameters().get(requirement).getSimpleName().toString();
-      return new ComponentParameterField(
-          requirement, componentImplementation, Optional.of(parameterName));
-    } else if (requirement.kind().isModule()) {
-      return new InstantiableModuleField(requirement, componentImplementation);
-    } else {
-      throw new AssertionError(
-          String.format("Can't create %s in %s", requirement, componentImplementation.name()));
-    }
-  }
-
-  private abstract static class AbstractField implements ComponentRequirementExpression {
-    final ComponentRequirement componentRequirement;
-    final ComponentImplementation componentImplementation;
-    final String fieldName;
-    private final Supplier<MemberSelect> field = memoize(this::addField);
-
-    private AbstractField(
-        ComponentRequirement componentRequirement,
-        ComponentImplementation componentImplementation) {
-      this.componentRequirement = checkNotNull(componentRequirement);
-      this.componentImplementation = checkNotNull(componentImplementation);
-      // Note: The field name is being claimed eagerly here even though we don't know at this point
-      // whether or not the requirement will even need a field. This is done because:
-      // A) ComponentParameterField wants to ensure that it doesn't give the parameter the same name
-      //    as any field in the component, which requires that it claim a "field name" for itself
-      //    when naming the parameter.
-      // B) The parameter name may be needed before the field name is.
-      // C) We want to prefer giving the best name to the field rather than the parameter given its
-      //    wider scope.
-      this.fieldName =
-          componentImplementation.getUniqueFieldName(componentRequirement.variableName());
-    }
-
-    @Override
-    public CodeBlock getExpression(ClassName requestingClass) {
-      return field.get().getExpressionFor(requestingClass);
-    }
-
-    private MemberSelect addField() {
-      FieldSpec field = createField();
-      componentImplementation.addField(COMPONENT_REQUIREMENT_FIELD, field);
-      componentImplementation.addComponentRequirementInitialization(fieldInitialization(field));
-      return MemberSelect.localField(componentImplementation.name(), fieldName);
-    }
-
-    private FieldSpec createField() {
-      return FieldSpec.builder(TypeName.get(componentRequirement.type()), fieldName, PRIVATE, FINAL)
-          .build();
-    }
-
-    /** Returns the {@link CodeBlock} that initializes the component field during construction. */
-    abstract CodeBlock fieldInitialization(FieldSpec componentField);
-  }
-
-  /**
-   * A {@link ComponentRequirementExpression} for {@link ComponentRequirement}s that can be
-   * instantiated by the component (i.e. a static class with a no-arg constructor).
-   */
-  private final class InstantiableModuleField extends AbstractField {
-    private final TypeElement moduleElement;
-
-    private InstantiableModuleField(
-        ComponentRequirement module, ComponentImplementation componentImplementation) {
-      super(module, componentImplementation);
-      checkArgument(module.kind().isModule());
-      this.moduleElement = module.typeElement();
-    }
-
-    @Override
-    CodeBlock fieldInitialization(FieldSpec componentField) {
-      return CodeBlock.of(
-          "this.$N = $L;",
-          componentField,
-          moduleProxies.newModuleInstance(moduleElement, componentImplementation.name()));
-    }
-  }
-
-  /**
-   * A {@link ComponentRequirementExpression} for {@link ComponentRequirement}s that are passed in
-   * as parameters to the component's constructor.
-   */
-  private static final class ComponentParameterField extends AbstractField {
-    private final String parameterName;
-
-    private ComponentParameterField(
-        ComponentRequirement componentRequirement,
-        ComponentImplementation componentImplementation,
-        Optional<String> name) {
-      super(componentRequirement, componentImplementation);
-      // Get the name that the component implementation will use for its parameter for the
-      // requirement. If the given name is different than the name of the field created for the
-      // requirement (as may be the case when the parameter name is derived from a user-written
-      // factory method parameter), just use that as the base name for the parameter. Otherwise,
-      // append "Param" to the end of the name to differentiate.
-      // In either case, componentImplementation.getParameterName() will ensure that the final name
-      // that is used is not the same name as any field in the component even if there's something
-      // weird where the component actually has fields named, say, "foo" and "fooParam".
-      String baseName = name.filter(n -> !n.equals(fieldName)).orElse(fieldName + "Param");
-      this.parameterName = componentImplementation.getParameterName(componentRequirement, baseName);
-    }
-
-    @Override
-    public CodeBlock getExpressionDuringInitialization(ClassName requestingClass) {
-      if (componentImplementation.name().equals(requestingClass)) {
-        return CodeBlock.of("$L", parameterName);
-      } else {
-        // requesting this component requirement during initialization of a child component requires
-        // it to be accessed from a field and not the parameter (since it is no longer available)
-        return getExpression(requestingClass);
-      }
-    }
-
-    @Override
-    CodeBlock fieldInitialization(FieldSpec componentField) {
-      // Don't checkNotNull here because the parameter may be nullable; if it isn't, the caller
-      // should handle checking that before passing the parameter.
-      return CodeBlock.of("this.$N = $L;", componentField, parameterName);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/DelegateBindingExpression.java b/java/dagger/internal/codegen/writing/DelegateBindingExpression.java
deleted file mode 100644
index 3361132..0000000
--- a/java/dagger/internal/codegen/writing/DelegateBindingExpression.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.RequestKinds.requestType;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static dagger.model.BindingKind.DELEGATE;
-
-import com.squareup.javapoet.ClassName;
-import dagger.internal.codegen.binding.Binding;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.BindsTypeChecker;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.RequestKind;
-import javax.lang.model.type.TypeMirror;
-
-/** A {@link dagger.internal.codegen.writing.BindingExpression} for {@code @Binds} methods. */
-final class DelegateBindingExpression extends BindingExpression {
-  private final ContributionBinding binding;
-  private final RequestKind requestKind;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final DaggerTypes types;
-  private final BindsTypeChecker bindsTypeChecker;
-
-  DelegateBindingExpression(
-      ContributionBinding binding,
-      RequestKind requestKind,
-      ComponentBindingExpressions componentBindingExpressions,
-      DaggerTypes types,
-      DaggerElements elements) {
-    this.binding = checkNotNull(binding);
-    this.requestKind = checkNotNull(requestKind);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-    this.types = checkNotNull(types);
-    this.bindsTypeChecker = new BindsTypeChecker(types, elements);
-  }
-
-  /**
-   * Returns {@code true} if the {@code @Binds} binding's scope is stronger than the scope of the
-   * binding it depends on.
-   */
-  static boolean isBindsScopeStrongerThanDependencyScope(
-      ContributionBinding bindsBinding, BindingGraph graph) {
-    checkArgument(bindsBinding.kind().equals(DELEGATE));
-    Binding dependencyBinding =
-        graph.contributionBinding(getOnlyElement(bindsBinding.dependencies()).key());
-    ScopeKind bindsScope = ScopeKind.get(bindsBinding);
-    ScopeKind dependencyScope = ScopeKind.get(dependencyBinding);
-    return bindsScope.isStrongerScopeThan(dependencyScope);
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    Expression delegateExpression =
-        componentBindingExpressions.getDependencyExpression(
-            bindingRequest(getOnlyElement(binding.dependencies()).key(), requestKind),
-            requestingClass);
-
-    TypeMirror contributedType = binding.contributedType();
-    switch (requestKind) {
-      case INSTANCE:
-        return instanceRequiresCast(delegateExpression, requestingClass)
-            ? delegateExpression.castTo(contributedType)
-            : delegateExpression;
-      default:
-        return castToRawTypeIfNecessary(
-            delegateExpression, requestType(requestKind, contributedType, types));
-    }
-  }
-
-  private boolean instanceRequiresCast(Expression delegateExpression, ClassName requestingClass) {
-    // delegateExpression.type() could be Object if expression is satisfied with a raw
-    // Provider's get() method.
-    return !bindsTypeChecker.isAssignable(
-        delegateExpression.type(), binding.contributedType(), binding.contributionType())
-        && isTypeAccessibleFrom(binding.contributedType(), requestingClass.packageName());
-  }
-
-  /**
-   * If {@code delegateExpression} can be assigned to {@code desiredType} safely, then {@code
-   * delegateExpression} is returned unchanged. If the {@code delegateExpression} is already a raw
-   * type, returns {@code delegateExpression} as well, as casting would have no effect. Otherwise,
-   * returns a {@link Expression#castTo(TypeMirror) casted} version of {@code delegateExpression}
-   * to the raw type of {@code desiredType}.
-   */
-  // TODO(ronshapiro): this probably can be generalized for usage in InjectionMethods
-  private Expression castToRawTypeIfNecessary(
-      Expression delegateExpression, TypeMirror desiredType) {
-    if (types.isAssignable(delegateExpression.type(), desiredType)) {
-      return delegateExpression;
-    }
-    return delegateExpression.castTo(types.erasure(desiredType));
-  }
-
-  private enum ScopeKind {
-    UNSCOPED,
-    SINGLE_CHECK,
-    DOUBLE_CHECK,
-    ;
-
-    static ScopeKind get(Binding binding) {
-      return binding
-          .scope()
-          .map(scope -> scope.isReusable() ? SINGLE_CHECK : DOUBLE_CHECK)
-          .orElse(UNSCOPED);
-    }
-
-    boolean isStrongerScopeThan(ScopeKind other) {
-      return this.ordinal() > other.ordinal();
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/DelegatingFrameworkInstanceCreationExpression.java b/java/dagger/internal/codegen/writing/DelegatingFrameworkInstanceCreationExpression.java
deleted file mode 100644
index a7f9556..0000000
--- a/java/dagger/internal/codegen/writing/DelegatingFrameworkInstanceCreationExpression.java
+++ /dev/null
@@ -1,57 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import dagger.model.DependencyRequest;
-
-/** A framework instance creation expression for a {@link dagger.Binds @Binds} binding. */
-final class DelegatingFrameworkInstanceCreationExpression
-    implements FrameworkInstanceCreationExpression {
-
-  private final ContributionBinding binding;
-  private final ComponentImplementation componentImplementation;
-  private final ComponentBindingExpressions componentBindingExpressions;
-
-  DelegatingFrameworkInstanceCreationExpression(
-      ContributionBinding binding,
-      ComponentImplementation componentImplementation,
-      ComponentBindingExpressions componentBindingExpressions) {
-    this.binding = checkNotNull(binding);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    DependencyRequest dependency = getOnlyElement(binding.dependencies());
-    return CodeBlocks.cast(
-        componentBindingExpressions
-            .getDependencyExpression(
-                bindingRequest(dependency.key(), binding.frameworkType()),
-                componentImplementation.name())
-            .codeBlock(),
-        binding.frameworkType().frameworkClass());
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/DependencyMethodProducerCreationExpression.java b/java/dagger/internal/codegen/writing/DependencyMethodProducerCreationExpression.java
deleted file mode 100644
index 5ac1e8f..0000000
--- a/java/dagger/internal/codegen/writing/DependencyMethodProducerCreationExpression.java
+++ /dev/null
@@ -1,100 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
-import static dagger.internal.codegen.javapoet.TypeNames.dependencyMethodProducerOf;
-import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-
-/**
- * A {@link dagger.producers.Producer} creation expression for a production method on a production
- * component's {@linkplain dagger.producers.ProductionComponent#dependencies()} dependency} that
- * returns a {@link com.google.common.util.concurrent.ListenableFuture}.
- */
-// TODO(dpb): Resolve with DependencyMethodProviderCreationExpression.
-final class DependencyMethodProducerCreationExpression
-    implements FrameworkInstanceCreationExpression {
-  private final ContributionBinding binding;
-  private final ComponentImplementation componentImplementation;
-  private final ComponentRequirementExpressions componentRequirementExpressions;
-  private final BindingGraph graph;
-
-  DependencyMethodProducerCreationExpression(
-      ContributionBinding binding,
-      ComponentImplementation componentImplementation,
-      ComponentRequirementExpressions componentRequirementExpressions,
-      BindingGraph graph) {
-    this.binding = checkNotNull(binding);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
-    this.graph = checkNotNull(graph);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    ComponentRequirement dependency =
-        graph.componentDescriptor().getDependencyThatDefinesMethod(binding.bindingElement().get());
-    FieldSpec dependencyField =
-        FieldSpec.builder(
-                ClassName.get(dependency.typeElement()), dependency.variableName(), PRIVATE, FINAL)
-            .initializer(
-                componentRequirementExpressions.getExpressionDuringInitialization(
-                    dependency,
-                    // This isn't a real class name, but we want the requesting class for the
-                    // expression to *not* be the same class as the component implementation,
-                    // because it isn't... it's an anonymous inner class.
-                    // TODO(cgdecker): If we didn't use an anonymous inner class here but instead
-                    // generated a named nested class as with
-                    // DependencyMethodProviderCreationExpression, we wouldn't need to deal with
-                    // this and might be able to avoid potentially creating an extra field in the
-                    // component?
-                    componentImplementation.name().nestedClass("Anonymous")))
-            .build();
-    // TODO(b/70395982): Explore using a private static type instead of an anonymous class.
-    TypeName keyType = TypeName.get(binding.key().type());
-    return CodeBlock.of(
-        "$L",
-        anonymousClassBuilder("")
-            .superclass(dependencyMethodProducerOf(keyType))
-            .addField(dependencyField)
-            .addMethod(
-                methodBuilder("callDependencyMethod")
-                    .addAnnotation(Override.class)
-                    .addModifiers(PUBLIC)
-                    .returns(listenableFutureOf(keyType))
-                    .addStatement(
-                        "return $N.$L()",
-                        dependencyField,
-                        binding.bindingElement().get().getSimpleName())
-                    .build())
-            .build());
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/DependencyMethodProviderCreationExpression.java b/java/dagger/internal/codegen/writing/DependencyMethodProviderCreationExpression.java
deleted file mode 100644
index 5a40c02..0000000
--- a/java/dagger/internal/codegen/writing/DependencyMethodProviderCreationExpression.java
+++ /dev/null
@@ -1,130 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
-import static dagger.internal.codegen.writing.ComponentImplementation.TypeSpecKind.COMPONENT_PROVISION_FACTORY;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreTypes;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import javax.lang.model.element.Element;
-
-/**
- * A {@link javax.inject.Provider} creation expression for a provision method on a component's
- * {@linkplain dagger.Component#dependencies()} dependency}.
- */
-// TODO(dpb): Resolve with DependencyMethodProducerCreationExpression.
-final class DependencyMethodProviderCreationExpression
-    implements FrameworkInstanceCreationExpression {
-
-  private final ComponentImplementation componentImplementation;
-  private final ComponentRequirementExpressions componentRequirementExpressions;
-  private final CompilerOptions compilerOptions;
-  private final BindingGraph graph;
-  private final ContributionBinding binding;
-
-  DependencyMethodProviderCreationExpression(
-      ContributionBinding binding,
-      ComponentImplementation componentImplementation,
-      ComponentRequirementExpressions componentRequirementExpressions,
-      CompilerOptions compilerOptions,
-      BindingGraph graph) {
-    this.binding = checkNotNull(binding);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
-    this.compilerOptions = checkNotNull(compilerOptions);
-    this.graph = checkNotNull(graph);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    // TODO(sameb): The Provider.get() throws a very vague NPE.  The stack trace doesn't
-    // help to figure out what the method or return type is.  If we include a string
-    // of the return type or method name in the error message, that can defeat obfuscation.
-    // We can easily include the raw type (no generics) + annotation type (no values),
-    // using .class & String.format -- but that wouldn't be the whole story.
-    // What should we do?
-    CodeBlock invocation =
-        ComponentProvisionBindingExpression.maybeCheckForNull(
-            (ProvisionBinding) binding,
-            compilerOptions,
-            CodeBlock.of(
-                "$N.$N()", dependency().variableName(), provisionMethod().getSimpleName()));
-    ClassName dependencyClassName = ClassName.get(dependency().typeElement());
-    TypeName keyType = TypeName.get(binding.key().type());
-    MethodSpec.Builder getMethod =
-        methodBuilder("get")
-            .addAnnotation(Override.class)
-            .addModifiers(PUBLIC)
-            .returns(keyType)
-            .addStatement("return $L", invocation);
-    if (binding.nullableType().isPresent()) {
-      getMethod.addAnnotation(ClassName.get(MoreTypes.asTypeElement(binding.nullableType().get())));
-    }
-    componentImplementation.addType(
-        COMPONENT_PROVISION_FACTORY,
-        classBuilder(factoryClassName())
-            .addSuperinterface(providerOf(keyType))
-            .addModifiers(PRIVATE, STATIC)
-            .addField(dependencyClassName, dependency().variableName(), PRIVATE, FINAL)
-            .addMethod(
-                constructorBuilder()
-                    .addParameter(dependencyClassName, dependency().variableName())
-                    .addStatement("this.$1L = $1L", dependency().variableName())
-                    .build())
-            .addMethod(getMethod.build())
-            .build());
-    return CodeBlock.of(
-        "new $T($L)",
-        factoryClassName(),
-        componentRequirementExpressions.getExpressionDuringInitialization(
-            dependency(), componentImplementation.name()));
-  }
-
-  private ClassName factoryClassName() {
-    String factoryName =
-        ClassName.get(dependency().typeElement()).toString().replace('.', '_')
-            + "_"
-            + binding.bindingElement().get().getSimpleName();
-    return componentImplementation.name().nestedClass(factoryName);
-  }
-
-  private ComponentRequirement dependency() {
-    return graph.componentDescriptor().getDependencyThatDefinesMethod(provisionMethod());
-  }
-
-  private Element provisionMethod() {
-    return binding.bindingElement().get();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/DerivedFromFrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/writing/DerivedFromFrameworkInstanceBindingExpression.java
deleted file mode 100644
index 6e5dca8..0000000
--- a/java/dagger/internal/codegen/writing/DerivedFromFrameworkInstanceBindingExpression.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-
-import com.squareup.javapoet.ClassName;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-
-/** A binding expression that depends on a framework instance. */
-final class DerivedFromFrameworkInstanceBindingExpression extends BindingExpression {
-
-  private final BindingRequest frameworkRequest;
-  private final RequestKind requestKind;
-  private final FrameworkType frameworkType;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final DaggerTypes types;
-
-  DerivedFromFrameworkInstanceBindingExpression(
-      Key key,
-      FrameworkType frameworkType,
-      RequestKind requestKind,
-      ComponentBindingExpressions componentBindingExpressions,
-      DaggerTypes types) {
-    this.frameworkRequest = bindingRequest(key, frameworkType);
-    this.requestKind = checkNotNull(requestKind);
-    this.frameworkType = checkNotNull(frameworkType);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-    this.types = checkNotNull(types);
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    return frameworkType.to(
-        requestKind,
-        componentBindingExpressions.getDependencyExpression(frameworkRequest, requestingClass),
-        types);
-  }
-
-  @Override
-  Expression getDependencyExpressionForComponentMethod(
-      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
-    Expression frameworkInstance =
-        componentBindingExpressions.getDependencyExpressionForComponentMethod(
-            frameworkRequest, componentMethod, component);
-    return frameworkType.to(requestKind, frameworkInstance, types);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/FactoryGenerator.java b/java/dagger/internal/codegen/writing/FactoryGenerator.java
deleted file mode 100644
index 70edd1a..0000000
--- a/java/dagger/internal/codegen/writing/FactoryGenerator.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2014 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.writing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Maps.transformValues;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedParameters;
-import static dagger.internal.codegen.binding.ContributionBinding.FactoryCreationStrategy.DELEGATE;
-import static dagger.internal.codegen.binding.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
-import static dagger.internal.codegen.binding.SourceFiles.bindingTypeElementTypeVariableNames;
-import static dagger.internal.codegen.binding.SourceFiles.frameworkFieldUsages;
-import static dagger.internal.codegen.binding.SourceFiles.frameworkTypeUsageStatement;
-import static dagger.internal.codegen.binding.SourceFiles.generateBindingFieldsForDependencies;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-import static dagger.internal.codegen.binding.SourceFiles.parameterizedGeneratedTypeNameForBinding;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
-import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeNames.factoryOf;
-import static dagger.internal.codegen.writing.GwtCompatibility.gwtIncompatibleAnnotation;
-import static dagger.model.BindingKind.PROVISION;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.Factory;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.base.UniqueNameSet;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.writing.InjectionMethods.InjectionSiteMethod;
-import dagger.internal.codegen.writing.InjectionMethods.ProvisionMethod;
-import dagger.model.BindingKind;
-import dagger.model.DependencyRequest;
-import java.util.List;
-import java.util.Optional;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-
-/**
- * Generates {@link Factory} implementations from {@link ProvisionBinding} instances for {@link
- * Inject} constructors.
- */
-public final class FactoryGenerator extends SourceFileGenerator<ProvisionBinding> {
-  private final DaggerTypes types;
-  private final CompilerOptions compilerOptions;
-  private final KotlinMetadataUtil metadataUtil;
-
-  @Inject
-  FactoryGenerator(
-      Filer filer,
-      SourceVersion sourceVersion,
-      DaggerTypes types,
-      DaggerElements elements,
-      CompilerOptions compilerOptions,
-      KotlinMetadataUtil metadataUtil) {
-    super(filer, elements, sourceVersion);
-    this.types = types;
-    this.compilerOptions = compilerOptions;
-    this.metadataUtil = metadataUtil;
-  }
-
-  @Override
-  public ClassName nameGeneratedType(ProvisionBinding binding) {
-    return generatedClassNameForBinding(binding);
-  }
-
-  @Override
-  public Element originatingElement(ProvisionBinding binding) {
-    // we only create factories for bindings that have a binding element
-    return binding.bindingElement().get();
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(ProvisionBinding binding) {
-    // We don't want to write out resolved bindings -- we want to write out the generic version.
-    checkArgument(!binding.unresolved().isPresent());
-    checkArgument(binding.bindingElement().isPresent());
-
-    if (binding.factoryCreationStrategy().equals(DELEGATE)) {
-      return Optional.empty();
-    }
-
-    return Optional.of(factoryBuilder(binding));
-  }
-
-  private TypeSpec.Builder factoryBuilder(ProvisionBinding binding) {
-    TypeSpec.Builder factoryBuilder =
-        classBuilder(nameGeneratedType(binding))
-            .addModifiers(PUBLIC, FINAL)
-            .addTypeVariables(bindingTypeElementTypeVariableNames(binding));
-
-    factoryTypeName(binding).ifPresent(factoryBuilder::addSuperinterface);
-    addConstructorAndFields(binding, factoryBuilder);
-    factoryBuilder.addMethod(getMethod(binding));
-    addCreateMethod(binding, factoryBuilder);
-
-    factoryBuilder.addMethod(ProvisionMethod.create(binding, compilerOptions, metadataUtil));
-    gwtIncompatibleAnnotation(binding).ifPresent(factoryBuilder::addAnnotation);
-
-    return factoryBuilder;
-  }
-
-  private void addConstructorAndFields(ProvisionBinding binding, TypeSpec.Builder factoryBuilder) {
-    if (binding.factoryCreationStrategy().equals(SINGLETON_INSTANCE)) {
-      return;
-    }
-    // TODO(bcorso): Make the constructor private?
-    MethodSpec.Builder constructor = constructorBuilder().addModifiers(PUBLIC);
-    constructorParams(binding).forEach(
-        param -> {
-          constructor.addParameter(param).addStatement("this.$1N = $1N", param);
-          factoryBuilder.addField(
-              FieldSpec.builder(param.type, param.name, PRIVATE, FINAL).build());
-        });
-    factoryBuilder.addMethod(constructor.build());
-  }
-
-  private ImmutableList<ParameterSpec> constructorParams(ProvisionBinding binding) {
-    ImmutableList.Builder<ParameterSpec> params = ImmutableList.builder();
-    moduleParameter(binding).ifPresent(params::add);
-    frameworkFields(binding).values().forEach(field -> params.add(toParameter(field)));
-    return params.build();
-  }
-
-  private Optional<ParameterSpec> moduleParameter(ProvisionBinding binding) {
-    if (binding.requiresModuleInstance()) {
-      // TODO(bcorso, dpb): Should this use contributingModule()?
-      TypeName type = TypeName.get(binding.bindingTypeElement().get().asType());
-      return Optional.of(ParameterSpec.builder(type, "module").build());
-    }
-    return Optional.empty();
-  }
-
-  private ImmutableMap<DependencyRequest, FieldSpec> frameworkFields(ProvisionBinding binding) {
-    UniqueNameSet uniqueFieldNames = new UniqueNameSet();
-    // TODO(bcorso, dpb): Add a test for the case when a Factory parameter is named "module".
-    moduleParameter(binding).ifPresent(module -> uniqueFieldNames.claim(module.name));
-    return ImmutableMap.copyOf(
-        transformValues(
-            generateBindingFieldsForDependencies(binding),
-            field ->
-                FieldSpec.builder(
-                        field.type(), uniqueFieldNames.getUniqueName(field.name()), PRIVATE, FINAL)
-                    .build()));
-  }
-
-  private void addCreateMethod(ProvisionBinding binding, TypeSpec.Builder factoryBuilder) {
-    // If constructing a factory for @Inject or @Provides bindings, we use a static create method
-    // so that generated components can avoid having to refer to the generic types
-    // of the factory.  (Otherwise they may have visibility problems referring to the types.)
-    MethodSpec.Builder createMethodBuilder =
-        methodBuilder("create")
-            .addModifiers(PUBLIC, STATIC)
-            .returns(parameterizedGeneratedTypeNameForBinding(binding))
-            .addTypeVariables(bindingTypeElementTypeVariableNames(binding));
-
-    switch (binding.factoryCreationStrategy()) {
-      case SINGLETON_INSTANCE:
-        FieldSpec.Builder instanceFieldBuilder =
-            FieldSpec.builder(nameGeneratedType(binding), "INSTANCE", PRIVATE, STATIC, FINAL)
-                .initializer("new $T()", nameGeneratedType(binding));
-
-        if (!bindingTypeElementTypeVariableNames(binding).isEmpty()) {
-          // If the factory has type parameters, ignore them in the field declaration & initializer
-          instanceFieldBuilder.addAnnotation(suppressWarnings(RAWTYPES));
-          createMethodBuilder.addAnnotation(suppressWarnings(UNCHECKED));
-        }
-
-        ClassName instanceHolderName = nameGeneratedType(binding).nestedClass("InstanceHolder");
-        createMethodBuilder.addStatement("return $T.INSTANCE", instanceHolderName);
-        factoryBuilder.addType(
-            TypeSpec.classBuilder(instanceHolderName)
-                .addModifiers(PRIVATE, STATIC, FINAL)
-                .addField(instanceFieldBuilder.build())
-                .build());
-        break;
-      case CLASS_CONSTRUCTOR:
-        List<ParameterSpec> params = constructorParams(binding);
-        createMethodBuilder.addParameters(params);
-        createMethodBuilder.addStatement(
-            "return new $T($L)",
-            parameterizedGeneratedTypeNameForBinding(binding),
-            makeParametersCodeBlock(Lists.transform(params, input -> CodeBlock.of("$N", input))));
-        break;
-      default:
-        throw new AssertionError();
-    }
-    factoryBuilder.addMethod(createMethodBuilder.build());
-  }
-
-  private MethodSpec getMethod(ProvisionBinding binding) {
-    TypeName providedTypeName = providedTypeName(binding);
-    MethodSpec.Builder getMethod =
-        methodBuilder("get")
-            .addModifiers(PUBLIC)
-            .returns(providedTypeName)
-            .addParameters(
-                // The 'get' method for an assisted injection type takes in the assisted parameters.
-                assistedParameters(binding).stream()
-                    .map(ParameterSpec::get)
-                    .collect(toImmutableList()));
-
-    if (factoryTypeName(binding).isPresent()) {
-      getMethod.addAnnotation(Override.class);
-    }
-
-    ImmutableMap<DependencyRequest, FieldSpec> frameworkFields = frameworkFields(binding);
-    CodeBlock invokeNewInstance =
-        ProvisionMethod.invoke(
-            binding,
-            request ->
-                frameworkTypeUsageStatement(
-                    CodeBlock.of("$N", frameworkFields.get(request)), request.kind()),
-            nameGeneratedType(binding),
-            moduleParameter(binding).map(module -> CodeBlock.of("$N", module)),
-            compilerOptions,
-            metadataUtil);
-
-    if (binding.kind().equals(PROVISION)) {
-      binding
-          .nullableType()
-          .ifPresent(nullableType -> CodeBlocks.addAnnotation(getMethod, nullableType));
-      getMethod.addStatement("return $L", invokeNewInstance);
-    } else if (!binding.injectionSites().isEmpty()) {
-      CodeBlock instance = CodeBlock.of("instance");
-      getMethod
-          .addStatement("$T $L = $L", providedTypeName, instance, invokeNewInstance)
-          .addCode(
-              InjectionSiteMethod.invokeAll(
-                  binding.injectionSites(),
-                  nameGeneratedType(binding),
-                  instance,
-                  binding.key().type(),
-                  frameworkFieldUsages(binding.dependencies(), frameworkFields)::get,
-                  types,
-                  metadataUtil))
-          .addStatement("return $L", instance);
-    } else {
-      getMethod.addStatement("return $L", invokeNewInstance);
-    }
-    return getMethod.build();
-  }
-
-  private static TypeName providedTypeName(ProvisionBinding binding) {
-    return TypeName.get(binding.contributedType());
-  }
-
-  private static Optional<TypeName> factoryTypeName(ProvisionBinding binding) {
-    return binding.kind() == BindingKind.ASSISTED_INJECTION
-        ? Optional.empty()
-        : Optional.of(factoryOf(providedTypeName(binding)));
-  }
-
-  private static ParameterSpec toParameter(FieldSpec field) {
-    return ParameterSpec.builder(field.type, field.name).build();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/FrameworkFieldInitializer.java b/java/dagger/internal/codegen/writing/FrameworkFieldInitializer.java
deleted file mode 100644
index c17ff8e..0000000
--- a/java/dagger/internal/codegen/writing/FrameworkFieldInitializer.java
+++ /dev/null
@@ -1,210 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.writing.ComponentImplementation.FieldSpecKind.FRAMEWORK_FIELD;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.google.auto.common.MoreTypes;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.DelegateFactory;
-import dagger.internal.codegen.binding.BindingType;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.FrameworkField;
-import dagger.internal.codegen.javapoet.AnnotationSpecs;
-import dagger.internal.codegen.javapoet.TypeNames;
-import dagger.model.BindingKind;
-import dagger.producers.internal.DelegateProducer;
-import java.util.Optional;
-
-/**
- * An object that can initialize a framework-type component field for a binding. An instance should
- * be created for each field.
- */
-class FrameworkFieldInitializer implements FrameworkInstanceSupplier {
-
-  /**
-   * An object that can determine the expression to use to assign to the component field for a
-   * binding.
-   */
-  interface FrameworkInstanceCreationExpression {
-    /** Returns the expression to use to assign to the component field for the binding. */
-    CodeBlock creationExpression();
-
-    /**
-     * Returns the framework class to use for the field, if different from the one implied by the
-     * binding. This implementation returns {@link Optional#empty()}.
-     */
-    default Optional<ClassName> alternativeFrameworkClass() {
-      return Optional.empty();
-    }
-
-    /**
-     * Returns {@code true} if instead of using {@link #creationExpression()} to create a framework
-     * instance, a case in {@link InnerSwitchingProviders} should be created for this binding.
-     */
-    // TODO(ronshapiro): perhaps this isn't the right approach. Instead of saying "Use
-    // SetFactory.EMPTY because you will only get 1 class for all types of bindings that use
-    // SetFactory", maybe we should still use an inner switching provider but the same switching
-    // provider index for all cases.
-    default boolean useInnerSwitchingProvider() {
-      return true;
-    }
-  }
-
-  private final ComponentImplementation componentImplementation;
-  private final ContributionBinding binding;
-  private final FrameworkInstanceCreationExpression frameworkInstanceCreationExpression;
-  private FieldSpec fieldSpec;
-  private InitializationState fieldInitializationState = InitializationState.UNINITIALIZED;
-
-  FrameworkFieldInitializer(
-      ComponentImplementation componentImplementation,
-      ContributionBinding binding,
-      FrameworkInstanceCreationExpression frameworkInstanceCreationExpression) {
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.binding = checkNotNull(binding);
-    this.frameworkInstanceCreationExpression = checkNotNull(frameworkInstanceCreationExpression);
-  }
-
-  /**
-   * Returns the {@link MemberSelect} for the framework field, and adds the field and its
-   * initialization code to the component if it's needed and not already added.
-   */
-  @Override
-  public final MemberSelect memberSelect() {
-    initializeField();
-    return MemberSelect.localField(componentImplementation.name(), checkNotNull(fieldSpec).name);
-  }
-
-  /** Adds the field and its initialization code to the component. */
-  private void initializeField() {
-    switch (fieldInitializationState) {
-      case UNINITIALIZED:
-        // Change our state in case we are recursively invoked via initializeBindingExpression
-        fieldInitializationState = InitializationState.INITIALIZING;
-        CodeBlock.Builder codeBuilder = CodeBlock.builder();
-        CodeBlock fieldInitialization = frameworkInstanceCreationExpression.creationExpression();
-        CodeBlock initCode = CodeBlock.of("this.$N = $L;", getOrCreateField(), fieldInitialization);
-
-        if (fieldInitializationState == InitializationState.DELEGATED) {
-          codeBuilder.add(
-              "$T.setDelegate($N, $L);", delegateType(), fieldSpec, fieldInitialization);
-        } else {
-          codeBuilder.add(initCode);
-        }
-        componentImplementation.addInitialization(codeBuilder.build());
-
-        fieldInitializationState = InitializationState.INITIALIZED;
-        break;
-
-      case INITIALIZING:
-        // We were recursively invoked, so create a delegate factory instead
-        fieldInitializationState = InitializationState.DELEGATED;
-        componentImplementation.addInitialization(
-            CodeBlock.of("this.$N = new $T<>();", getOrCreateField(), delegateType()));
-        break;
-
-      case DELEGATED:
-      case INITIALIZED:
-        break;
-    }
-  }
-
-  /**
-   * Adds a field representing the resolved bindings, optionally forcing it to use a particular
-   * binding type (instead of the type the resolved bindings would typically use).
-   */
-  private FieldSpec getOrCreateField() {
-    if (fieldSpec != null) {
-      return fieldSpec;
-    }
-    boolean useRawType = !componentImplementation.isTypeAccessible(binding.key().type());
-    FrameworkField contributionBindingField =
-        FrameworkField.forBinding(
-            binding, frameworkInstanceCreationExpression.alternativeFrameworkClass());
-
-    TypeName fieldType =
-        useRawType ? contributionBindingField.type().rawType : contributionBindingField.type();
-
-    if (binding.kind() == BindingKind.ASSISTED_INJECTION) {
-      // An assisted injection factory doesn't extend Provider, so we reference the generated
-      // factory type directly (i.e. Foo_Factory<T> instead of Provider<Foo<T>>).
-      TypeName[] typeParameters =
-          MoreTypes.asDeclared(binding.key().type()).getTypeArguments().stream()
-              .map(TypeName::get)
-              .toArray(TypeName[]::new);
-      fieldType =
-          typeParameters.length == 0
-              ? generatedClassNameForBinding(binding)
-              : ParameterizedTypeName.get(generatedClassNameForBinding(binding), typeParameters);
-    }
-
-    FieldSpec.Builder contributionField =
-        FieldSpec.builder(
-            fieldType, componentImplementation.getUniqueFieldName(contributionBindingField.name()));
-    contributionField.addModifiers(PRIVATE);
-    if (useRawType) {
-      contributionField.addAnnotation(AnnotationSpecs.suppressWarnings(RAWTYPES));
-    }
-
-    fieldSpec = contributionField.build();
-    componentImplementation.addField(FRAMEWORK_FIELD, fieldSpec);
-
-    return fieldSpec;
-  }
-
-  private Class<?> delegateType() {
-    return isProvider() ? DelegateFactory.class : DelegateProducer.class;
-  }
-
-  private boolean isProvider() {
-    return binding.bindingType().equals(BindingType.PROVISION)
-        && frameworkInstanceCreationExpression
-            .alternativeFrameworkClass()
-            .map(TypeNames.PROVIDER::equals)
-            .orElse(true);
-  }
-
-  /** Initialization state for a factory field. */
-  private enum InitializationState {
-    /** The field is {@code null}. */
-    UNINITIALIZED,
-
-    /**
-     * The field's dependencies are being set up. If the field is needed in this state, use a {@link
-     * DelegateFactory}.
-     */
-    INITIALIZING,
-
-    /**
-     * The field's dependencies are being set up, but the field can be used because it has already
-     * been set to a {@link DelegateFactory}.
-     */
-    DELEGATED,
-
-    /** The field is set to an undelegated factory. */
-    INITIALIZED;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/FrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/writing/FrameworkInstanceBindingExpression.java
deleted file mode 100644
index 56a6ef3..0000000
--- a/java/dagger/internal/codegen/writing/FrameworkInstanceBindingExpression.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/** A binding expression that uses a {@link FrameworkType} field. */
-abstract class FrameworkInstanceBindingExpression extends BindingExpression {
-  private final ContributionBinding binding;
-  private final FrameworkInstanceSupplier frameworkInstanceSupplier;
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-
-  FrameworkInstanceBindingExpression(
-      ContributionBinding binding,
-      FrameworkInstanceSupplier frameworkInstanceSupplier,
-      DaggerTypes types,
-      DaggerElements elements) {
-    this.binding = checkNotNull(binding);
-    this.frameworkInstanceSupplier = checkNotNull(frameworkInstanceSupplier);
-    this.types = checkNotNull(types);
-    this.elements = checkNotNull(elements);
-  }
-
-  /**
-   * The expression for the framework instance for this binding. The field will be {@link
-   * ComponentImplementation#addInitialization(CodeBlock) initialized} and {@link
-   * ComponentImplementation#addField(ComponentImplementation.FieldSpecKind, FieldSpec) added} to
-   * the component the first time this method is invoked.
-   */
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    MemberSelect memberSelect = frameworkInstanceSupplier.memberSelect();
-    TypeMirror expressionType =
-        isTypeAccessibleFrom(binding.contributedType(), requestingClass.packageName())
-                || isInlinedFactoryCreation(memberSelect)
-            ? types.wrapType(binding.contributedType(), frameworkType().frameworkClass())
-            : rawFrameworkType();
-    return Expression.create(expressionType, memberSelect.getExpressionFor(requestingClass));
-  }
-
-  /** Returns the framework type for the binding. */
-  protected abstract FrameworkType frameworkType();
-
-  /**
-   * Returns {@code true} if a factory is created inline each time it is requested. For example, in
-   * the initialization {@code this.fooProvider = Foo_Factory.create(Bar_Factory.create());}, {@code
-   * Bar_Factory} is considered to be inline.
-   *
-   * <p>This is used in {@link #getDependencyExpression(ClassName)} when determining the type of a
-   * factory. Normally if the {@link ContributionBinding#contributedType()} is not accessible from
-   * the component, the type of the expression will be a raw {@link javax.inject.Provider}. However,
-   * if the factory is created inline, even if contributed type is not accessible, javac will still
-   * be able to determine the type that is returned from the {@code Foo_Factory.create()} method.
-   */
-  private static boolean isInlinedFactoryCreation(MemberSelect memberSelect) {
-    return memberSelect.staticMember();
-  }
-
-  private DeclaredType rawFrameworkType() {
-    return types.getDeclaredType(elements.getTypeElement(frameworkType().frameworkClass()));
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/FrameworkInstanceSupplier.java b/java/dagger/internal/codegen/writing/FrameworkInstanceSupplier.java
deleted file mode 100644
index cc0e136..0000000
--- a/java/dagger/internal/codegen/writing/FrameworkInstanceSupplier.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-/** An object that supplies a {@link MemberSelect} for a framework instance. */
-interface FrameworkInstanceSupplier {
-  /** Returns a {@link MemberSelect}, with possible side effects on the first call. */
-  MemberSelect memberSelect();
-}
diff --git a/java/dagger/internal/codegen/writing/GwtCompatibility.java b/java/dagger/internal/codegen/writing/GwtCompatibility.java
deleted file mode 100644
index 2df6a99..0000000
--- a/java/dagger/internal/codegen/writing/GwtCompatibility.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.squareup.javapoet.AnnotationSpec;
-import dagger.internal.codegen.binding.Binding;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.Name;
-
-final class GwtCompatibility {
-
-  /**
-   * Returns a {@code @GwtIncompatible} annotation that is applied to {@code binding}'s {@link
-   * Binding#bindingElement()} or any enclosing type.
-   */
-  static Optional<AnnotationSpec> gwtIncompatibleAnnotation(Binding binding) {
-    checkArgument(binding.bindingElement().isPresent());
-    Element element = binding.bindingElement().get();
-    while (element != null) {
-      Optional<AnnotationSpec> gwtIncompatible =
-          element
-              .getAnnotationMirrors()
-              .stream()
-              .filter(annotation -> isGwtIncompatible(annotation))
-              .map(AnnotationSpec::get)
-              .findFirst();
-      if (gwtIncompatible.isPresent()) {
-        return gwtIncompatible;
-      }
-      element = element.getEnclosingElement();
-    }
-    return Optional.empty();
-  }
-
-  private static boolean isGwtIncompatible(AnnotationMirror annotation) {
-    Name simpleName = annotation.getAnnotationType().asElement().getSimpleName();
-    return simpleName.contentEquals("GwtIncompatible");
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/HjarSourceFileGenerator.java b/java/dagger/internal/codegen/writing/HjarSourceFileGenerator.java
deleted file mode 100644
index 5a4b6f1..0000000
--- a/java/dagger/internal/codegen/writing/HjarSourceFileGenerator.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import java.util.Optional;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.Modifier;
-
-/**
- * A source file generator that only writes the relevant code necessary for Bazel to create a
- * correct header (ABI) jar.
- */
-public final class HjarSourceFileGenerator<T> extends SourceFileGenerator<T> {
-  private final SourceFileGenerator<T> delegate;
-
-  private HjarSourceFileGenerator(SourceFileGenerator<T> delegate) {
-    super(delegate);
-    this.delegate = delegate;
-  }
-
-  public static <T> SourceFileGenerator<T> wrap(SourceFileGenerator<T> delegate) {
-    return new HjarSourceFileGenerator<>(delegate);
-  }
-
-  @Override
-  public ClassName nameGeneratedType(T input) {
-    return delegate.nameGeneratedType(input);
-  }
-
-  @Override
-  public Element originatingElement(T input) {
-    return delegate.originatingElement(input);
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(T input) {
-    return delegate.write(input).map(completeType -> skeletonType(completeType.build()));
-  }
-
-  private TypeSpec.Builder skeletonType(TypeSpec completeType) {
-    TypeSpec.Builder skeleton =
-        classBuilder(completeType.name)
-            .addSuperinterfaces(completeType.superinterfaces)
-            .addTypeVariables(completeType.typeVariables)
-            .addModifiers(completeType.modifiers.toArray(new Modifier[0]))
-            .addAnnotations(completeType.annotations);
-
-    if (!completeType.superclass.equals(ClassName.OBJECT)) {
-      skeleton.superclass(completeType.superclass);
-    }
-
-    completeType.methodSpecs.stream()
-        .filter(method -> !method.modifiers.contains(PRIVATE) || method.isConstructor())
-        .map(this::skeletonMethod)
-        .forEach(skeleton::addMethod);
-
-    completeType.fieldSpecs.stream()
-        .filter(field -> !field.modifiers.contains(PRIVATE))
-        .map(this::skeletonField)
-        .forEach(skeleton::addField);
-
-    completeType.typeSpecs.stream()
-        .map(type -> skeletonType(type).build())
-        .forEach(skeleton::addType);
-
-    return skeleton;
-  }
-
-  private MethodSpec skeletonMethod(MethodSpec completeMethod) {
-    MethodSpec.Builder skeleton =
-        completeMethod.isConstructor()
-            ? constructorBuilder()
-            : methodBuilder(completeMethod.name).returns(completeMethod.returnType);
-
-    if (completeMethod.isConstructor()) {
-      // Code in Turbine must (for technical reasons in javac) have a valid super() call for
-      // constructors, otherwise javac will bark, and Turbine has no way to avoid this. So we retain
-      // constructor method bodies if they do exist
-      skeleton.addCode(completeMethod.code);
-    }
-
-    return skeleton
-        .addModifiers(completeMethod.modifiers)
-        .addTypeVariables(completeMethod.typeVariables)
-        .addParameters(completeMethod.parameters)
-        .addExceptions(completeMethod.exceptions)
-        .varargs(completeMethod.varargs)
-        .addAnnotations(completeMethod.annotations)
-        .build();
-  }
-
-  private FieldSpec skeletonField(FieldSpec completeField) {
-    return FieldSpec.builder(
-            completeField.type,
-            completeField.name,
-            completeField.modifiers.toArray(new Modifier[0]))
-        .addAnnotations(completeField.annotations)
-        .build();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ImmediateFutureBindingExpression.java b/java/dagger/internal/codegen/writing/ImmediateFutureBindingExpression.java
deleted file mode 100644
index dcd02fa..0000000
--- a/java/dagger/internal/codegen/writing/ImmediateFutureBindingExpression.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-import javax.lang.model.SourceVersion;
-
-final class ImmediateFutureBindingExpression extends BindingExpression {
-  private final Key key;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final DaggerTypes types;
-  private final SourceVersion sourceVersion;
-
-  ImmediateFutureBindingExpression(
-      Key key,
-      ComponentBindingExpressions componentBindingExpressions,
-      DaggerTypes types,
-      SourceVersion sourceVersion) {
-    this.key = key;
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-    this.types = checkNotNull(types);
-    this.sourceVersion = checkNotNull(sourceVersion);
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    return Expression.create(
-        types.wrapType(key.type(), ListenableFuture.class),
-        CodeBlock.of("$T.immediateFuture($L)", Futures.class, instanceExpression(requestingClass)));
-  }
-
-  private CodeBlock instanceExpression(ClassName requestingClass) {
-    Expression expression =
-        componentBindingExpressions.getDependencyExpression(
-            bindingRequest(key, RequestKind.INSTANCE), requestingClass);
-    if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
-      // Java 7 type inference is not as strong as in Java 8, and therefore some generated code must
-      // cast.
-      //
-      // For example, javac7 cannot detect that Futures.immediateFuture(ImmutableSet.of("T"))
-      // can safely be assigned to ListenableFuture<Set<T>>.
-      if (!types.isSameType(expression.type(), key.type())) {
-        return CodeBlock.of(
-            "($T) $L", types.accessibleType(key.type(), requestingClass), expression.codeBlock());
-      }
-    }
-    return expression.codeBlock();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/InaccessibleMapKeyProxyGenerator.java b/java/dagger/internal/codegen/writing/InaccessibleMapKeyProxyGenerator.java
deleted file mode 100644
index d527359..0000000
--- a/java/dagger/internal/codegen/writing/InaccessibleMapKeyProxyGenerator.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.writing;
-
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.MapKeys;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import java.util.Optional;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-
-/**
- * Generates a class that exposes a non-{@code public} {@link
- * ContributionBinding#mapKeyAnnotation()} @MapKey} annotation.
- */
-public final class InaccessibleMapKeyProxyGenerator
-    extends SourceFileGenerator<ContributionBinding> {
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-
-  @Inject
-  InaccessibleMapKeyProxyGenerator(
-      Filer filer, DaggerTypes types, DaggerElements elements, SourceVersion sourceVersion) {
-    super(filer, elements, sourceVersion);
-    this.types = types;
-    this.elements = elements;
-  }
-
-  @Override
-  public ClassName nameGeneratedType(ContributionBinding binding) {
-    return MapKeys.mapKeyProxyClassName(binding);
-  }
-
-  @Override
-  public Element originatingElement(ContributionBinding binding) {
-    // a map key is only ever present on bindings that have a binding element
-    return binding.bindingElement().get();
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(ContributionBinding binding) {
-    return MapKeys.mapKeyFactoryMethod(binding, types, elements)
-        .map(
-            method ->
-                classBuilder(nameGeneratedType(binding))
-                    .addModifiers(PUBLIC, FINAL)
-                    .addMethod(constructorBuilder().addModifiers(PRIVATE).build())
-                    .addMethod(method));
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/InjectionMethods.java b/java/dagger/internal/codegen/writing/InjectionMethods.java
deleted file mode 100644
index 7cebc10..0000000
--- a/java/dagger/internal/codegen/writing/InjectionMethods.java
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.auto.common.MoreElements.asExecutable;
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.auto.common.MoreElements.asVariable;
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static dagger.internal.codegen.base.RequestKinds.requestTypeName;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.getNullableType;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-import static dagger.internal.codegen.binding.SourceFiles.memberInjectedFieldSignatureForVariable;
-import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.binding.SourceFiles.protectAgainstKeywords;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
-import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toConcatenatedCodeBlock;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
-import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
-import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
-import static dagger.internal.codegen.langmodel.Accessibility.isRawTypePubliclyAccessible;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static java.util.stream.Collectors.toList;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.type.TypeKind.VOID;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.internal.Preconditions;
-import dagger.internal.codegen.base.UniqueNameSet;
-import dagger.internal.codegen.binding.AssistedInjectionAnnotations;
-import dagger.internal.codegen.binding.MembersInjectionBinding.InjectionSite;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.extension.DaggerCollectors;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import dagger.internal.codegen.javapoet.TypeNames;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import dagger.model.RequestKind;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Function;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Parameterizable;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-
-/** Convenience methods for creating and invoking {@link InjectionMethod}s. */
-final class InjectionMethods {
-
-  /**
-   * A method that returns an object from a {@code @Provides} method or an {@code @Inject}ed
-   * constructor. Its parameters match the dependency requests for constructor and members
-   * injection.
-   *
-   * <p>For {@code @Provides} methods named "foo", the method name is "proxyFoo". For example:
-   *
-   * <pre><code>
-   * abstract class FooModule {
-   *   {@literal @Provides} static Foo provideFoo(Bar bar, Baz baz) { … }
-   * }
-   *
-   * public static proxyProvideFoo(Bar bar, Baz baz) { … }
-   * </code></pre>
-   *
-   * <p>For {@code @Inject}ed constructors, the method name is "newFoo". For example:
-   *
-   * <pre><code>
-   * class Foo {
-   *   {@literal @Inject} Foo(Bar bar) {}
-   * }
-   *
-   * public static Foo newFoo(Bar bar) { … }
-   * </code></pre>
-   */
-  static final class ProvisionMethod {
-    // These names are already defined in factories and shouldn't be used for the proxy method name.
-    private static final ImmutableSet<String> BANNED_PROXY_NAMES = ImmutableSet.of("get", "create");
-
-    /**
-     * Returns a method that invokes the binding's {@linkplain ProvisionBinding#bindingElement()
-     * constructor} and injects the instance's members.
-     */
-    static MethodSpec create(
-        ProvisionBinding binding,
-        CompilerOptions compilerOptions,
-        KotlinMetadataUtil metadataUtil) {
-      ExecutableElement element = asExecutable(binding.bindingElement().get());
-      switch (element.getKind()) {
-        case CONSTRUCTOR:
-          return constructorProxy(element);
-        case METHOD:
-          return methodProxy(
-              element,
-              methodName(element),
-              InstanceCastPolicy.IGNORE,
-              CheckNotNullPolicy.get(binding, compilerOptions),
-              metadataUtil);
-        default:
-          throw new AssertionError(element);
-      }
-    }
-
-    /**
-     * Invokes the injection method for {@code binding}, with the dependencies transformed with the
-     * {@code dependencyUsage} function.
-     */
-    static CodeBlock invoke(
-        ProvisionBinding binding,
-        Function<DependencyRequest, CodeBlock> dependencyUsage,
-        ClassName requestingClass,
-        Optional<CodeBlock> moduleReference,
-        CompilerOptions compilerOptions,
-        KotlinMetadataUtil metadataUtil) {
-      ImmutableList.Builder<CodeBlock> arguments = ImmutableList.builder();
-      moduleReference.ifPresent(arguments::add);
-      invokeArguments(binding, dependencyUsage, requestingClass).forEach(arguments::add);
-
-      ClassName enclosingClass = generatedClassNameForBinding(binding);
-      MethodSpec methodSpec = create(binding, compilerOptions, metadataUtil);
-      return invokeMethod(methodSpec, arguments.build(), enclosingClass, requestingClass);
-    }
-
-    static ImmutableList<CodeBlock> invokeArguments(
-        ProvisionBinding binding,
-        Function<DependencyRequest, CodeBlock> dependencyUsage,
-        ClassName requestingClass) {
-      ImmutableMap<VariableElement, DependencyRequest> dependencyRequestMap =
-          binding.provisionDependencies().stream()
-              .collect(
-                  toImmutableMap(
-                      request -> MoreElements.asVariable(request.requestElement().get()),
-                      request -> request));
-
-      ImmutableList.Builder<CodeBlock> arguments = ImmutableList.builder();
-      for (VariableElement parameter :
-          asExecutable(binding.bindingElement().get()).getParameters()) {
-        if (AssistedInjectionAnnotations.isAssistedParameter(parameter)) {
-          arguments.add(CodeBlock.of("$L", parameter.getSimpleName()));
-        } else if (dependencyRequestMap.containsKey(parameter)) {
-          DependencyRequest request = dependencyRequestMap.get(parameter);
-          arguments.add(
-              injectionMethodArgument(request, dependencyUsage.apply(request), requestingClass));
-        } else {
-          throw new AssertionError("Unexpected parameter: " + parameter);
-        }
-      }
-
-      return arguments.build();
-    }
-
-    private static MethodSpec constructorProxy(ExecutableElement constructor) {
-      TypeElement enclosingType = MoreElements.asType(constructor.getEnclosingElement());
-      MethodSpec.Builder builder =
-          methodBuilder(methodName(constructor))
-              .addModifiers(PUBLIC, STATIC)
-              .varargs(constructor.isVarArgs())
-              .returns(TypeName.get(enclosingType.asType()));
-
-      copyTypeParameters(builder, enclosingType);
-      copyThrows(builder, constructor);
-
-      CodeBlock arguments =
-          copyParameters(builder, new UniqueNameSet(), constructor.getParameters());
-      return builder.addStatement("return new $T($L)", enclosingType, arguments).build();
-    }
-
-    /**
-     * Returns {@code true} if injecting an instance of {@code binding} from {@code callingPackage}
-     * requires the use of an injection method.
-     */
-    static boolean requiresInjectionMethod(
-        ProvisionBinding binding, CompilerOptions compilerOptions, ClassName requestingClass) {
-      ExecutableElement method = MoreElements.asExecutable(binding.bindingElement().get());
-      return !binding.injectionSites().isEmpty()
-          || binding.shouldCheckForNull(compilerOptions)
-          || !isElementAccessibleFrom(method, requestingClass.packageName())
-          // This check should be removable once we drop support for -source 7
-          || method.getParameters().stream()
-              .map(VariableElement::asType)
-              .anyMatch(type -> !isRawTypeAccessible(type, requestingClass.packageName()));
-    }
-
-    /**
-     * Returns the name of the {@code static} method that wraps {@code method}. For methods that are
-     * associated with {@code @Inject} constructors, the method will also inject all {@link
-     * InjectionSite}s.
-     */
-    private static String methodName(ExecutableElement method) {
-      switch (method.getKind()) {
-        case CONSTRUCTOR:
-          return "newInstance";
-        case METHOD:
-          String methodName = method.getSimpleName().toString();
-          return BANNED_PROXY_NAMES.contains(methodName)
-              ? "proxy" + LOWER_CAMEL.to(UPPER_CAMEL, methodName)
-              : methodName;
-        default:
-          throw new AssertionError(method);
-      }
-    }
-  }
-
-  /**
-   * A static method that injects one member of an instance of a type. Its first parameter is an
-   * instance of the type to be injected. The remaining parameters match the dependency requests for
-   * the injection site.
-   *
-   * <p>Example:
-   *
-   * <pre><code>
-   * class Foo {
-   *   {@literal @Inject} Bar bar;
-   *   {@literal @Inject} void setThings(Baz baz, Qux qux) {}
-   * }
-   *
-   * public static injectBar(Foo instance, Bar bar) { … }
-   * public static injectSetThings(Foo instance, Baz baz, Qux qux) { … }
-   * </code></pre>
-   */
-  static final class InjectionSiteMethod {
-    /**
-     * When a type has an inaccessible member from a supertype (e.g. an @Inject field in a parent
-     * that's in a different package), a method in the supertype's package must be generated to give
-     * the subclass's members injector a way to inject it. Each potentially inaccessible member
-     * receives its own method, as the subclass may need to inject them in a different order from
-     * the parent class.
-     */
-    static MethodSpec create(InjectionSite injectionSite, KotlinMetadataUtil metadataUtil) {
-      String methodName = methodName(injectionSite);
-      switch (injectionSite.kind()) {
-        case METHOD:
-          return methodProxy(
-              asExecutable(injectionSite.element()),
-              methodName,
-              InstanceCastPolicy.CAST_IF_NOT_PUBLIC,
-              CheckNotNullPolicy.IGNORE,
-              metadataUtil);
-        case FIELD:
-          Optional<AnnotationMirror> qualifier =
-              injectionSite.dependencies().stream()
-                  // methods for fields have a single dependency request
-                  .collect(DaggerCollectors.onlyElement())
-                  .key()
-                  .qualifier();
-          return fieldProxy(asVariable(injectionSite.element()), methodName, qualifier);
-      }
-      throw new AssertionError(injectionSite);
-    }
-
-    /**
-     * Invokes each of the injection methods for {@code injectionSites}, with the dependencies
-     * transformed using the {@code dependencyUsage} function.
-     *
-     * @param instanceType the type of the {@code instance} parameter
-     */
-    static CodeBlock invokeAll(
-        ImmutableSet<InjectionSite> injectionSites,
-        ClassName generatedTypeName,
-        CodeBlock instanceCodeBlock,
-        TypeMirror instanceType,
-        Function<DependencyRequest, CodeBlock> dependencyUsage,
-        DaggerTypes types,
-        KotlinMetadataUtil metadataUtil) {
-      return injectionSites.stream()
-          .map(
-              injectionSite -> {
-                TypeMirror injectSiteType =
-                    types.erasure(injectionSite.element().getEnclosingElement().asType());
-
-                // If instance has been declared as Object because it is not accessible from the
-                // component, but the injectionSite is in a supertype of instanceType that is
-                // publicly accessible, the InjectionSiteMethod will request the actual type and not
-                // Object as the first parameter. If so, cast to the supertype which is accessible
-                // from within generatedTypeName
-                CodeBlock maybeCastedInstance =
-                    !types.isSubtype(instanceType, injectSiteType)
-                            && isTypeAccessibleFrom(injectSiteType, generatedTypeName.packageName())
-                        ? CodeBlock.of("($T) $L", injectSiteType, instanceCodeBlock)
-                        : instanceCodeBlock;
-                return CodeBlock.of(
-                    "$L;",
-                    invoke(
-                        injectionSite,
-                        generatedTypeName,
-                        maybeCastedInstance,
-                        dependencyUsage,
-                        metadataUtil));
-              })
-          .collect(toConcatenatedCodeBlock());
-    }
-
-    /**
-     * Invokes the injection method for {@code injectionSite}, with the dependencies transformed
-     * using the {@code dependencyUsage} function.
-     */
-    private static CodeBlock invoke(
-        InjectionSite injectionSite,
-        ClassName generatedTypeName,
-        CodeBlock instanceCodeBlock,
-        Function<DependencyRequest, CodeBlock> dependencyUsage,
-        KotlinMetadataUtil metadataUtil) {
-      ImmutableList.Builder<CodeBlock> arguments = ImmutableList.builder();
-      arguments.add(instanceCodeBlock);
-      if (!injectionSite.dependencies().isEmpty()) {
-        arguments.addAll(
-            injectionSite.dependencies().stream().map(dependencyUsage).collect(toList()));
-      }
-
-      ClassName enclosingClass =
-          membersInjectorNameForType(asType(injectionSite.element().getEnclosingElement()));
-      MethodSpec methodSpec = create(injectionSite, metadataUtil);
-      return invokeMethod(methodSpec, arguments.build(), enclosingClass, generatedTypeName);
-    }
-
-    /*
-     * TODO(ronshapiro): this isn't perfect, as collisions could still exist. Some examples:
-     *
-     *  - @Inject void members() {} will generate a method that conflicts with the instance
-     *    method `injectMembers(T)`
-     *  - Adding the index could conflict with another member:
-     *      @Inject void a(Object o) {}
-     *      @Inject void a(String s) {}
-     *      @Inject void a1(String s) {}
-     *
-     *    Here, Method a(String) will add the suffix "1", which will conflict with the method
-     *    generated for a1(String)
-     *  - Members named "members" or "methods" could also conflict with the {@code static} injection
-     *    method.
-     */
-    private static String methodName(InjectionSite injectionSite) {
-      int index = injectionSite.indexAmongAtInjectMembersWithSameSimpleName();
-      String indexString = index == 0 ? "" : String.valueOf(index + 1);
-      return "inject"
-          + LOWER_CAMEL.to(UPPER_CAMEL, injectionSite.element().getSimpleName().toString())
-          + indexString;
-    }
-  }
-
-  private static CodeBlock injectionMethodArgument(
-      DependencyRequest dependency, CodeBlock argument, ClassName generatedTypeName) {
-    TypeMirror keyType = dependency.key().type();
-    CodeBlock.Builder codeBlock = CodeBlock.builder();
-    if (!isRawTypeAccessible(keyType, generatedTypeName.packageName())
-        && isTypeAccessibleFrom(keyType, generatedTypeName.packageName())) {
-      if (!dependency.kind().equals(RequestKind.INSTANCE)) {
-        TypeName usageTypeName = accessibleType(dependency);
-        codeBlock.add("($T) ($T)", usageTypeName, rawTypeName(usageTypeName));
-      } else if (dependency.requestElement().get().asType().getKind().equals(TypeKind.TYPEVAR)) {
-        codeBlock.add("($T)", keyType);
-      }
-    }
-    return codeBlock.add(argument).build();
-  }
-
-  /**
-   * Returns the parameter type for {@code dependency}. If the raw type is not accessible, returns
-   * {@link Object}.
-   */
-  private static TypeName accessibleType(DependencyRequest dependency) {
-    TypeName typeName = requestTypeName(dependency.kind(), accessibleType(dependency.key().type()));
-    return dependency
-            .requestElement()
-            .map(element -> element.asType().getKind().isPrimitive())
-            .orElse(false)
-        ? typeName.unbox()
-        : typeName;
-  }
-
-  /**
-   * Returns the accessible type for {@code type}. If the raw type is not accessible, returns {@link
-   * Object}.
-   */
-  private static TypeName accessibleType(TypeMirror type) {
-    return isRawTypePubliclyAccessible(type) ? TypeName.get(type) : TypeName.OBJECT;
-  }
-
-  private enum InstanceCastPolicy {
-    CAST_IF_NOT_PUBLIC, IGNORE;
-
-    boolean useObjectType(TypeMirror instanceType) {
-      return this == CAST_IF_NOT_PUBLIC && !isRawTypePubliclyAccessible(instanceType);
-    }
-  }
-
-  private enum CheckNotNullPolicy {
-    IGNORE, CHECK_FOR_NULL;
-
-    CodeBlock checkForNull(CodeBlock maybeNull) {
-      return this.equals(IGNORE)
-          ? maybeNull
-          : CodeBlock.of("$T.checkNotNullFromProvides($L)", Preconditions.class, maybeNull);
-    }
-
-    static CheckNotNullPolicy get(ProvisionBinding binding, CompilerOptions compilerOptions) {
-      return binding.shouldCheckForNull(compilerOptions) ? CHECK_FOR_NULL : IGNORE;
-    }
-  }
-
-  private static MethodSpec methodProxy(
-      ExecutableElement method,
-      String methodName,
-      InstanceCastPolicy instanceCastPolicy,
-      CheckNotNullPolicy checkNotNullPolicy,
-      KotlinMetadataUtil metadataUtil) {
-    MethodSpec.Builder builder =
-        methodBuilder(methodName).addModifiers(PUBLIC, STATIC).varargs(method.isVarArgs());
-
-    TypeElement enclosingType = asType(method.getEnclosingElement());
-    boolean isMethodInKotlinObject = metadataUtil.isObjectClass(enclosingType);
-    boolean isMethodInKotlinCompanionObject = metadataUtil.isCompanionObjectClass(enclosingType);
-    UniqueNameSet parameterNameSet = new UniqueNameSet();
-    CodeBlock instance;
-    if (isMethodInKotlinCompanionObject || method.getModifiers().contains(STATIC)) {
-      instance = CodeBlock.of("$T", rawTypeName(TypeName.get(enclosingType.asType())));
-    } else if (isMethodInKotlinObject) {
-      // Call through the singleton instance.
-      // See: https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#static-methods
-      instance = CodeBlock.of("$T.INSTANCE", rawTypeName(TypeName.get(enclosingType.asType())));
-    } else {
-      copyTypeParameters(builder, enclosingType);
-      boolean useObject = instanceCastPolicy.useObjectType(enclosingType.asType());
-      instance = copyInstance(builder, parameterNameSet, enclosingType.asType(), useObject);
-    }
-    CodeBlock arguments = copyParameters(builder, parameterNameSet, method.getParameters());
-    CodeBlock invocation =
-        checkNotNullPolicy.checkForNull(
-            CodeBlock.of("$L.$L($L)", instance, method.getSimpleName(), arguments));
-
-    copyTypeParameters(builder, method);
-    copyThrows(builder, method);
-
-    if (method.getReturnType().getKind().equals(VOID)) {
-      return builder.addStatement("$L", invocation).build();
-    } else {
-      getNullableType(method)
-          .ifPresent(annotation -> CodeBlocks.addAnnotation(builder, annotation));
-      return builder
-          .returns(TypeName.get(method.getReturnType()))
-          .addStatement("return $L", invocation).build();
-    }
-  }
-
-  private static MethodSpec fieldProxy(
-      VariableElement field, String methodName, Optional<AnnotationMirror> qualifierAnnotation) {
-    MethodSpec.Builder builder =
-        methodBuilder(methodName)
-            .addModifiers(PUBLIC, STATIC)
-            .addAnnotation(
-                AnnotationSpec.builder(TypeNames.INJECTED_FIELD_SIGNATURE)
-                    .addMember("value", "$S", memberInjectedFieldSignatureForVariable(field))
-                    .build());
-
-    qualifierAnnotation.map(AnnotationSpec::get).ifPresent(builder::addAnnotation);
-
-    TypeElement enclosingType = asType(field.getEnclosingElement());
-    copyTypeParameters(builder, enclosingType);
-
-    boolean useObject = !isRawTypePubliclyAccessible(enclosingType.asType());
-    UniqueNameSet parameterNameSet = new UniqueNameSet();
-    CodeBlock instance = copyInstance(builder, parameterNameSet, enclosingType.asType(), useObject);
-    CodeBlock argument = copyParameters(builder, parameterNameSet, ImmutableList.of(field));
-    return builder.addStatement("$L.$L = $L", instance, field.getSimpleName(), argument).build();
-  }
-
-  private static CodeBlock invokeMethod(
-      MethodSpec methodSpec,
-      ImmutableList<CodeBlock> parameters,
-      ClassName enclosingClass,
-      ClassName requestingClass) {
-    checkArgument(methodSpec.parameters.size() == parameters.size());
-    CodeBlock parameterBlock = makeParametersCodeBlock(parameters);
-    return enclosingClass.equals(requestingClass)
-        ? CodeBlock.of("$L($L)", methodSpec.name, parameterBlock)
-        : CodeBlock.of("$T.$L($L)", enclosingClass, methodSpec.name, parameterBlock);
-  }
-
-  private static void copyTypeParameters(
-      MethodSpec.Builder methodBuilder, Parameterizable element) {
-    element.getTypeParameters().stream()
-        .map(TypeVariableName::get)
-        .forEach(methodBuilder::addTypeVariable);
-  }
-
-  private static void copyThrows(MethodSpec.Builder methodBuilder, ExecutableElement method) {
-    method.getThrownTypes().stream().map(TypeName::get).forEach(methodBuilder::addException);
-  }
-
-  private static CodeBlock copyParameters(
-      MethodSpec.Builder methodBuilder,
-      UniqueNameSet parameterNameSet,
-      List<? extends VariableElement> parameters) {
-    return parameters.stream()
-        .map(
-            parameter -> {
-              String name =
-                  parameterNameSet.getUniqueName(validJavaName(parameter.getSimpleName()));
-              TypeMirror type = parameter.asType();
-              boolean useObject = !isRawTypePubliclyAccessible(type);
-              return copyParameter(methodBuilder, type, name, useObject);
-            })
-        .collect(toParametersCodeBlock());
-  }
-
-  private static CodeBlock copyParameter(
-      MethodSpec.Builder methodBuilder, TypeMirror type, String name, boolean useObject) {
-    TypeName typeName = useObject ? TypeName.OBJECT : TypeName.get(type);
-    methodBuilder.addParameter(ParameterSpec.builder(typeName, name).build());
-    return useObject ? CodeBlock.of("($T) $L", type, name) : CodeBlock.of("$L", name);
-  }
-
-  private static CodeBlock copyInstance(
-      MethodSpec.Builder methodBuilder,
-      UniqueNameSet parameterNameSet,
-      TypeMirror type,
-      boolean useObject) {
-    CodeBlock instance =
-        copyParameter(methodBuilder, type, parameterNameSet.getUniqueName("instance"), useObject);
-    // If we had to cast the instance add an extra parenthesis incase we're calling a method on it.
-    return useObject ? CodeBlock.of("($L)", instance) : instance;
-  }
-
-  private static String validJavaName(CharSequence name) {
-    if (SourceVersion.isIdentifier(name)) {
-      return protectAgainstKeywords(name.toString());
-    }
-
-    StringBuilder newName = new StringBuilder(name.length());
-    char firstChar = name.charAt(0);
-    if (!Character.isJavaIdentifierStart(firstChar)) {
-      newName.append('_');
-    }
-
-    name.chars().forEach(c -> newName.append(Character.isJavaIdentifierPart(c) ? c : '_'));
-    return newName.toString();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/InjectionOrProvisionProviderCreationExpression.java b/java/dagger/internal/codegen/writing/InjectionOrProvisionProviderCreationExpression.java
deleted file mode 100644
index b5135b0..0000000
--- a/java/dagger/internal/codegen/writing/InjectionOrProvisionProviderCreationExpression.java
+++ /dev/null
@@ -1,64 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-import static dagger.model.BindingKind.INJECTION;
-
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import javax.inject.Provider;
-
-/**
- * A {@link Provider} creation expression for an {@link javax.inject.Inject @Inject}-constructed
- * class or a {@link dagger.Provides @Provides}-annotated module method.
- */
-// TODO(dpb): Resolve with ProducerCreationExpression.
-final class InjectionOrProvisionProviderCreationExpression
-    implements FrameworkInstanceCreationExpression {
-
-  private final ContributionBinding binding;
-  private final ComponentBindingExpressions componentBindingExpressions;
-
-  InjectionOrProvisionProviderCreationExpression(
-      ContributionBinding binding, ComponentBindingExpressions componentBindingExpressions) {
-    this.binding = checkNotNull(binding);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    CodeBlock createFactory =
-        CodeBlock.of(
-            "$T.create($L)",
-            generatedClassNameForBinding(binding),
-            componentBindingExpressions.getCreateMethodArgumentsCodeBlock(binding));
-
-    // When scoping a parameterized factory for an @Inject class, Java 7 cannot always infer the
-    // type properly, so cast to a raw framework type before scoping.
-    if (binding.kind().equals(INJECTION)
-        && binding.unresolved().isPresent()
-        && binding.scope().isPresent()) {
-      return CodeBlocks.cast(createFactory, Provider.class);
-    } else {
-      return createFactory;
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/InnerSwitchingProviders.java b/java/dagger/internal/codegen/writing/InnerSwitchingProviders.java
deleted file mode 100644
index c2f9893..0000000
--- a/java/dagger/internal/codegen/writing/InnerSwitchingProviders.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.writing;
-
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.model.RequestKind.INSTANCE;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-import javax.inject.Provider;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * Generates {@linkplain BindingExpression binding expressions} for a binding that is represented by
- * an inner {@code SwitchingProvider} class.
- */
-final class InnerSwitchingProviders extends SwitchingProviders {
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final DaggerTypes types;
-
-  InnerSwitchingProviders(
-      ComponentImplementation componentImplementation,
-      ComponentBindingExpressions componentBindingExpressions,
-      DaggerTypes types) {
-    super(componentImplementation, types);
-    this.componentBindingExpressions = componentBindingExpressions;
-    this.types = types;
-  }
-
-  /**
-   * Returns the binding expression for a binding that satisfies a {@link Provider} requests with a
-   * inner {@code SwitchingProvider} class.
-   */
-  BindingExpression newBindingExpression(ContributionBinding binding) {
-    return new BindingExpression() {
-      @Override
-      Expression getDependencyExpression(ClassName requestingClass) {
-        return getProviderExpression(new SwitchCase(binding, requestingClass));
-      }
-    };
-  }
-
-  @Override
-  protected TypeSpec createSwitchingProviderType(TypeSpec.Builder builder) {
-    return builder
-        .addModifiers(PRIVATE, FINAL)
-        .addField(TypeName.INT, "id", PRIVATE, FINAL)
-        .addMethod(
-            constructorBuilder()
-                .addParameter(TypeName.INT, "id")
-                .addStatement("this.id = id")
-                .build())
-        .build();
-  }
-
-  private final class SwitchCase implements SwitchingProviders.SwitchCase {
-    private final ContributionBinding binding;
-    private final ClassName requestingClass;
-
-    SwitchCase(ContributionBinding binding, ClassName requestingClass) {
-      this.binding = binding;
-      this.requestingClass = requestingClass;
-    }
-
-    @Override
-    public Key key() {
-      return binding.key();
-    }
-
-    @Override
-    public Expression getProviderExpression(ClassName switchingProviderClass, int switchId) {
-      TypeMirror instanceType = types.accessibleType(binding.contributedType(), requestingClass);
-      return Expression.create(
-          types.wrapType(instanceType, Provider.class),
-          CodeBlock.of("new $T<>($L)", switchingProviderClass, switchId));
-    }
-
-    @Override
-    public Expression getReturnExpression(ClassName switchingProviderClass) {
-      return componentBindingExpressions.getDependencyExpression(
-          bindingRequest(binding.key(), INSTANCE), switchingProviderClass);
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/InstanceFactoryCreationExpression.java b/java/dagger/internal/codegen/writing/InstanceFactoryCreationExpression.java
deleted file mode 100644
index a7d6685..0000000
--- a/java/dagger/internal/codegen/writing/InstanceFactoryCreationExpression.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.InstanceFactory;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import java.util.function.Supplier;
-
-/**
- * A {@link FrameworkInstanceCreationExpression} that creates an {@link InstanceFactory} for an
- * instance.
- */
-final class InstanceFactoryCreationExpression implements FrameworkInstanceCreationExpression {
-
-  private final boolean nullable;
-  private final Supplier<CodeBlock> instanceExpression;
-
-  InstanceFactoryCreationExpression(Supplier<CodeBlock> instanceExpression) {
-    this(false, instanceExpression);
-  }
-
-  InstanceFactoryCreationExpression(boolean nullable, Supplier<CodeBlock> instanceExpression) {
-    this.nullable = nullable;
-    this.instanceExpression = checkNotNull(instanceExpression);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    return CodeBlock.of(
-        "$T.$L($L)",
-        InstanceFactory.class,
-        nullable ? "createNullable" : "create",
-        instanceExpression.get());
-  }
-
-  @Override
-  public boolean useInnerSwitchingProvider() {
-    return false;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/MapBindingExpression.java b/java/dagger/internal/codegen/writing/MapBindingExpression.java
deleted file mode 100644
index 255e85d..0000000
--- a/java/dagger/internal/codegen/writing/MapBindingExpression.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.binding.MapKeys.getMapKeyExpression;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static dagger.model.BindingKind.MULTIBOUND_MAP;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.MapBuilder;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingKind;
-import dagger.model.DependencyRequest;
-import java.util.Collections;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/** A {@link BindingExpression} for multibound maps. */
-final class MapBindingExpression extends SimpleInvocationBindingExpression {
-  /** Maximum number of key-value pairs that can be passed to ImmutableMap.of(K, V, K, V, ...). */
-  private static final int MAX_IMMUTABLE_MAP_OF_KEY_VALUE_PAIRS = 5;
-
-  private final ProvisionBinding binding;
-  private final ImmutableMap<DependencyRequest, ContributionBinding> dependencies;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-
-  MapBindingExpression(
-      ProvisionBinding binding,
-      BindingGraph graph,
-      ComponentBindingExpressions componentBindingExpressions,
-      DaggerTypes types,
-      DaggerElements elements) {
-    super(binding);
-    this.binding = binding;
-    BindingKind bindingKind = this.binding.kind();
-    checkArgument(bindingKind.equals(MULTIBOUND_MAP), bindingKind);
-    this.componentBindingExpressions = componentBindingExpressions;
-    this.types = types;
-    this.elements = elements;
-    this.dependencies =
-        Maps.toMap(binding.dependencies(), dep -> graph.contributionBinding(dep.key()));
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    // TODO(ronshapiro): We should also make an ImmutableMap version of MapFactory
-    boolean isImmutableMapAvailable = isImmutableMapAvailable();
-    // TODO(ronshapiro, gak): Use Maps.immutableEnumMap() if it's available?
-    if (isImmutableMapAvailable && dependencies.size() <= MAX_IMMUTABLE_MAP_OF_KEY_VALUE_PAIRS) {
-      return Expression.create(
-          immutableMapType(),
-          CodeBlock.builder()
-              .add("$T.", ImmutableMap.class)
-              .add(maybeTypeParameters(requestingClass))
-              .add(
-                  "of($L)",
-                  dependencies
-                      .keySet()
-                      .stream()
-                      .map(dependency -> keyAndValueExpression(dependency, requestingClass))
-                      .collect(toParametersCodeBlock()))
-              .build());
-    }
-    switch (dependencies.size()) {
-      case 0:
-        return collectionsStaticFactoryInvocation(requestingClass, CodeBlock.of("emptyMap()"));
-      case 1:
-        return collectionsStaticFactoryInvocation(
-            requestingClass,
-            CodeBlock.of(
-                "singletonMap($L)",
-                keyAndValueExpression(getOnlyElement(dependencies.keySet()), requestingClass)));
-      default:
-        CodeBlock.Builder instantiation = CodeBlock.builder();
-        instantiation
-            .add("$T.", isImmutableMapAvailable ? ImmutableMap.class : MapBuilder.class)
-            .add(maybeTypeParameters(requestingClass));
-        if (isImmutableMapBuilderWithExpectedSizeAvailable()) {
-          instantiation.add("builderWithExpectedSize($L)", dependencies.size());
-        } else if (isImmutableMapAvailable) {
-          instantiation.add("builder()");
-        } else {
-          instantiation.add("newMapBuilder($L)", dependencies.size());
-        }
-        for (DependencyRequest dependency : dependencies.keySet()) {
-          instantiation.add(".put($L)", keyAndValueExpression(dependency, requestingClass));
-        }
-        return Expression.create(
-            isImmutableMapAvailable ? immutableMapType() : binding.key().type(),
-            instantiation.add(".build()").build());
-    }
-  }
-
-  private DeclaredType immutableMapType() {
-    MapType mapType = MapType.from(binding.key());
-    return types.getDeclaredType(
-        elements.getTypeElement(ImmutableMap.class), mapType.keyType(), mapType.valueType());
-  }
-
-  private CodeBlock keyAndValueExpression(DependencyRequest dependency, ClassName requestingClass) {
-    return CodeBlock.of(
-        "$L, $L",
-        getMapKeyExpression(dependencies.get(dependency), requestingClass, elements),
-        componentBindingExpressions
-            .getDependencyExpression(bindingRequest(dependency), requestingClass)
-            .codeBlock());
-  }
-
-  private Expression collectionsStaticFactoryInvocation(
-      ClassName requestingClass, CodeBlock methodInvocation) {
-    return Expression.create(
-        binding.key().type(),
-        CodeBlock.builder()
-            .add("$T.", Collections.class)
-            .add(maybeTypeParameters(requestingClass))
-            .add(methodInvocation)
-            .build());
-  }
-
-  private CodeBlock maybeTypeParameters(ClassName requestingClass) {
-    TypeMirror bindingKeyType = binding.key().type();
-    MapType mapType = MapType.from(binding.key());
-    return isTypeAccessibleFrom(bindingKeyType, requestingClass.packageName())
-        ? CodeBlock.of("<$T, $T>", mapType.keyType(), mapType.valueType())
-        : CodeBlock.of("");
-  }
-
-  private boolean isImmutableMapBuilderWithExpectedSizeAvailable() {
-    if (isImmutableMapAvailable()) {
-      return methodsIn(elements.getTypeElement(ImmutableMap.class).getEnclosedElements())
-          .stream()
-          .anyMatch(method -> method.getSimpleName().contentEquals("builderWithExpectedSize"));
-    }
-    return false;
-  }
-
-  private boolean isImmutableMapAvailable() {
-    return elements.getTypeElement(ImmutableMap.class) != null;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java b/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java
deleted file mode 100644
index 104d48a..0000000
--- a/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java
+++ /dev/null
@@ -1,87 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.MapKeys.getMapKeyExpression;
-import static dagger.internal.codegen.binding.SourceFiles.mapFactoryClassName;
-
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.base.MapType;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.model.DependencyRequest;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import javax.inject.Provider;
-import javax.lang.model.type.TypeMirror;
-
-/** A factory creation expression for a multibound map. */
-final class MapFactoryCreationExpression extends MultibindingFactoryCreationExpression {
-
-  private final ComponentImplementation componentImplementation;
-  private final BindingGraph graph;
-  private final ContributionBinding binding;
-  private final DaggerElements elements;
-
-  MapFactoryCreationExpression(
-      ContributionBinding binding,
-      ComponentImplementation componentImplementation,
-      ComponentBindingExpressions componentBindingExpressions,
-      BindingGraph graph,
-      DaggerElements elements) {
-    super(binding, componentImplementation, componentBindingExpressions);
-    this.binding = checkNotNull(binding);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.graph = checkNotNull(graph);
-    this.elements = checkNotNull(elements);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", mapFactoryClassName(binding));
-    if (!useRawType()) {
-      MapType mapType = MapType.from(binding.key().type());
-      // TODO(ronshapiro): either inline this into mapFactoryClassName, or add a
-      // mapType.unwrappedValueType() method that doesn't require a framework type
-      TypeMirror valueType = mapType.valueType();
-      for (Class<?> frameworkClass :
-          ImmutableSet.of(Provider.class, Producer.class, Produced.class)) {
-        if (mapType.valuesAreTypeOf(frameworkClass)) {
-          valueType = mapType.unwrappedValueType(frameworkClass);
-          break;
-        }
-      }
-      builder.add("<$T, $T>", mapType.keyType(), valueType);
-    }
-
-    builder.add("builder($L)", binding.dependencies().size());
-
-    for (DependencyRequest dependency : binding.dependencies()) {
-      ContributionBinding contributionBinding = graph.contributionBinding(dependency.key());
-      builder.add(
-          ".put($L, $L)",
-          getMapKeyExpression(contributionBinding, componentImplementation.name(), elements),
-          multibindingDependencyExpression(dependency));
-    }
-    builder.add(".build()");
-
-    return builder.build();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/MemberSelect.java b/java/dagger/internal/codegen/writing/MemberSelect.java
deleted file mode 100644
index b04e21b..0000000
--- a/java/dagger/internal/codegen/writing/MemberSelect.java
+++ /dev/null
@@ -1,263 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
-import static dagger.internal.codegen.binding.SourceFiles.bindingTypeElementTypeVariableNames;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-import static dagger.internal.codegen.binding.SourceFiles.setFactoryClassName;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeNames.FACTORY;
-import static dagger.internal.codegen.javapoet.TypeNames.MAP_FACTORY;
-import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER;
-import static dagger.internal.codegen.javapoet.TypeNames.PRODUCERS;
-import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static javax.lang.model.type.TypeKind.DECLARED;
-
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.binding.BindingType;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import java.util.List;
-import java.util.Optional;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * Represents a {@link com.sun.source.tree.MemberSelectTree} as a {@link CodeBlock}.
- */
-abstract class MemberSelect {
-
-  /**
-   * Returns a {@link MemberSelect} that accesses the field given by {@code fieldName} owned by
-   * {@code owningClass}.  In this context "local" refers to the fact that the field is owned by the
-   * type (or an enclosing type) from which the code block will be used.  The returned
-   * {@link MemberSelect} will not be valid for accessing the field from a different class
-   * (regardless of accessibility).
-   */
-  static MemberSelect localField(ClassName owningClass, String fieldName) {
-    return new LocalField(owningClass, fieldName);
-  }
-
-  private static final class LocalField extends MemberSelect {
-    final String fieldName;
-
-    LocalField(ClassName owningClass, String fieldName) {
-      super(owningClass, false);
-      this.fieldName = checkNotNull(fieldName);
-    }
-
-    @Override
-    CodeBlock getExpressionFor(ClassName usingClass) {
-      return owningClass().equals(usingClass)
-          ? CodeBlock.of("$N", fieldName)
-          : CodeBlock.of("$T.this.$N", owningClass(), fieldName);
-    }
-  }
-
-  /**
-   * Returns a {@link MemberSelect} that accesses the method given by {@code methodName} owned by
-   * {@code owningClass}. In this context "local" refers to the fact that the method is owned by the
-   * type (or an enclosing type) from which the code block will be used. The returned {@link
-   * MemberSelect} will not be valid for accessing the method from a different class (regardless of
-   * accessibility).
-   */
-  static MemberSelect localMethod(ClassName owningClass, String methodName) {
-    return new LocalMethod(owningClass, methodName);
-  }
-
-  private static final class LocalMethod extends MemberSelect {
-    final String methodName;
-
-    LocalMethod(ClassName owningClass, String methodName) {
-      super(owningClass, false);
-      this.methodName = checkNotNull(methodName);
-    }
-
-    @Override
-    CodeBlock getExpressionFor(ClassName usingClass) {
-      return owningClass().equals(usingClass)
-          ? CodeBlock.of("$N()", methodName)
-          : CodeBlock.of("$T.this.$N()", owningClass(), methodName);
-    }
-  }
-
-  /**
-   * If {@code resolvedBindings} is an unscoped provision binding with no factory arguments or a
-   * no-op members injection binding, then we don't need a field to hold its factory. In that case,
-   * this method returns the static member select that returns the factory or no-op members
-   * injector.
-   */
-  static Optional<MemberSelect> staticFactoryCreation(ContributionBinding contributionBinding) {
-    if (contributionBinding.factoryCreationStrategy().equals(SINGLETON_INSTANCE)
-        && !contributionBinding.scope().isPresent()) {
-      switch (contributionBinding.kind()) {
-        case MULTIBOUND_MAP:
-          return Optional.of(emptyMapFactory(contributionBinding));
-
-        case MULTIBOUND_SET:
-          return Optional.of(emptySetFactory(contributionBinding));
-
-        case INJECTION:
-        case PROVISION:
-          TypeMirror keyType = contributionBinding.key().type();
-          if (keyType.getKind().equals(DECLARED)) {
-            ImmutableList<TypeVariableName> typeVariables =
-                bindingTypeElementTypeVariableNames(contributionBinding);
-            if (!typeVariables.isEmpty()) {
-              List<? extends TypeMirror> typeArguments =
-                  ((DeclaredType) keyType).getTypeArguments();
-              return Optional.of(
-                  MemberSelect.parameterizedFactoryCreateMethod(
-                      generatedClassNameForBinding(contributionBinding), typeArguments));
-            }
-          }
-          // fall through
-
-        default:
-          return Optional.of(
-              new StaticMethod(
-                  generatedClassNameForBinding(contributionBinding), CodeBlock.of("create()")));
-      }
-    }
-
-    return Optional.empty();
-  }
-
-  /**
-   * Returns a {@link MemberSelect} for the instance of a {@code create()} method on a factory. This
-   * only applies for factories that do not have any dependencies.
-   */
-  private static MemberSelect parameterizedFactoryCreateMethod(
-      ClassName owningClass, List<? extends TypeMirror> parameters) {
-    return new ParameterizedStaticMethod(
-        owningClass, ImmutableList.copyOf(parameters), CodeBlock.of("create()"), FACTORY);
-  }
-
-  private static final class StaticMethod extends MemberSelect {
-    final CodeBlock methodCodeBlock;
-
-    StaticMethod(ClassName owningClass, CodeBlock methodCodeBlock) {
-      super(owningClass, true);
-      this.methodCodeBlock = checkNotNull(methodCodeBlock);
-    }
-
-    @Override
-    CodeBlock getExpressionFor(ClassName usingClass) {
-      return owningClass().equals(usingClass)
-          ? methodCodeBlock
-          : CodeBlock.of("$T.$L", owningClass(), methodCodeBlock);
-    }
-  }
-
-  /** A {@link MemberSelect} for a factory of an empty map. */
-  private static MemberSelect emptyMapFactory(ContributionBinding contributionBinding) {
-    BindingType bindingType = contributionBinding.bindingType();
-    ImmutableList<TypeMirror> typeParameters =
-        ImmutableList.copyOf(
-            MoreTypes.asDeclared(contributionBinding.key().type()).getTypeArguments());
-    if (bindingType.equals(BindingType.PRODUCTION)) {
-      return new ParameterizedStaticMethod(
-          PRODUCERS, typeParameters, CodeBlock.of("emptyMapProducer()"), PRODUCER);
-    } else {
-      return new ParameterizedStaticMethod(
-          MAP_FACTORY, typeParameters, CodeBlock.of("emptyMapProvider()"), PROVIDER);
-    }
-  }
-
-  /**
-   * A static member select for an empty set factory. Calls {@link
-   * dagger.internal.SetFactory#empty()}, {@link dagger.producers.internal.SetProducer#empty()}, or
-   * {@link dagger.producers.internal.SetOfProducedProducer#empty()}, depending on the set bindings.
-   */
-  private static MemberSelect emptySetFactory(ContributionBinding binding) {
-    return new ParameterizedStaticMethod(
-        setFactoryClassName(binding),
-        ImmutableList.of(SetType.from(binding.key()).elementType()),
-        CodeBlock.of("empty()"),
-        FACTORY);
-  }
-
-  private static final class ParameterizedStaticMethod extends MemberSelect {
-    final ImmutableList<TypeMirror> typeParameters;
-    final CodeBlock methodCodeBlock;
-    final ClassName rawReturnType;
-
-    ParameterizedStaticMethod(
-        ClassName owningClass,
-        ImmutableList<TypeMirror> typeParameters,
-        CodeBlock methodCodeBlock,
-        ClassName rawReturnType) {
-      super(owningClass, true);
-      this.typeParameters = typeParameters;
-      this.methodCodeBlock = methodCodeBlock;
-      this.rawReturnType = rawReturnType;
-    }
-
-    @Override
-    CodeBlock getExpressionFor(ClassName usingClass) {
-      boolean accessible = true;
-      for (TypeMirror typeParameter : typeParameters) {
-        accessible &= isTypeAccessibleFrom(typeParameter, usingClass.packageName());
-      }
-
-      if (accessible) {
-        return CodeBlock.of(
-            "$T.<$L>$L",
-            owningClass(),
-            typeParameters.stream().map(CodeBlocks::type).collect(toParametersCodeBlock()),
-            methodCodeBlock);
-      } else {
-        return CodeBlock.of("(($T) $T.$L)", rawReturnType, owningClass(), methodCodeBlock);
-      }
-    }
-  }
-
-  private final ClassName owningClass;
-  private final boolean staticMember;
-
-  MemberSelect(ClassName owningClass, boolean staticMemeber) {
-    this.owningClass = owningClass;
-    this.staticMember = staticMemeber;
-  }
-
-  /** Returns the class that owns the member being selected. */
-  ClassName owningClass() {
-    return owningClass;
-  }
-
-  /**
-   * Returns true if the member being selected is static and does not require an instance of
-   * {@link #owningClass()}.
-   */
-  boolean staticMember() {
-    return staticMember;
-  }
-
-  /**
-   * Returns a {@link CodeBlock} suitable for accessing the member from the given {@code
-   * usingClass}.
-   */
-  abstract CodeBlock getExpressionFor(ClassName usingClass);
-}
diff --git a/java/dagger/internal/codegen/writing/MembersInjectionBindingExpression.java b/java/dagger/internal/codegen/writing/MembersInjectionBindingExpression.java
deleted file mode 100644
index abf9d03..0000000
--- a/java/dagger/internal/codegen/writing/MembersInjectionBindingExpression.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static javax.lang.model.type.TypeKind.VOID;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.ParameterSpec;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.binding.MembersInjectionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import javax.lang.model.element.ExecutableElement;
-
-/**
- * A binding expression for members injection component methods. See {@link
- * MembersInjectionMethods}.
- */
-final class MembersInjectionBindingExpression extends BindingExpression {
-  private final MembersInjectionBinding binding;
-  private final MembersInjectionMethods membersInjectionMethods;
-
-  MembersInjectionBindingExpression(
-      MembersInjectionBinding binding, MembersInjectionMethods membersInjectionMethods) {
-    this.binding = binding;
-    this.membersInjectionMethods = membersInjectionMethods;
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    throw new UnsupportedOperationException(binding.toString());
-  }
-
-  // TODO(ronshapiro): This class doesn't need to be a BindingExpression, as
-  // getDependencyExpression() should never be called for members injection methods. It's probably
-  // better suited as a method on MembersInjectionMethods
-  @Override
-  protected CodeBlock getComponentMethodImplementation(
-      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
-    ExecutableElement methodElement = componentMethod.methodElement();
-    ParameterSpec parameter = ParameterSpec.get(getOnlyElement(methodElement.getParameters()));
-
-    if (binding.injectionSites().isEmpty()) {
-      return methodElement.getReturnType().getKind().equals(VOID)
-          ? CodeBlock.of("")
-          : CodeBlock.of("return $N;", parameter);
-    } else {
-      return methodElement.getReturnType().getKind().equals(VOID)
-          ? CodeBlock.of("$L;", membersInjectionInvocation(parameter))
-          : CodeBlock.of("return $L;", membersInjectionInvocation(parameter));
-    }
-  }
-
-  CodeBlock membersInjectionInvocation(ParameterSpec target) {
-    return CodeBlock.of("$N($N)", membersInjectionMethods.getOrCreate(binding.key()), target);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/MembersInjectionMethods.java b/java/dagger/internal/codegen/writing/MembersInjectionMethods.java
deleted file mode 100644
index 3d602b3..0000000
--- a/java/dagger/internal/codegen/writing/MembersInjectionMethods.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.MEMBERS_INJECTION_METHOD;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.codegen.binding.Binding;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.MembersInjectionBinding;
-import dagger.internal.codegen.binding.MembersInjectionBinding.InjectionSite;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.writing.InjectionMethods.InjectionSiteMethod;
-import dagger.model.Key;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-/** Manages the member injection methods for a component. */
-final class MembersInjectionMethods {
-  private final Map<Key, MethodSpec> membersInjectionMethods = new LinkedHashMap<>();
-  private final ComponentImplementation componentImplementation;
-  private final ComponentBindingExpressions bindingExpressions;
-  private final BindingGraph graph;
-  private final DaggerElements elements;
-  private final DaggerTypes types;
-  private final KotlinMetadataUtil metadataUtil;
-
-  MembersInjectionMethods(
-      ComponentImplementation componentImplementation,
-      ComponentBindingExpressions bindingExpressions,
-      BindingGraph graph,
-      DaggerElements elements,
-      DaggerTypes types,
-      KotlinMetadataUtil metadataUtil) {
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.bindingExpressions = checkNotNull(bindingExpressions);
-    this.graph = checkNotNull(graph);
-    this.elements = checkNotNull(elements);
-    this.types = checkNotNull(types);
-    this.metadataUtil = metadataUtil;
-  }
-
-  /**
-   * Returns the members injection {@link MethodSpec} for the given {@link Key}, creating it if
-   * necessary.
-   */
-  MethodSpec getOrCreate(Key key) {
-    return reentrantComputeIfAbsent(membersInjectionMethods, key, this::membersInjectionMethod);
-  }
-
-  private MethodSpec membersInjectionMethod(Key key) {
-    Binding binding =
-        graph.membersInjectionBinding(key).isPresent()
-            ? graph.membersInjectionBinding(key).get()
-            : graph.contributionBinding(key);
-    TypeMirror keyType = binding.key().type();
-    TypeMirror membersInjectedType =
-        isTypeAccessibleFrom(keyType, componentImplementation.name().packageName())
-            ? keyType
-            : elements.getTypeElement(Object.class).asType();
-    TypeName membersInjectedTypeName = TypeName.get(membersInjectedType);
-    Name bindingTypeName = binding.bindingTypeElement().get().getSimpleName();
-    // TODO(ronshapiro): include type parameters in this name e.g. injectFooOfT, and outer class
-    // simple names Foo.Builder -> injectFooBuilder
-    String methodName = componentImplementation.getUniqueMethodName("inject" + bindingTypeName);
-    ParameterSpec parameter = ParameterSpec.builder(membersInjectedTypeName, "instance").build();
-    MethodSpec.Builder methodBuilder =
-        methodBuilder(methodName)
-            .addModifiers(PRIVATE)
-            .returns(membersInjectedTypeName)
-            .addParameter(parameter);
-    TypeElement canIgnoreReturnValue =
-        elements.getTypeElement("com.google.errorprone.annotations.CanIgnoreReturnValue");
-    if (canIgnoreReturnValue != null) {
-      methodBuilder.addAnnotation(ClassName.get(canIgnoreReturnValue));
-    }
-    CodeBlock instance = CodeBlock.of("$N", parameter);
-    methodBuilder.addCode(
-        InjectionSiteMethod.invokeAll(
-            injectionSites(binding),
-            componentImplementation.name(),
-            instance,
-            membersInjectedType,
-            request ->
-                bindingExpressions
-                    .getDependencyArgumentExpression(request, componentImplementation.name())
-                    .codeBlock(),
-            types,
-            metadataUtil));
-    methodBuilder.addStatement("return $L", instance);
-
-    MethodSpec method = methodBuilder.build();
-    componentImplementation.addMethod(MEMBERS_INJECTION_METHOD, method);
-    return method;
-  }
-
-  private static ImmutableSet<InjectionSite> injectionSites(Binding binding) {
-    if (binding instanceof ProvisionBinding) {
-      return ((ProvisionBinding) binding).injectionSites();
-    } else if (binding instanceof MembersInjectionBinding) {
-      return ((MembersInjectionBinding) binding).injectionSites();
-    }
-    throw new IllegalArgumentException(binding.key().toString());
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/MembersInjectorGenerator.java b/java/dagger/internal/codegen/writing/MembersInjectorGenerator.java
deleted file mode 100644
index df618b0..0000000
--- a/java/dagger/internal/codegen/writing/MembersInjectorGenerator.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2014 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.writing;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedInjectedConstructors;
-import static dagger.internal.codegen.binding.InjectionAnnotations.injectedConstructors;
-import static dagger.internal.codegen.binding.SourceFiles.bindingTypeElementTypeVariableNames;
-import static dagger.internal.codegen.binding.SourceFiles.frameworkFieldUsages;
-import static dagger.internal.codegen.binding.SourceFiles.generateBindingFieldsForDependencies;
-import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.binding.SourceFiles.parameterizedGeneratedTypeNameForBinding;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeNames.membersInjectorOf;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.writing.GwtCompatibility.gwtIncompatibleAnnotation;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.MembersInjector;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.base.UniqueNameSet;
-import dagger.internal.codegen.binding.FrameworkField;
-import dagger.internal.codegen.binding.MembersInjectionBinding;
-import dagger.internal.codegen.binding.MembersInjectionBinding.InjectionSite;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.internal.codegen.writing.InjectionMethods.InjectionSiteMethod;
-import dagger.model.DependencyRequest;
-import java.util.Map.Entry;
-import java.util.Optional;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-
-/**
- * Generates {@link MembersInjector} implementations from {@link MembersInjectionBinding} instances.
- */
-public final class MembersInjectorGenerator extends SourceFileGenerator<MembersInjectionBinding> {
-  private final DaggerTypes types;
-  private final KotlinMetadataUtil metadataUtil;
-
-  @Inject
-  MembersInjectorGenerator(
-      Filer filer,
-      DaggerElements elements,
-      DaggerTypes types,
-      SourceVersion sourceVersion,
-      KotlinMetadataUtil metadataUtil) {
-    super(filer, elements, sourceVersion);
-    this.types = types;
-    this.metadataUtil = metadataUtil;
-  }
-
-  @Override
-  public ClassName nameGeneratedType(MembersInjectionBinding binding) {
-    return membersInjectorNameForType(binding.membersInjectedType());
-  }
-
-  @Override
-  public Element originatingElement(MembersInjectionBinding binding) {
-    return binding.membersInjectedType();
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(MembersInjectionBinding binding) {
-    // Empty members injection bindings are special and don't need source files.
-    if (binding.injectionSites().isEmpty()) {
-      return Optional.empty();
-    }
-
-    // Members injectors for classes with no local injection sites and no @Inject
-    // constructor are unused.
-    if (!binding.hasLocalInjectionSites()
-        && injectedConstructors(binding.membersInjectedType()).isEmpty()
-        && assistedInjectedConstructors(binding.membersInjectedType()).isEmpty()) {
-      return Optional.empty();
-    }
-
-
-    // We don't want to write out resolved bindings -- we want to write out the generic version.
-    checkState(
-        !binding.unresolved().isPresent(),
-        "tried to generate a MembersInjector for a binding of a resolved generic type: %s",
-        binding);
-
-    ClassName generatedTypeName = nameGeneratedType(binding);
-    ImmutableList<TypeVariableName> typeParameters = bindingTypeElementTypeVariableNames(binding);
-    TypeSpec.Builder injectorTypeBuilder =
-        classBuilder(generatedTypeName)
-            .addModifiers(PUBLIC, FINAL)
-            .addTypeVariables(typeParameters);
-
-    TypeName injectedTypeName = TypeName.get(binding.key().type());
-    TypeName implementedType = membersInjectorOf(injectedTypeName);
-    injectorTypeBuilder.addSuperinterface(implementedType);
-
-    MethodSpec.Builder injectMembersBuilder =
-        methodBuilder("injectMembers")
-            .addModifiers(PUBLIC)
-            .addAnnotation(Override.class)
-            .addParameter(injectedTypeName, "instance");
-
-    ImmutableMap<DependencyRequest, FrameworkField> fields =
-        generateBindingFieldsForDependencies(binding);
-
-    ImmutableMap.Builder<DependencyRequest, FieldSpec> dependencyFieldsBuilder =
-        ImmutableMap.builder();
-
-    MethodSpec.Builder constructorBuilder = constructorBuilder().addModifiers(PUBLIC);
-
-    // We use a static create method so that generated components can avoid having
-    // to refer to the generic types of the factory.
-    // (Otherwise they may have visibility problems referring to the types.)
-    MethodSpec.Builder createMethodBuilder =
-        methodBuilder("create")
-            .returns(implementedType)
-            .addModifiers(PUBLIC, STATIC)
-            .addTypeVariables(typeParameters);
-
-    createMethodBuilder.addCode(
-        "return new $T(", parameterizedGeneratedTypeNameForBinding(binding));
-    ImmutableList.Builder<CodeBlock> constructorInvocationParameters = ImmutableList.builder();
-
-    boolean usesRawFrameworkTypes = false;
-    UniqueNameSet fieldNames = new UniqueNameSet();
-    for (Entry<DependencyRequest, FrameworkField> fieldEntry : fields.entrySet()) {
-      DependencyRequest dependency = fieldEntry.getKey();
-      FrameworkField bindingField = fieldEntry.getValue();
-
-      // If the dependency type is not visible to this members injector, then use the raw framework
-      // type for the field.
-      boolean useRawFrameworkType =
-          !isTypeAccessibleFrom(dependency.key().type(), generatedTypeName.packageName());
-
-      String fieldName = fieldNames.getUniqueName(bindingField.name());
-      TypeName fieldType = useRawFrameworkType ? bindingField.type().rawType : bindingField.type();
-      FieldSpec.Builder fieldBuilder = FieldSpec.builder(fieldType, fieldName, PRIVATE, FINAL);
-      ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(fieldType, fieldName);
-
-      // If we're using the raw type for the field, then suppress the injectMembers method's
-      // unchecked-type warning and the field's and the constructor and create-method's
-      // parameters' raw-type warnings.
-      if (useRawFrameworkType) {
-        usesRawFrameworkTypes = true;
-        fieldBuilder.addAnnotation(suppressWarnings(RAWTYPES));
-        parameterBuilder.addAnnotation(suppressWarnings(RAWTYPES));
-      }
-      constructorBuilder.addParameter(parameterBuilder.build());
-      createMethodBuilder.addParameter(parameterBuilder.build());
-
-      FieldSpec field = fieldBuilder.build();
-      injectorTypeBuilder.addField(field);
-      constructorBuilder.addStatement("this.$1N = $1N", field);
-      dependencyFieldsBuilder.put(dependency, field);
-      constructorInvocationParameters.add(CodeBlock.of("$N", field));
-    }
-
-    createMethodBuilder.addCode(
-        constructorInvocationParameters.build().stream().collect(toParametersCodeBlock()));
-    createMethodBuilder.addCode(");");
-
-    injectorTypeBuilder.addMethod(constructorBuilder.build());
-    injectorTypeBuilder.addMethod(createMethodBuilder.build());
-
-    ImmutableMap<DependencyRequest, FieldSpec> dependencyFields = dependencyFieldsBuilder.build();
-
-    injectMembersBuilder.addCode(
-        InjectionSiteMethod.invokeAll(
-            binding.injectionSites(),
-            generatedTypeName,
-            CodeBlock.of("instance"),
-            binding.key().type(),
-            frameworkFieldUsages(binding.dependencies(), dependencyFields)::get,
-            types,
-            metadataUtil));
-
-    if (usesRawFrameworkTypes) {
-      injectMembersBuilder.addAnnotation(suppressWarnings(UNCHECKED));
-    }
-    injectorTypeBuilder.addMethod(injectMembersBuilder.build());
-
-    for (InjectionSite injectionSite : binding.injectionSites()) {
-      if (injectionSite.element().getEnclosingElement().equals(binding.membersInjectedType())) {
-        injectorTypeBuilder.addMethod(InjectionSiteMethod.create(injectionSite, metadataUtil));
-      }
-    }
-
-    gwtIncompatibleAnnotation(binding).ifPresent(injectorTypeBuilder::addAnnotation);
-
-    return Optional.of(injectorTypeBuilder);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/MembersInjectorProviderCreationExpression.java b/java/dagger/internal/codegen/writing/MembersInjectorProviderCreationExpression.java
deleted file mode 100644
index 534c057..0000000
--- a/java/dagger/internal/codegen/writing/MembersInjectorProviderCreationExpression.java
+++ /dev/null
@@ -1,93 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.javapoet.TypeNames.INSTANCE_FACTORY;
-import static dagger.internal.codegen.javapoet.TypeNames.MEMBERS_INJECTORS;
-
-import com.google.auto.common.MoreTypes;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-/** A {@code Provider<MembersInjector<Foo>>} creation expression. */
-final class MembersInjectorProviderCreationExpression
-    implements FrameworkInstanceCreationExpression {
-
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final ProvisionBinding binding;
-
-  MembersInjectorProviderCreationExpression(
-      ProvisionBinding binding, ComponentBindingExpressions componentBindingExpressions) {
-    this.binding = checkNotNull(binding);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    TypeMirror membersInjectedType =
-        getOnlyElement(MoreTypes.asDeclared(binding.key().type()).getTypeArguments());
-
-    boolean castThroughRawType = false;
-    CodeBlock membersInjector;
-    if (binding.injectionSites().isEmpty()) {
-      membersInjector = CodeBlock.of("$T.<$T>noOp()", MEMBERS_INJECTORS, membersInjectedType);
-    } else {
-      TypeElement injectedTypeElement = MoreTypes.asTypeElement(membersInjectedType);
-      while (!hasLocalInjectionSites(injectedTypeElement)) {
-        // Cast through a raw type since we're going to be using the MembersInjector for the
-        // parent type.
-        castThroughRawType = true;
-        injectedTypeElement = MoreTypes.asTypeElement(injectedTypeElement.getSuperclass());
-      }
-
-      membersInjector = CodeBlock.of(
-          "$T.create($L)",
-          membersInjectorNameForType(injectedTypeElement),
-          componentBindingExpressions.getCreateMethodArgumentsCodeBlock(binding));
-    }
-
-    // TODO(ronshapiro): consider adding a MembersInjectorBindingExpression to return this directly
-    // (as it's rarely requested as a Provider).
-    CodeBlock providerExpression = CodeBlock.of("$T.create($L)", INSTANCE_FACTORY, membersInjector);
-    // If needed we cast through raw type around the InstanceFactory type as opposed to the
-    // MembersInjector since we end up with an InstanceFactory<MembersInjector> as opposed to a
-    // InstanceFactory<MembersInjector<Foo>> and that becomes unassignable. To fix it would require
-    // a second cast. If we just cast to the raw type InstanceFactory though, that becomes
-    // assignable.
-    return castThroughRawType
-        ? CodeBlock.of("($T) $L", INSTANCE_FACTORY, providerExpression) : providerExpression;
-  }
-
-  private boolean hasLocalInjectionSites(TypeElement injectedTypeElement) {
-    return binding.injectionSites()
-        .stream()
-        .anyMatch(
-            injectionSite ->
-                injectionSite.element().getEnclosingElement().equals(injectedTypeElement));
-  }
-
-  @Override
-  public boolean useInnerSwitchingProvider() {
-    return !binding.injectionSites().isEmpty();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/MethodBindingExpression.java b/java/dagger/internal/codegen/writing/MethodBindingExpression.java
deleted file mode 100644
index 9c0c74a..0000000
--- a/java/dagger/internal/codegen/writing/MethodBindingExpression.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedParameterSpecs;
-import static dagger.internal.codegen.javapoet.CodeBlocks.parameterNames;
-import static dagger.internal.codegen.writing.ComponentImplementation.FieldSpecKind.PRIVATE_METHOD_SCOPED_FIELD;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.VOLATILE;
-
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.DoubleCheck;
-import dagger.internal.MemoizedSentinel;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.FrameworkField;
-import dagger.internal.codegen.binding.KeyVariableNamer;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingKind;
-import dagger.model.RequestKind;
-import java.util.Optional;
-import javax.lang.model.type.TypeMirror;
-
-/** A binding expression that wraps another in a nullary method on the component. */
-abstract class MethodBindingExpression extends BindingExpression {
-  private final BindingRequest request;
-  private final ContributionBinding binding;
-  private final BindingMethodImplementation bindingMethodImplementation;
-  private final ComponentImplementation componentImplementation;
-  private final ProducerEntryPointView producerEntryPointView;
-  private final BindingExpression wrappedBindingExpression;
-  private final DaggerTypes types;
-
-  protected MethodBindingExpression(
-      BindingRequest request,
-      ContributionBinding binding,
-      MethodImplementationStrategy methodImplementationStrategy,
-      BindingExpression wrappedBindingExpression,
-      ComponentImplementation componentImplementation,
-      DaggerTypes types) {
-    this.request = checkNotNull(request);
-    this.binding = checkNotNull(binding);
-    this.bindingMethodImplementation = bindingMethodImplementation(methodImplementationStrategy);
-    this.wrappedBindingExpression = checkNotNull(wrappedBindingExpression);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.producerEntryPointView = new ProducerEntryPointView(types);
-    this.types = checkNotNull(types);
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    if (request.frameworkType().isPresent()) {
-      // Initializing a framework instance that participates in a cycle requires that the underlying
-      // FrameworkInstanceBindingExpression is invoked in order for a cycle to be detected properly.
-      // When a MethodBindingExpression wraps a FrameworkInstanceBindingExpression, the wrapped
-      // expression will only be invoked once to implement the method body. This is a hack to work
-      // around that weirdness - methodImplementation.body() will invoke the framework instance
-      // initialization again in case the field is not fully initialized.
-      // TODO(b/121196706): use a less hacky approach to fix this bug
-      Object unused = methodBody();
-    }
-
-    addMethod();
-
-    CodeBlock methodCall =
-         binding.kind() == BindingKind.ASSISTED_INJECTION
-              // Private methods for assisted injection take assisted parameters as input.
-              ? CodeBlock.of(
-                  "$N($L)", methodName(), parameterNames(assistedParameterSpecs(binding, types)))
-              : CodeBlock.of("$N()", methodName());
-
-    return Expression.create(
-        returnType(),
-        requestingClass.equals(componentImplementation.name())
-            ? methodCall
-            : CodeBlock.of("$L.$L", componentImplementation.externalReferenceBlock(), methodCall));
-  }
-
-  @Override
-  Expression getDependencyExpressionForComponentMethod(ComponentMethodDescriptor componentMethod,
-      ComponentImplementation component) {
-    return producerEntryPointView
-        .getProducerEntryPointField(this, componentMethod, component)
-        .orElseGet(
-            () -> super.getDependencyExpressionForComponentMethod(componentMethod, component));
-  }
-
-  /** Adds the method to the component (if necessary) the first time it's called. */
-  protected abstract void addMethod();
-
-  /** Returns the name of the method to call. */
-  protected abstract String methodName();
-
-  /** The method's body. */
-  protected final CodeBlock methodBody() {
-    return implementation(
-        wrappedBindingExpression.getDependencyExpression(componentImplementation.name())
-            ::codeBlock);
-  }
-
-  /** The method's body if this method is a component method. */
-  protected final CodeBlock methodBodyForComponentMethod(
-      ComponentMethodDescriptor componentMethod) {
-    return implementation(
-        wrappedBindingExpression.getDependencyExpressionForComponentMethod(
-                componentMethod, componentImplementation)
-            ::codeBlock);
-  }
-
-  private CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression) {
-    return bindingMethodImplementation.implementation(simpleBindingExpression);
-  }
-
-  private BindingMethodImplementation bindingMethodImplementation(
-      MethodImplementationStrategy methodImplementationStrategy) {
-    switch (methodImplementationStrategy) {
-      case SIMPLE:
-        return new SimpleMethodImplementation();
-      case SINGLE_CHECK:
-        return new SingleCheckedMethodImplementation();
-      case DOUBLE_CHECK:
-        return new DoubleCheckedMethodImplementation();
-    }
-    throw new AssertionError(methodImplementationStrategy);
-  }
-
-  /** Returns the return type for the dependency request. */
-  protected TypeMirror returnType() {
-    if (request.isRequestKind(RequestKind.INSTANCE)
-        && binding.contributedPrimitiveType().isPresent()) {
-      return binding.contributedPrimitiveType().get();
-    }
-
-    if (matchingComponentMethod().isPresent()) {
-      // Component methods are part of the user-defined API, and thus we must use the user-defined
-      // type.
-      return matchingComponentMethod().get().resolvedReturnType(types);
-    }
-
-    TypeMirror requestedType = request.requestedType(binding.contributedType(), types);
-    return types.accessibleType(requestedType, componentImplementation.name());
-  }
-
-  private Optional<ComponentMethodDescriptor> matchingComponentMethod() {
-    return componentImplementation.componentDescriptor().firstMatchingComponentMethod(request);
-  }
-
-  /** Strateg for implementing the body of this method. */
-  enum MethodImplementationStrategy {
-    SIMPLE,
-    SINGLE_CHECK,
-    DOUBLE_CHECK,
-    ;
-  }
-
-  private abstract static class BindingMethodImplementation {
-    /**
-     * Returns the method body, which contains zero or more statements (including semicolons).
-     *
-     * <p>If the implementation has a non-void return type, the body will also include the {@code
-     * return} statement.
-     *
-     * @param simpleBindingExpression the expression to retrieve an instance of this binding without
-     *     the wrapping method.
-     */
-    abstract CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression);
-  }
-
-  /** Returns the {@code wrappedBindingExpression} directly. */
-  private static final class SimpleMethodImplementation extends BindingMethodImplementation {
-    @Override
-    CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression) {
-      return CodeBlock.of("return $L;", simpleBindingExpression.get());
-    }
-  }
-
-  /**
-   * Defines a method body for single checked caching of the given {@code wrappedBindingExpression}.
-   */
-  private final class SingleCheckedMethodImplementation extends BindingMethodImplementation {
-    private final Supplier<FieldSpec> field = Suppliers.memoize(this::createField);
-
-    @Override
-    CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression) {
-      String fieldExpression = field.get().name.equals("local") ? "this.local" : field.get().name;
-
-      CodeBlock.Builder builder = CodeBlock.builder()
-          .addStatement("Object local = $N", fieldExpression);
-
-      if (isNullable()) {
-        builder.beginControlFlow("if (local instanceof $T)", MemoizedSentinel.class);
-      } else {
-        builder.beginControlFlow("if (local == null)");
-      }
-
-      return builder
-          .addStatement("local = $L", simpleBindingExpression.get())
-          .addStatement("$N = ($T) local", fieldExpression, returnType())
-          .endControlFlow()
-          .addStatement("return ($T) local", returnType())
-          .build();
-    }
-
-    FieldSpec createField() {
-      String name =
-          componentImplementation.getUniqueFieldName(
-              request.isRequestKind(RequestKind.INSTANCE)
-                  ? KeyVariableNamer.name(binding.key())
-                  : FrameworkField.forBinding(binding, Optional.empty()).name());
-
-      FieldSpec.Builder builder = FieldSpec.builder(fieldType(), name, PRIVATE, VOLATILE);
-      if (isNullable()) {
-        builder.initializer("new $T()", MemoizedSentinel.class);
-      }
-
-      FieldSpec field = builder.build();
-      componentImplementation.addField(PRIVATE_METHOD_SCOPED_FIELD, field);
-      return field;
-    }
-
-    TypeName fieldType() {
-      if (isNullable()) {
-        // Nullable instances use `MemoizedSentinel` instead of `null` as the initialization value,
-        // so the field type must accept that and the return type
-        return TypeName.OBJECT;
-      }
-      TypeName returnType = TypeName.get(returnType());
-      return returnType.isPrimitive() ? returnType.box() : returnType;
-    }
-
-    private boolean isNullable() {
-      return request.isRequestKind(RequestKind.INSTANCE) && binding.isNullable();
-    }
-  }
-
-  /**
-   * Defines a method body for double checked caching of the given {@code wrappedBindingExpression}.
-   */
-  private final class DoubleCheckedMethodImplementation extends BindingMethodImplementation {
-    private final Supplier<String> fieldName = Suppliers.memoize(this::createField);
-
-    @Override
-    CodeBlock implementation(Supplier<CodeBlock> simpleBindingExpression) {
-      String fieldExpression = fieldName.get().equals("local") ? "this.local" : fieldName.get();
-      return CodeBlock.builder()
-          .addStatement("$T local = $L", TypeName.OBJECT, fieldExpression)
-          .beginControlFlow("if (local instanceof $T)", MemoizedSentinel.class)
-          .beginControlFlow("synchronized (local)")
-          .addStatement("local = $L", fieldExpression)
-          .beginControlFlow("if (local instanceof $T)", MemoizedSentinel.class)
-          .addStatement("local = $L", simpleBindingExpression.get())
-          .addStatement("$1L = $2T.reentrantCheck($1L, local)", fieldExpression, DoubleCheck.class)
-          .endControlFlow()
-          .endControlFlow()
-          .endControlFlow()
-          .addStatement("return ($T) local", returnType())
-          .build();
-    }
-
-    private String createField() {
-      String name =
-          componentImplementation.getUniqueFieldName(KeyVariableNamer.name(binding.key()));
-      componentImplementation.addField(
-          PRIVATE_METHOD_SCOPED_FIELD,
-          FieldSpec.builder(TypeName.OBJECT, name, PRIVATE, VOLATILE)
-              .initializer("new $T()", MemoizedSentinel.class)
-              .build());
-      return name;
-    }
-  }
-
-}
diff --git a/java/dagger/internal/codegen/writing/ModuleGenerator.java b/java/dagger/internal/codegen/writing/ModuleGenerator.java
deleted file mode 100644
index afd0e99..0000000
--- a/java/dagger/internal/codegen/writing/ModuleGenerator.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.writing;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import dagger.internal.codegen.base.SourceFileGenerator;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifier for a {@link SourceFileGenerator} for modules. */
-@Qualifier
-@Retention(RUNTIME)
-public @interface ModuleGenerator {}
diff --git a/java/dagger/internal/codegen/writing/ModuleProxies.java b/java/dagger/internal/codegen/writing/ModuleProxies.java
deleted file mode 100644
index fcd9b56..0000000
--- a/java/dagger/internal/codegen/writing/ModuleProxies.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.writing;
-
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.util.ElementFilter.constructorsIn;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.binding.ModuleKind;
-import dagger.internal.codegen.binding.SourceFiles;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.Accessibility;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.Optional;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-
-/** Convenience methods for generating and using module constructor proxy methods. */
-public final class ModuleProxies {
-
-  private final DaggerElements elements;
-  private final KotlinMetadataUtil metadataUtil;
-
-  @Inject
-  public ModuleProxies(DaggerElements elements, KotlinMetadataUtil metadataUtil) {
-    this.elements = elements;
-    this.metadataUtil = metadataUtil;
-  }
-
-  /** Generates a {@code public static} proxy method for constructing module instances. */
-  // TODO(dpb): See if this can become a SourceFileGenerator<ModuleDescriptor> instead. Doing so may
-  // cause ModuleProcessingStep to defer elements multiple times.
-  public static final class ModuleConstructorProxyGenerator
-      extends SourceFileGenerator<TypeElement> {
-
-    private final ModuleProxies moduleProxies;
-    private final KotlinMetadataUtil metadataUtil;
-
-    @Inject
-    ModuleConstructorProxyGenerator(
-        Filer filer,
-        DaggerElements elements,
-        SourceVersion sourceVersion,
-        ModuleProxies moduleProxies,
-        KotlinMetadataUtil metadataUtil) {
-      super(filer, elements, sourceVersion);
-      this.moduleProxies = moduleProxies;
-      this.metadataUtil = metadataUtil;
-    }
-
-    @Override
-    public ClassName nameGeneratedType(TypeElement moduleElement) {
-      return moduleProxies.constructorProxyTypeName(moduleElement);
-    }
-
-    @Override
-    public Element originatingElement(TypeElement moduleElement) {
-      return moduleElement;
-    }
-
-    @Override
-    public Optional<TypeSpec.Builder> write(TypeElement moduleElement) {
-      ModuleKind.checkIsModule(moduleElement, metadataUtil);
-      return moduleProxies.nonPublicNullaryConstructor(moduleElement).isPresent()
-          ? Optional.of(buildProxy(moduleElement))
-          : Optional.empty();
-    }
-
-    private TypeSpec.Builder buildProxy(TypeElement moduleElement) {
-      return classBuilder(nameGeneratedType(moduleElement))
-          .addModifiers(PUBLIC, FINAL)
-          .addMethod(constructorBuilder().addModifiers(PRIVATE).build())
-          .addMethod(
-              methodBuilder("newInstance")
-                  .addModifiers(PUBLIC, STATIC)
-                  .returns(ClassName.get(moduleElement))
-                  .addStatement("return new $T()", moduleElement)
-                  .build());
-    }
-  }
-
-  /** The name of the class that hosts the module constructor proxy method. */
-  private ClassName constructorProxyTypeName(TypeElement moduleElement) {
-    ModuleKind.checkIsModule(moduleElement, metadataUtil);
-    ClassName moduleClassName = ClassName.get(moduleElement);
-    return moduleClassName
-        .topLevelClassName()
-        .peerClass(SourceFiles.classFileName(moduleClassName) + "_Proxy");
-  }
-
-  /**
-   * The module constructor being proxied. A proxy is generated if it is not publicly accessible and
-   * has no arguments. If an implicit reference to the enclosing class exists, or the module is
-   * abstract, no proxy method can be generated.
-   */
-  private Optional<ExecutableElement> nonPublicNullaryConstructor(TypeElement moduleElement) {
-    ModuleKind.checkIsModule(moduleElement, metadataUtil);
-    if (moduleElement.getModifiers().contains(ABSTRACT)
-        || (moduleElement.getNestingKind().isNested()
-            && !moduleElement.getModifiers().contains(STATIC))) {
-      return Optional.empty();
-    }
-    return constructorsIn(elements.getAllMembers(moduleElement)).stream()
-        .filter(constructor -> !Accessibility.isElementPubliclyAccessible(constructor))
-        .filter(constructor -> !constructor.getModifiers().contains(PRIVATE))
-        .filter(constructor -> constructor.getParameters().isEmpty())
-        .findAny();
-  }
-
-  /**
-   * Returns a code block that creates a new module instance, either by invoking the nullary
-   * constructor if it's accessible from {@code requestingClass} or else by invoking the
-   * constructor's generated proxy method.
-   */
-  public CodeBlock newModuleInstance(TypeElement moduleElement, ClassName requestingClass) {
-    ModuleKind.checkIsModule(moduleElement, metadataUtil);
-    String packageName = requestingClass.packageName();
-    return nonPublicNullaryConstructor(moduleElement)
-        .filter(constructor -> !isElementAccessibleFrom(constructor, packageName))
-        .map(
-            constructor ->
-                CodeBlock.of("$T.newInstance()", constructorProxyTypeName(moduleElement)))
-        .orElse(CodeBlock.of("new $T()", moduleElement));
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/MultibindingFactoryCreationExpression.java b/java/dagger/internal/codegen/writing/MultibindingFactoryCreationExpression.java
deleted file mode 100644
index 64e008e..0000000
--- a/java/dagger/internal/codegen/writing/MultibindingFactoryCreationExpression.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import dagger.model.DependencyRequest;
-
-/** An abstract factory creation expression for multibindings. */
-abstract class MultibindingFactoryCreationExpression
-    implements FrameworkInstanceCreationExpression {
-  private final ComponentImplementation componentImplementation;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final ContributionBinding binding;
-
-  MultibindingFactoryCreationExpression(
-      ContributionBinding binding,
-      ComponentImplementation componentImplementation,
-      ComponentBindingExpressions componentBindingExpressions) {
-    this.binding = checkNotNull(binding);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-  }
-
-  /** Returns the expression for a dependency of this multibinding. */
-  protected final CodeBlock multibindingDependencyExpression(DependencyRequest dependency) {
-    CodeBlock expression =
-        componentBindingExpressions
-            .getDependencyExpression(
-                BindingRequest.bindingRequest(dependency.key(), binding.frameworkType()),
-                componentImplementation.name())
-            .codeBlock();
-
-    return useRawType()
-        ? CodeBlocks.cast(expression, binding.frameworkType().frameworkClass())
-        : expression;
-  }
-
-  /** The binding request for this framework instance. */
-  protected final BindingRequest bindingRequest() {
-    return BindingRequest.bindingRequest(binding.key(), binding.frameworkType());
-  }
-
-  /**
-   * Returns true if the {@linkplain ContributionBinding#key() key type} is inaccessible from the
-   * component, and therefore a raw type must be used.
-   */
-  protected final boolean useRawType() {
-    return !componentImplementation.isTypeAccessible(binding.key().type());
-  }
-
-  @Override
-  public final boolean useInnerSwitchingProvider() {
-    return !binding.dependencies().isEmpty();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/OptionalBindingExpression.java b/java/dagger/internal/codegen/writing/OptionalBindingExpression.java
deleted file mode 100644
index 4faf3fa..0000000
--- a/java/dagger/internal/codegen/writing/OptionalBindingExpression.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.base.OptionalType;
-import dagger.internal.codegen.base.OptionalType.OptionalKind;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-
-/** A binding expression for optional bindings. */
-final class OptionalBindingExpression extends SimpleInvocationBindingExpression {
-  private final ProvisionBinding binding;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final DaggerTypes types;
-  private final SourceVersion sourceVersion;
-
-  @Inject
-  OptionalBindingExpression(
-      ProvisionBinding binding,
-      ComponentBindingExpressions componentBindingExpressions,
-      DaggerTypes types,
-      SourceVersion sourceVersion) {
-    super(binding);
-    this.binding = binding;
-    this.componentBindingExpressions = componentBindingExpressions;
-    this.types = types;
-    this.sourceVersion = sourceVersion;
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    OptionalType optionalType = OptionalType.from(binding.key());
-    OptionalKind optionalKind = optionalType.kind();
-    if (binding.dependencies().isEmpty()) {
-      if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
-        // When compiling with -source 7, javac's type inference isn't strong enough to detect
-        // Futures.immediateFuture(Optional.absent()) for keys that aren't Object. It also has
-        // issues
-        // when used as an argument to some members injection proxy methods (see
-        // https://github.com/google/dagger/issues/916)
-        if (isTypeAccessibleFrom(binding.key().type(), requestingClass.packageName())) {
-          return Expression.create(
-              binding.key().type(), optionalKind.parameterizedAbsentValueExpression(optionalType));
-        }
-      }
-      return Expression.create(binding.key().type(), optionalKind.absentValueExpression());
-    }
-    DependencyRequest dependency = getOnlyElement(binding.dependencies());
-
-    CodeBlock dependencyExpression =
-        componentBindingExpressions
-            .getDependencyExpression(bindingRequest(dependency), requestingClass)
-            .codeBlock();
-
-    // If the dependency type is inaccessible, then we have to use Optional.<Object>of(...), or else
-    // we will get "incompatible types: inference variable has incompatible bounds.
-    return isTypeAccessibleFrom(dependency.key().type(), requestingClass.packageName())
-        ? Expression.create(
-            binding.key().type(), optionalKind.presentExpression(dependencyExpression))
-        : Expression.create(
-            types.erasure(binding.key().type()),
-            optionalKind.presentObjectExpression(dependencyExpression));
-  }
-
-  @Override
-  boolean requiresMethodEncapsulation() {
-    // TODO(dpb): Maybe require it for present bindings.
-    return false;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/OptionalFactories.java b/java/dagger/internal/codegen/writing/OptionalFactories.java
deleted file mode 100644
index 2d80963..0000000
--- a/java/dagger/internal/codegen/writing/OptionalFactories.java
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Copyright (C) 2016 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.writing;
-
-import static com.google.common.base.CaseFormat.UPPER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
-import static com.google.common.base.Verify.verify;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.base.RequestKinds.requestTypeName;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER;
-import static dagger.internal.codegen.javapoet.TypeNames.abstractProducerOf;
-import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
-import static dagger.internal.codegen.writing.ComponentImplementation.FieldSpecKind.ABSENT_OPTIONAL_FIELD;
-import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.ABSENT_OPTIONAL_METHOD;
-import static dagger.internal.codegen.writing.ComponentImplementation.TypeSpecKind.PRESENT_FACTORY;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.internal.InstanceFactory;
-import dagger.internal.Preconditions;
-import dagger.internal.codegen.base.OptionalType;
-import dagger.internal.codegen.base.OptionalType.OptionalKind;
-import dagger.internal.codegen.binding.BindingType;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.javapoet.AnnotationSpecs;
-import dagger.model.RequestKind;
-import dagger.producers.Producer;
-import dagger.producers.internal.Producers;
-import java.util.Comparator;
-import java.util.Map;
-import java.util.Optional;
-import java.util.TreeMap;
-import java.util.concurrent.Executor;
-import javax.inject.Inject;
-import javax.inject.Provider;
-
-/** The nested class and static methods required by the component to implement optional bindings. */
-// TODO(dpb): Name members simply if a component uses only one of Guava or JDK Optional.
-@PerGeneratedFile
-final class OptionalFactories {
-  private final ComponentImplementation componentImplementation;
-
-  @Inject OptionalFactories(@TopLevel ComponentImplementation componentImplementation) {
-    this.componentImplementation = componentImplementation;
-  }
-
-  /**
-   * The factory classes that implement {@code Provider<Optional<T>>} or {@code
-   * Producer<Optional<T>>} for present optional bindings for a given kind of dependency request
-   * within the component.
-   *
-   * <p>The key is the {@code Provider<Optional<T>>} type.
-   */
-  private final Map<PresentFactorySpec, TypeSpec> presentFactoryClasses =
-      new TreeMap<>(
-          Comparator.comparing(PresentFactorySpec::valueKind)
-              .thenComparing(PresentFactorySpec::frameworkType)
-              .thenComparing(PresentFactorySpec::optionalKind));
-
-  /**
-   * The static methods that return a {@code Provider<Optional<T>>} that always returns an absent
-   * value.
-   */
-  private final Map<OptionalKind, MethodSpec> absentOptionalProviderMethods = new TreeMap<>();
-
-  /**
-   * The static fields for {@code Provider<Optional<T>>} objects that always return an absent value.
-   */
-  private final Map<OptionalKind, FieldSpec> absentOptionalProviderFields = new TreeMap<>();
-
-  /**
-   * Returns an expression that calls a static method that returns a {@code Provider<Optional<T>>}
-   * for absent optional bindings.
-   */
-  CodeBlock absentOptionalProvider(ContributionBinding binding) {
-    verify(
-        binding.bindingType().equals(BindingType.PROVISION),
-        "Absent optional bindings should be provisions: %s",
-        binding);
-    OptionalKind optionalKind = OptionalType.from(binding.key()).kind();
-    return CodeBlock.of(
-        "$N()",
-        absentOptionalProviderMethods.computeIfAbsent(
-            optionalKind,
-            kind -> {
-              MethodSpec method = absentOptionalProviderMethod(kind);
-              componentImplementation.addMethod(ABSENT_OPTIONAL_METHOD, method);
-              return method;
-            }));
-  }
-
-  /**
-   * Creates a method specification for a {@code Provider<Optional<T>>} that always returns an
-   * absent value.
-   */
-  private MethodSpec absentOptionalProviderMethod(OptionalKind optionalKind) {
-    TypeVariableName typeVariable = TypeVariableName.get("T");
-    return methodBuilder(
-            String.format(
-                "absent%sProvider", UPPER_UNDERSCORE.to(UPPER_CAMEL, optionalKind.name())))
-        .addModifiers(PRIVATE, STATIC)
-        .addTypeVariable(typeVariable)
-        .returns(providerOf(optionalKind.of(typeVariable)))
-        .addJavadoc(
-            "Returns a {@link $T} that returns {@code $L}.",
-            Provider.class,
-            optionalKind.absentValueExpression())
-        .addCode("$L // safe covariant cast\n", AnnotationSpecs.suppressWarnings(UNCHECKED))
-        .addCode(
-            "$1T provider = ($1T) $2N;",
-            providerOf(optionalKind.of(typeVariable)),
-            absentOptionalProviderFields.computeIfAbsent(
-                optionalKind,
-                kind -> {
-                  FieldSpec field = absentOptionalProviderField(kind);
-                  componentImplementation.addField(ABSENT_OPTIONAL_FIELD, field);
-                  return field;
-                }))
-        .addCode("return provider;")
-        .build();
-  }
-
-  /**
-   * Creates a field specification for a {@code Provider<Optional<T>>} that always returns an absent
-   * value.
-   */
-  private FieldSpec absentOptionalProviderField(OptionalKind optionalKind) {
-    return FieldSpec.builder(
-            PROVIDER,
-            String.format("ABSENT_%s_PROVIDER", optionalKind.name()),
-            PRIVATE,
-            STATIC,
-            FINAL)
-        .addAnnotation(AnnotationSpecs.suppressWarnings(RAWTYPES))
-        .initializer("$T.create($L)", InstanceFactory.class, optionalKind.absentValueExpression())
-        .addJavadoc(
-            "A {@link $T} that returns {@code $L}.",
-            Provider.class,
-            optionalKind.absentValueExpression())
-        .build();
-  }
-
-  /** Information about the type of a factory for present bindings. */
-  @AutoValue
-  abstract static class PresentFactorySpec {
-    /** Whether the factory is a {@link Provider} or a {@link Producer}. */
-    abstract FrameworkType frameworkType();
-
-    /** What kind of {@code Optional} is returned. */
-    abstract OptionalKind optionalKind();
-
-    /** The kind of request satisfied by the value of the {@code Optional}. */
-    abstract RequestKind valueKind();
-
-    /** The type variable for the factory class. */
-    TypeVariableName typeVariable() {
-      return TypeVariableName.get("T");
-    }
-
-    /** The type contained by the {@code Optional}. */
-    TypeName valueType() {
-      return requestTypeName(valueKind(), typeVariable());
-    }
-
-    /** The type provided or produced by the factory. */
-    ParameterizedTypeName optionalType() {
-      return optionalKind().of(valueType());
-    }
-
-    /** The type of the factory. */
-    ParameterizedTypeName factoryType() {
-      return frameworkType().frameworkClassOf(optionalType());
-    }
-
-    /** The type of the delegate provider or producer. */
-    ParameterizedTypeName delegateType() {
-      return frameworkType().frameworkClassOf(typeVariable());
-    }
-
-    /** Returns the superclass the generated factory should have, if any. */
-    Optional<ParameterizedTypeName> superclass() {
-      switch (frameworkType()) {
-        case PRODUCER_NODE:
-          // TODO(cgdecker): This probably isn't a big issue for now, but it's possible this
-          // shouldn't be an AbstractProducer:
-          // - As AbstractProducer, it'll only call the delegate's get() method once and then cache
-          //   that result (essentially) rather than calling the delegate's get() method each time
-          //   its get() method is called (which was what it did before the cancellation change).
-          // - It's not 100% clear to me whether the view-creation methods should return a view of
-          //   the same view created by the delegate or if they should just return their own views.
-          return Optional.of(abstractProducerOf(optionalType()));
-        default:
-          return Optional.empty();
-      }
-    }
-
-    /** Returns the superinterface the generated factory should have, if any. */
-    Optional<ParameterizedTypeName> superinterface() {
-      switch (frameworkType()) {
-        case PROVIDER:
-          return Optional.of(factoryType());
-        default:
-          return Optional.empty();
-      }
-    }
-
-    /** Returns the name of the factory method to generate. */
-    String factoryMethodName() {
-      switch (frameworkType()) {
-        case PROVIDER:
-          return "get";
-        case PRODUCER_NODE:
-          return "compute";
-      }
-      throw new AssertionError(frameworkType());
-    }
-
-    /** The name of the factory class. */
-    String factoryClassName() {
-      return new StringBuilder("Present")
-          .append(UPPER_UNDERSCORE.to(UPPER_CAMEL, optionalKind().name()))
-          .append(UPPER_UNDERSCORE.to(UPPER_CAMEL, valueKind().toString()))
-          .append(frameworkType().frameworkClass().getSimpleName())
-          .toString();
-    }
-
-    private static PresentFactorySpec of(ContributionBinding binding) {
-      return new AutoValue_OptionalFactories_PresentFactorySpec(
-          FrameworkType.forBindingType(binding.bindingType()),
-          OptionalType.from(binding.key()).kind(),
-          getOnlyElement(binding.dependencies()).kind());
-    }
-  }
-
-  /**
-   * Returns an expression for an instance of a nested class that implements {@code
-   * Provider<Optional<T>>} or {@code Producer<Optional<T>>} for a present optional binding, where
-   * {@code T} represents dependency requests of that kind.
-   *
-   * <ul>
-   *   <li>If {@code optionalRequestKind} is {@link RequestKind#INSTANCE}, the class implements
-   *       {@code ProviderOrProducer<Optional<T>>}.
-   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PROVIDER}, the class implements
-   *       {@code Provider<Optional<Provider<T>>>}.
-   *   <li>If {@code optionalRequestKind} is {@link RequestKind#LAZY}, the class implements {@code
-   *       Provider<Optional<Lazy<T>>>}.
-   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PROVIDER_OF_LAZY}, the class
-   *       implements {@code Provider<Optional<Provider<Lazy<T>>>>}.
-   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PRODUCER}, the class implements
-   *       {@code Producer<Optional<Producer<T>>>}.
-   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PRODUCED}, the class implements
-   *       {@code Producer<Optional<Produced<T>>>}.
-   * </ul>
-   *
-   * @param delegateFactory an expression for a {@link Provider} or {@link Producer} of the
-   *     underlying type
-   */
-  CodeBlock presentOptionalFactory(ContributionBinding binding, CodeBlock delegateFactory) {
-    return CodeBlock.of(
-        "$N.of($L)",
-        presentFactoryClasses.computeIfAbsent(
-            PresentFactorySpec.of(binding),
-            spec -> {
-              TypeSpec type = presentOptionalFactoryClass(spec);
-              componentImplementation.addType(PRESENT_FACTORY, type);
-              return type;
-            }),
-        delegateFactory);
-  }
-
-  private TypeSpec presentOptionalFactoryClass(PresentFactorySpec spec) {
-    FieldSpec delegateField =
-        FieldSpec.builder(spec.delegateType(), "delegate", PRIVATE, FINAL).build();
-    ParameterSpec delegateParameter = ParameterSpec.builder(delegateField.type, "delegate").build();
-    TypeSpec.Builder factoryClassBuilder =
-        classBuilder(spec.factoryClassName())
-            .addTypeVariable(spec.typeVariable())
-            .addModifiers(PRIVATE, STATIC, FINAL)
-            .addJavadoc(
-                "A {@code $T} that uses a delegate {@code $T}.",
-                spec.factoryType(),
-                delegateField.type);
-
-    spec.superclass().ifPresent(factoryClassBuilder::superclass);
-    spec.superinterface().ifPresent(factoryClassBuilder::addSuperinterface);
-
-    return factoryClassBuilder
-        .addField(delegateField)
-        .addMethod(
-            constructorBuilder()
-                .addModifiers(PRIVATE)
-                .addParameter(delegateParameter)
-                .addCode(
-                    "this.$N = $T.checkNotNull($N);",
-                    delegateField,
-                    Preconditions.class,
-                    delegateParameter)
-                .build())
-        .addMethod(presentOptionalFactoryGetMethod(spec, delegateField))
-        .addMethod(
-            methodBuilder("of")
-                .addModifiers(PRIVATE, STATIC)
-                .addTypeVariable(spec.typeVariable())
-                .returns(spec.factoryType())
-                .addParameter(delegateParameter)
-                .addCode(
-                    "return new $L<$T>($N);",
-                    spec.factoryClassName(),
-                    spec.typeVariable(),
-                    delegateParameter)
-                .build())
-        .build();
-  }
-
-  private MethodSpec presentOptionalFactoryGetMethod(
-      PresentFactorySpec spec, FieldSpec delegateField) {
-    MethodSpec.Builder getMethodBuilder =
-        methodBuilder(spec.factoryMethodName()).addAnnotation(Override.class).addModifiers(PUBLIC);
-
-    switch (spec.frameworkType()) {
-      case PROVIDER:
-        return getMethodBuilder
-            .returns(spec.optionalType())
-            .addCode(
-                "return $L;",
-                spec.optionalKind()
-                    .presentExpression(
-                        FrameworkType.PROVIDER.to(
-                            spec.valueKind(), CodeBlock.of("$N", delegateField))))
-            .build();
-
-      case PRODUCER_NODE:
-        getMethodBuilder.returns(listenableFutureOf(spec.optionalType()));
-
-        switch (spec.valueKind()) {
-          case FUTURE: // return a ListenableFuture<Optional<ListenableFuture<T>>>
-          case PRODUCER: // return a ListenableFuture<Optional<Producer<T>>>
-            return getMethodBuilder
-                .addCode(
-                    "return $T.immediateFuture($L);",
-                    Futures.class,
-                    spec.optionalKind()
-                        .presentExpression(
-                            FrameworkType.PRODUCER_NODE.to(
-                                spec.valueKind(), CodeBlock.of("$N", delegateField))))
-                .build();
-
-          case INSTANCE: // return a ListenableFuture<Optional<T>>
-            return getMethodBuilder
-                .addCode(
-                    "return $L;",
-                    transformFutureToOptional(
-                        spec.optionalKind(),
-                        spec.typeVariable(),
-                        CodeBlock.of("$N.get()", delegateField)))
-                .build();
-
-          case PRODUCED: // return a ListenableFuture<Optional<Produced<T>>>
-            return getMethodBuilder
-                .addCode(
-                    "return $L;",
-                    transformFutureToOptional(
-                        spec.optionalKind(),
-                        spec.valueType(),
-                        CodeBlock.of(
-                            "$T.createFutureProduced($N.get())", Producers.class, delegateField)))
-                .build();
-
-          default:
-            throw new UnsupportedOperationException(
-                spec.factoryType() + " objects are not supported");
-        }
-    }
-    throw new AssertionError(spec.frameworkType());
-  }
-
-  /**
-   * An expression that uses {@link Futures#transform(ListenableFuture, Function, Executor)} to
-   * transform a {@code ListenableFuture<inputType>} into a {@code
-   * ListenableFuture<Optional<inputType>>}.
-   *
-   * @param inputFuture an expression of type {@code ListenableFuture<inputType>}
-   */
-  private static CodeBlock transformFutureToOptional(
-      OptionalKind optionalKind, TypeName inputType, CodeBlock inputFuture) {
-    return CodeBlock.of(
-        "$T.transform($L, $L, $T.directExecutor())",
-        Futures.class,
-        inputFuture,
-        anonymousClassBuilder("")
-            .addSuperinterface(
-                ParameterizedTypeName.get(
-                    ClassName.get(Function.class), inputType, optionalKind.of(inputType)))
-            .addMethod(
-                methodBuilder("apply")
-                    .addAnnotation(Override.class)
-                    .addModifiers(PUBLIC)
-                    .returns(optionalKind.of(inputType))
-                    .addParameter(inputType, "input")
-                    .addCode("return $L;", optionalKind.presentExpression(CodeBlock.of("input")))
-                    .build())
-            .build(),
-        MoreExecutors.class);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/OptionalFactoryInstanceCreationExpression.java b/java/dagger/internal/codegen/writing/OptionalFactoryInstanceCreationExpression.java
deleted file mode 100644
index 593921e..0000000
--- a/java/dagger/internal/codegen/writing/OptionalFactoryInstanceCreationExpression.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.writing;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-
-/**
- * A {@link FrameworkInstanceCreationExpression} for {@link dagger.model.BindingKind#OPTIONAL
- * optional bindings}.
- */
-final class OptionalFactoryInstanceCreationExpression
-    implements FrameworkInstanceCreationExpression {
-  private final OptionalFactories optionalFactories;
-  private final ContributionBinding binding;
-  private final ComponentImplementation componentImplementation;
-  private final ComponentBindingExpressions componentBindingExpressions;
-
-  OptionalFactoryInstanceCreationExpression(
-      OptionalFactories optionalFactories,
-      ContributionBinding binding,
-      ComponentImplementation componentImplementation,
-      ComponentBindingExpressions componentBindingExpressions) {
-    this.optionalFactories = optionalFactories;
-    this.binding = binding;
-    this.componentImplementation = componentImplementation;
-    this.componentBindingExpressions = componentBindingExpressions;
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    return binding.dependencies().isEmpty()
-        ? optionalFactories.absentOptionalProvider(binding)
-        : optionalFactories.presentOptionalFactory(
-            binding,
-            componentBindingExpressions
-                .getDependencyExpression(
-                    bindingRequest(
-                        getOnlyElement(binding.dependencies()).key(), binding.frameworkType()),
-                    componentImplementation.name())
-                .codeBlock());
-  }
-
-  @Override
-  public boolean useInnerSwitchingProvider() {
-    // Share providers for empty optionals from OptionalFactories so we don't have numerous
-    // switch cases that all return Optional.empty().
-    return !binding.dependencies().isEmpty();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ParentComponent.java b/java/dagger/internal/codegen/writing/ParentComponent.java
deleted file mode 100644
index 20b946e..0000000
--- a/java/dagger/internal/codegen/writing/ParentComponent.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.writing;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/**
- * A {@link Qualifier} for bindings that are associated with a component implementation's parent
- * component.
- */
-@Retention(RUNTIME)
-@Qualifier
-public @interface ParentComponent {}
diff --git a/java/dagger/internal/codegen/writing/PerComponentImplementation.java b/java/dagger/internal/codegen/writing/PerComponentImplementation.java
deleted file mode 100644
index 80888df..0000000
--- a/java/dagger/internal/codegen/writing/PerComponentImplementation.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.writing;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import javax.inject.Scope;
-
-/** A {@link Scope} that encompasses a single component implementation. */
-@Retention(RUNTIME)
-@Scope
-public @interface PerComponentImplementation {}
diff --git a/java/dagger/internal/codegen/writing/PerGeneratedFile.java b/java/dagger/internal/codegen/writing/PerGeneratedFile.java
deleted file mode 100644
index c1fcaf7..0000000
--- a/java/dagger/internal/codegen/writing/PerGeneratedFile.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.writing;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import javax.inject.Scope;
-
-/**
- * A {@link Scope} that encompasses a top-level component implementation and any of its inner
- * descendant component implementations in the same generated file.
- */
-@Retention(RUNTIME)
-@Scope
-public @interface PerGeneratedFile {}
diff --git a/java/dagger/internal/codegen/writing/PrivateMethodBindingExpression.java b/java/dagger/internal/codegen/writing/PrivateMethodBindingExpression.java
deleted file mode 100644
index b6502ea..0000000
--- a/java/dagger/internal/codegen/writing/PrivateMethodBindingExpression.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedParameterSpecs;
-import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.PRIVATE_METHOD;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.codegen.binding.BindingRequest;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.BindingKind;
-
-/**
- * A binding expression that wraps the dependency expressions in a private, no-arg method.
- *
- * <p>Dependents of this binding expression will just call the no-arg private method.
- */
-final class PrivateMethodBindingExpression extends MethodBindingExpression {
-  private final ContributionBinding binding;
-  private final BindingRequest request;
-  private final ComponentImplementation componentImplementation;
-  private final CompilerOptions compilerOptions;
-  private final DaggerTypes types;
-  private String methodName;
-
-  PrivateMethodBindingExpression(
-      BindingRequest request,
-      ContributionBinding binding,
-      MethodImplementationStrategy methodImplementationStrategy,
-      BindingExpression wrappedBindingExpression,
-      ComponentImplementation componentImplementation,
-      DaggerTypes types,
-      CompilerOptions compilerOptions) {
-    super(
-        request,
-        binding,
-        methodImplementationStrategy,
-        wrappedBindingExpression,
-        componentImplementation,
-        types);
-    this.binding = binding;
-    this.request = checkNotNull(request);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.compilerOptions = checkNotNull(compilerOptions);
-    this.types = types;
-  }
-
-  @Override
-  protected void addMethod() {
-    if (methodName == null) {
-      // Have to set methodName field before implementing the method in order to handle recursion.
-      methodName = componentImplementation.getUniqueMethodName(request);
-
-      // TODO(bcorso): Fix the order that these generated methods are written to the component.
-      componentImplementation.addMethod(
-          PRIVATE_METHOD,
-          methodBuilder(methodName)
-              .addModifiers(PRIVATE)
-              .addParameters(
-                  // Private methods for assisted injection take assisted parameters as input.
-                  binding.kind() == BindingKind.ASSISTED_INJECTION
-                      ? assistedParameterSpecs(binding, types)
-                      : ImmutableList.of())
-              .returns(TypeName.get(returnType()))
-              .addCode(methodBody())
-              .build());
-    }
-  }
-
-  @Override
-  protected String methodName() {
-    checkState(methodName != null, "addMethod() must be called before methodName()");
-    return methodName;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ProducerCreationExpression.java b/java/dagger/internal/codegen/writing/ProducerCreationExpression.java
deleted file mode 100644
index 0d1ccf3..0000000
--- a/java/dagger/internal/codegen/writing/ProducerCreationExpression.java
+++ /dev/null
@@ -1,49 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-
-/**
- * A {@link dagger.producers.Producer} creation expression for a {@link
- * dagger.producers.Produces @Produces}-annotated module method.
- */
-// TODO(dpb): Resolve with InjectionOrProvisionProviderCreationExpression.
-final class ProducerCreationExpression implements FrameworkInstanceCreationExpression {
-
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final ContributionBinding binding;
-
-  ProducerCreationExpression(
-      ContributionBinding binding, ComponentBindingExpressions componentBindingExpressions) {
-    this.binding = checkNotNull(binding);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    return CodeBlock.of(
-        "$T.create($L)",
-        generatedClassNameForBinding(binding),
-        componentBindingExpressions.getCreateMethodArgumentsCodeBlock(binding));
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ProducerEntryPointView.java b/java/dagger/internal/codegen/writing/ProducerEntryPointView.java
deleted file mode 100644
index c58f4e0..0000000
--- a/java/dagger/internal/codegen/writing/ProducerEntryPointView.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.writing;
-
-import static dagger.internal.codegen.writing.ComponentImplementation.FieldSpecKind.FRAMEWORK_FIELD;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.RequestKind;
-import dagger.producers.Producer;
-import dagger.producers.internal.CancellationListener;
-import dagger.producers.internal.Producers;
-import java.util.Optional;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A factory of {@linkplain Producers#entryPointViewOf(Producer, CancellationListener) entry point
- * views} of {@link Producer}s.
- */
-final class ProducerEntryPointView {
-  private final DaggerTypes types;
-
-  ProducerEntryPointView(DaggerTypes types) {
-    this.types = types;
-  }
-
-  /**
-   * Returns an expression for an {@linkplain Producers#entryPointViewOf(Producer,
-   * CancellationListener) entry point view} of a producer if the component method returns a {@link
-   * Producer} or {@link com.google.common.util.concurrent.ListenableFuture}.
-   *
-   * <p>This is intended to be a replacement implementation for {@link
-   * dagger.internal.codegen.writing.BindingExpression#getDependencyExpressionForComponentMethod(ComponentMethodDescriptor,
-   * ComponentImplementation)}, and in cases where {@link Optional#empty()} is returned, callers
-   * should call {@code super.getDependencyExpressionForComponentMethod()}.
-   */
-  Optional<Expression> getProducerEntryPointField(
-      BindingExpression producerExpression,
-      ComponentMethodDescriptor componentMethod,
-      ComponentImplementation component) {
-    if (component.componentDescriptor().isProduction()
-        && (componentMethod.dependencyRequest().get().kind().equals(RequestKind.FUTURE)
-            || componentMethod.dependencyRequest().get().kind().equals(RequestKind.PRODUCER))) {
-      return Optional.of(
-          Expression.create(
-              fieldType(componentMethod),
-              "$N",
-              createField(producerExpression, componentMethod, component)));
-    } else {
-      // If the component isn't a production component, it won't implement CancellationListener and
-      // as such we can't create an entry point. But this binding must also just be a Producer from
-      // Provider anyway in that case, so there shouldn't be an issue.
-      // TODO(b/116855531): Is it really intended that a non-production component can have Producer
-      // entry points?
-      return Optional.empty();
-    }
-  }
-
-  private FieldSpec createField(
-      BindingExpression producerExpression,
-      ComponentMethodDescriptor componentMethod,
-      ComponentImplementation component) {
-    // TODO(cgdecker): Use a FrameworkFieldInitializer for this?
-    // Though I don't think we need the once-only behavior of that, since I think
-    // getComponentMethodImplementation will only be called once anyway
-    String methodName = componentMethod.methodElement().getSimpleName().toString();
-    FieldSpec field =
-        FieldSpec.builder(
-                TypeName.get(fieldType(componentMethod)),
-                component.getUniqueFieldName(methodName + "EntryPoint"),
-                PRIVATE)
-            .build();
-    component.addField(FRAMEWORK_FIELD, field);
-
-    CodeBlock fieldInitialization =
-        CodeBlock.of(
-            "this.$N = $T.entryPointViewOf($L, this);",
-            field,
-            Producers.class,
-            producerExpression.getDependencyExpression(component.name()).codeBlock());
-    component.addInitialization(fieldInitialization);
-
-    return field;
-  }
-
-  // TODO(cgdecker): Can we use producerExpression.getDependencyExpression().type() instead of
-  // needing to (re)compute this?
-  private TypeMirror fieldType(ComponentMethodDescriptor componentMethod) {
-    return types.wrapType(componentMethod.dependencyRequest().get().key().type(), Producer.class);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ProducerFactoryGenerator.java b/java/dagger/internal/codegen/writing/ProducerFactoryGenerator.java
deleted file mode 100644
index 5e52923..0000000
--- a/java/dagger/internal/codegen/writing/ProducerFactoryGenerator.java
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * Copyright (C) 2014 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.writing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Verify.verifyNotNull;
-import static com.squareup.javapoet.ClassName.OBJECT;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.binding.SourceFiles.bindingTypeElementTypeVariableNames;
-import static dagger.internal.codegen.binding.SourceFiles.generateBindingFieldsForDependencies;
-import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
-import static dagger.internal.codegen.binding.SourceFiles.parameterizedGeneratedTypeNameForBinding;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.FUTURE_RETURN_VALUE_IGNORED;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeNames.FUTURES;
-import static dagger.internal.codegen.javapoet.TypeNames.PRODUCERS;
-import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER_TOKEN;
-import static dagger.internal.codegen.javapoet.TypeNames.VOID_CLASS;
-import static dagger.internal.codegen.javapoet.TypeNames.listOf;
-import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.javapoet.TypeNames.producedOf;
-import static dagger.internal.codegen.writing.GwtCompatibility.gwtIncompatibleAnnotation;
-import static java.util.stream.Collectors.joining;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PROTECTED;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import dagger.internal.codegen.base.UniqueNameSet;
-import dagger.internal.codegen.binding.Binding;
-import dagger.internal.codegen.binding.FrameworkField;
-import dagger.internal.codegen.binding.KeyFactory;
-import dagger.internal.codegen.binding.ProductionBinding;
-import dagger.internal.codegen.binding.SourceFiles;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.javapoet.AnnotationSpecs;
-import dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression;
-import dagger.internal.codegen.javapoet.TypeNames;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.model.DependencyRequest;
-import dagger.model.Key;
-import dagger.model.RequestKind;
-import dagger.producers.Producer;
-import dagger.producers.internal.AbstractProducesMethodProducer;
-import dagger.producers.internal.Producers;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Optional;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.type.TypeMirror;
-
-/** Generates {@link Producer} implementations from {@link ProductionBinding} instances. */
-public final class ProducerFactoryGenerator extends SourceFileGenerator<ProductionBinding> {
-  private final CompilerOptions compilerOptions;
-  private final KeyFactory keyFactory;
-
-  @Inject
-  ProducerFactoryGenerator(
-      Filer filer,
-      DaggerElements elements,
-      SourceVersion sourceVersion,
-      CompilerOptions compilerOptions,
-      KeyFactory keyFactory) {
-    super(filer, elements, sourceVersion);
-    this.compilerOptions = compilerOptions;
-    this.keyFactory = keyFactory;
-  }
-
-  @Override
-  public ClassName nameGeneratedType(ProductionBinding binding) {
-    return generatedClassNameForBinding(binding);
-  }
-
-  @Override
-  public Element originatingElement(ProductionBinding binding) {
-    // we only create factories for bindings that have a binding element
-    return binding.bindingElement().get();
-  }
-
-  @Override
-  public Optional<TypeSpec.Builder> write(ProductionBinding binding) {
-    // We don't want to write out resolved bindings -- we want to write out the generic version.
-    checkArgument(!binding.unresolved().isPresent());
-    checkArgument(binding.bindingElement().isPresent());
-
-    TypeName providedTypeName = TypeName.get(binding.contributedType());
-    TypeName futureTypeName = listenableFutureOf(providedTypeName);
-
-    ClassName generatedTypeName = nameGeneratedType(binding);
-    TypeSpec.Builder factoryBuilder =
-        classBuilder(generatedTypeName)
-            .addModifiers(PUBLIC, FINAL)
-            .addTypeVariables(bindingTypeElementTypeVariableNames(binding));
-
-    UniqueNameSet uniqueFieldNames = new UniqueNameSet();
-    ImmutableMap.Builder<DependencyRequest, FieldSpec> fieldsBuilder = ImmutableMap.builder();
-
-    MethodSpec.Builder constructorBuilder = constructorBuilder().addModifiers(PRIVATE);
-
-    Optional<FieldSpec> moduleField =
-        binding.requiresModuleInstance()
-            ? Optional.of(
-                addFieldAndConstructorParameter(
-                    factoryBuilder,
-                    constructorBuilder,
-                    uniqueFieldNames.getUniqueName("module"),
-                    TypeName.get(binding.bindingTypeElement().get().asType())))
-            : Optional.empty();
-
-    List<CodeBlock> frameworkFieldAssignments = new ArrayList<>();
-
-    String executorParameterName = null;
-    String monitorParameterName = null;
-    ImmutableMap<DependencyRequest, FrameworkField> bindingFieldsForDependencies =
-        generateBindingFieldsForDependencies(binding);
-    for (Entry<DependencyRequest, FrameworkField> entry : bindingFieldsForDependencies.entrySet()) {
-      DependencyRequest dependency = entry.getKey();
-      Key key = dependency.key();
-      FrameworkField bindingField = entry.getValue();
-      String fieldName = uniqueFieldNames.getUniqueName(bindingField.name());
-      if (key.equals(keyFactory.forProductionImplementationExecutor())) {
-        executorParameterName = fieldName;
-        constructorBuilder.addParameter(bindingField.type(), executorParameterName);
-      } else if (key.equals(keyFactory.forProductionComponentMonitor())) {
-        monitorParameterName = fieldName;
-        constructorBuilder.addParameter(bindingField.type(), monitorParameterName);
-      } else {
-        FieldSpec field =
-            addFieldAndConstructorParameter(
-                factoryBuilder, constructorBuilder, fieldName, bindingField.type());
-        fieldsBuilder.put(dependency, field);
-        frameworkFieldAssignments.add(fieldAssignment(field, bindingField.type()));
-      }
-    }
-    ImmutableMap<DependencyRequest, FieldSpec> fields = fieldsBuilder.build();
-
-    constructorBuilder.addStatement(
-        "super($N, $L, $N)",
-        verifyNotNull(monitorParameterName),
-        producerTokenConstruction(generatedTypeName, binding),
-        verifyNotNull(executorParameterName));
-
-    if (binding.requiresModuleInstance()) {
-      assignField(constructorBuilder, moduleField.get(), null);
-    }
-
-    constructorBuilder.addCode(CodeBlock.join(frameworkFieldAssignments, "\n"));
-
-    MethodSpec.Builder collectDependenciesBuilder =
-        methodBuilder("collectDependencies").addAnnotation(Override.class).addModifiers(PROTECTED);
-
-    ImmutableList<DependencyRequest> asyncDependencies = asyncDependencies(binding);
-    for (DependencyRequest dependency : asyncDependencies) {
-      TypeName futureType = listenableFutureOf(asyncDependencyType(dependency));
-      CodeBlock futureAccess = CodeBlock.of("$N.get()", fields.get(dependency));
-      collectDependenciesBuilder.addStatement(
-          "$T $L = $L",
-          futureType,
-          dependencyFutureName(dependency),
-          dependency.kind().equals(RequestKind.PRODUCED)
-              ? CodeBlock.of("$T.createFutureProduced($L)", PRODUCERS, futureAccess)
-              : futureAccess);
-    }
-    FutureTransform futureTransform = FutureTransform.create(fields, binding, asyncDependencies);
-
-    collectDependenciesBuilder
-        .returns(listenableFutureOf(futureTransform.applyArgType()))
-        .addStatement("return $L", futureTransform.futureCodeBlock());
-
-    MethodSpec.Builder callProducesMethod =
-        methodBuilder("callProducesMethod")
-            .returns(futureTypeName)
-            .addAnnotation(Override.class)
-            .addModifiers(PUBLIC)
-            .addParameter(futureTransform.applyArgType(), futureTransform.applyArgName())
-            .addExceptions(getThrownTypeNames(binding.thrownTypes()))
-            .addCode(
-                getInvocationCodeBlock(
-                    binding, providedTypeName, futureTransform.parameterCodeBlocks()));
-    if (futureTransform.hasUncheckedCast()) {
-      callProducesMethod.addAnnotation(AnnotationSpecs.suppressWarnings(UNCHECKED));
-    }
-
-    MethodSpec constructor = constructorBuilder.build();
-    factoryBuilder
-        .superclass(
-            ParameterizedTypeName.get(
-                ClassName.get(AbstractProducesMethodProducer.class),
-                futureTransform.applyArgType(),
-                providedTypeName))
-        .addMethod(constructor)
-        .addMethod(staticFactoryMethod(binding, constructor))
-        .addMethod(collectDependenciesBuilder.build())
-        .addMethod(callProducesMethod.build());
-
-    gwtIncompatibleAnnotation(binding).ifPresent(factoryBuilder::addAnnotation);
-
-    // TODO(gak): write a sensible toString
-    return Optional.of(factoryBuilder);
-  }
-
-  private MethodSpec staticFactoryMethod(ProductionBinding binding, MethodSpec constructor) {
-    return MethodSpec.methodBuilder("create")
-        .addModifiers(PUBLIC, STATIC)
-        .returns(parameterizedGeneratedTypeNameForBinding(binding))
-        .addTypeVariables(bindingTypeElementTypeVariableNames(binding))
-        .addParameters(constructor.parameters)
-        .addStatement(
-            "return new $T($L)",
-            parameterizedGeneratedTypeNameForBinding(binding),
-            constructor.parameters.stream()
-                .map(p -> CodeBlock.of("$N", p.name))
-                .collect(toParametersCodeBlock()))
-        .build();
-  }
-
-  // TODO(ronshapiro): consolidate versions of these
-  private static FieldSpec addFieldAndConstructorParameter(
-      TypeSpec.Builder typeBuilder,
-      MethodSpec.Builder constructorBuilder,
-      String variableName,
-      TypeName variableType) {
-    FieldSpec field = FieldSpec.builder(variableType, variableName, PRIVATE, FINAL).build();
-    typeBuilder.addField(field);
-    constructorBuilder.addParameter(field.type, field.name);
-    return field;
-  }
-
-  private static CodeBlock fieldAssignment(FieldSpec field, ParameterizedTypeName type) {
-    CodeBlock.Builder statement = CodeBlock.builder();
-    if (type != null && type.rawType.equals(TypeNames.PRODUCER)) {
-      statement.addStatement(
-          "this.$1N = $2T.nonCancellationPropagatingViewOf($1N)", field, Producers.class);
-    } else {
-      statement.addStatement("this.$1N = $1N", field);
-    }
-    return statement.build();
-  }
-
-  private static void assignField(
-      MethodSpec.Builder constructorBuilder, FieldSpec field, ParameterizedTypeName type) {
-    if (type != null && type.rawType.equals(TypeNames.PRODUCER)) {
-      constructorBuilder.addStatement(
-          "this.$1N = $2T.nonCancellationPropagatingViewOf($1N)", field, Producers.class);
-    } else {
-      constructorBuilder.addStatement("this.$1N = $1N", field);
-    }
-  }
-
-  /** Returns a list of dependencies that are generated asynchronously. */
-  private static ImmutableList<DependencyRequest> asyncDependencies(Binding binding) {
-    return binding.dependencies().stream()
-        .filter(ProducerFactoryGenerator::isAsyncDependency)
-        .collect(toImmutableList());
-  }
-
-  private CodeBlock producerTokenConstruction(
-      ClassName generatedTypeName, ProductionBinding binding) {
-    CodeBlock producerTokenArgs =
-        compilerOptions.writeProducerNameInToken()
-            ? CodeBlock.of(
-                "$S",
-                String.format(
-                    "%s#%s",
-                    ClassName.get(binding.bindingTypeElement().get()),
-                    binding.bindingElement().get().getSimpleName()))
-            : CodeBlock.of("$T.class", generatedTypeName);
-    return CodeBlock.of("$T.create($L)", PRODUCER_TOKEN, producerTokenArgs);
-  }
-
-  /** Returns a name of the variable representing this dependency's future. */
-  private static String dependencyFutureName(DependencyRequest dependency) {
-    return dependency.requestElement().get().getSimpleName() + "Future";
-  }
-
-  /** Represents the transformation of an input future by a producer method. */
-  abstract static class FutureTransform {
-    protected final ImmutableMap<DependencyRequest, FieldSpec> fields;
-    protected final ProductionBinding binding;
-
-    FutureTransform(ImmutableMap<DependencyRequest, FieldSpec> fields, ProductionBinding binding) {
-      this.fields = fields;
-      this.binding = binding;
-    }
-
-    /** The code block representing the future that should be transformed. */
-    abstract CodeBlock futureCodeBlock();
-
-    /** The type of the argument to the apply method. */
-    abstract TypeName applyArgType();
-
-    /** The name of the argument to the apply method */
-    abstract String applyArgName();
-
-    /** The code blocks to be passed to the produces method itself. */
-    abstract ImmutableList<CodeBlock> parameterCodeBlocks();
-
-    /** Whether the transform method has an unchecked cast. */
-    boolean hasUncheckedCast() {
-      return false;
-    }
-
-    CodeBlock frameworkTypeUsageStatement(DependencyRequest dependency) {
-      return SourceFiles.frameworkTypeUsageStatement(
-          CodeBlock.of("$N", fields.get(dependency)), dependency.kind());
-    }
-
-    static FutureTransform create(
-        ImmutableMap<DependencyRequest, FieldSpec> fields,
-        ProductionBinding binding,
-        ImmutableList<DependencyRequest> asyncDependencies) {
-      if (asyncDependencies.isEmpty()) {
-        return new NoArgFutureTransform(fields, binding);
-      } else if (asyncDependencies.size() == 1) {
-        return new SingleArgFutureTransform(
-            fields, binding, Iterables.getOnlyElement(asyncDependencies));
-      } else {
-        return new MultiArgFutureTransform(fields, binding, asyncDependencies);
-      }
-    }
-  }
-
-  static final class NoArgFutureTransform extends FutureTransform {
-    NoArgFutureTransform(
-        ImmutableMap<DependencyRequest, FieldSpec> fields, ProductionBinding binding) {
-      super(fields, binding);
-    }
-
-    @Override
-    CodeBlock futureCodeBlock() {
-      return CodeBlock.of("$T.<$T>immediateFuture(null)", FUTURES, VOID_CLASS);
-    }
-
-    @Override
-    TypeName applyArgType() {
-      return VOID_CLASS;
-    }
-
-    @Override
-    String applyArgName() {
-      return "ignoredVoidArg";
-    }
-
-    @Override
-    ImmutableList<CodeBlock> parameterCodeBlocks() {
-      return binding.explicitDependencies().stream()
-          .map(this::frameworkTypeUsageStatement)
-          .collect(toImmutableList());
-    }
-  }
-
-  static final class SingleArgFutureTransform extends FutureTransform {
-    private final DependencyRequest asyncDependency;
-
-    SingleArgFutureTransform(
-        ImmutableMap<DependencyRequest, FieldSpec> fields,
-        ProductionBinding binding,
-        DependencyRequest asyncDependency) {
-      super(fields, binding);
-      this.asyncDependency = asyncDependency;
-    }
-
-    @Override
-    CodeBlock futureCodeBlock() {
-      return CodeBlock.of("$L", dependencyFutureName(asyncDependency));
-    }
-
-    @Override
-    TypeName applyArgType() {
-      return asyncDependencyType(asyncDependency);
-    }
-
-    @Override
-    String applyArgName() {
-      String argName = asyncDependency.requestElement().get().getSimpleName().toString();
-      if (argName.equals("module")) {
-        return "moduleArg";
-      }
-      return argName;
-    }
-
-    @Override
-    ImmutableList<CodeBlock> parameterCodeBlocks() {
-      ImmutableList.Builder<CodeBlock> parameterCodeBlocks = ImmutableList.builder();
-      for (DependencyRequest dependency : binding.explicitDependencies()) {
-        // We really want to compare instances here, because asyncDependency is an element in the
-        // set binding.dependencies().
-        if (dependency == asyncDependency) {
-          parameterCodeBlocks.add(CodeBlock.of("$L", applyArgName()));
-        } else {
-          parameterCodeBlocks.add(frameworkTypeUsageStatement(dependency));
-        }
-      }
-      return parameterCodeBlocks.build();
-    }
-  }
-
-  static final class MultiArgFutureTransform extends FutureTransform {
-    private final ImmutableList<DependencyRequest> asyncDependencies;
-
-    MultiArgFutureTransform(
-        ImmutableMap<DependencyRequest, FieldSpec> fields,
-        ProductionBinding binding,
-        ImmutableList<DependencyRequest> asyncDependencies) {
-      super(fields, binding);
-      this.asyncDependencies = asyncDependencies;
-    }
-
-    @Override
-    CodeBlock futureCodeBlock() {
-      return CodeBlock.of(
-          "$T.<$T>allAsList($L)",
-          FUTURES,
-          OBJECT,
-          asyncDependencies
-              .stream()
-              .map(ProducerFactoryGenerator::dependencyFutureName)
-              .collect(joining(", ")));
-    }
-
-    @Override
-    TypeName applyArgType() {
-      return listOf(OBJECT);
-    }
-
-    @Override
-    String applyArgName() {
-      return "args";
-    }
-
-    @Override
-    ImmutableList<CodeBlock> parameterCodeBlocks() {
-      int argIndex = 0;
-      ImmutableList.Builder<CodeBlock> codeBlocks = ImmutableList.builder();
-      for (DependencyRequest dependency : binding.explicitDependencies()) {
-        if (isAsyncDependency(dependency)) {
-          codeBlocks.add(
-              CodeBlock.of(
-                  "($T) $L.get($L)", asyncDependencyType(dependency), applyArgName(), argIndex));
-          argIndex++;
-        } else {
-          codeBlocks.add(frameworkTypeUsageStatement(dependency));
-        }
-      }
-      return codeBlocks.build();
-    }
-
-    @Override
-    boolean hasUncheckedCast() {
-      return true;
-    }
-  }
-
-  private static boolean isAsyncDependency(DependencyRequest dependency) {
-    switch (dependency.kind()) {
-      case INSTANCE:
-      case PRODUCED:
-        return true;
-      default:
-        return false;
-    }
-  }
-
-  private static TypeName asyncDependencyType(DependencyRequest dependency) {
-    TypeName keyName = TypeName.get(dependency.key().type());
-    switch (dependency.kind()) {
-      case INSTANCE:
-        return keyName;
-      case PRODUCED:
-        return producedOf(keyName);
-      default:
-        throw new AssertionError();
-    }
-  }
-
-  /**
-   * Creates a code block for the invocation of the producer method from the module, which should be
-   * used entirely within a method body.
-   *
-   * @param binding The binding to generate the invocation code block for.
-   * @param providedTypeName The type name that should be provided by this producer.
-   * @param parameterCodeBlocks The code blocks for all the parameters to the producer method.
-   */
-  private CodeBlock getInvocationCodeBlock(
-      ProductionBinding binding,
-      TypeName providedTypeName,
-      ImmutableList<CodeBlock> parameterCodeBlocks) {
-    CodeBlock moduleCodeBlock =
-        CodeBlock.of(
-            "$L.$L($L)",
-            binding.requiresModuleInstance()
-                ? "module"
-                : CodeBlock.of("$T", ClassName.get(binding.bindingTypeElement().get())),
-            binding.bindingElement().get().getSimpleName(),
-            makeParametersCodeBlock(parameterCodeBlocks));
-
-    final CodeBlock returnCodeBlock;
-    switch (binding.productionKind().get()) {
-      case IMMEDIATE:
-        returnCodeBlock =
-            CodeBlock.of("$T.<$T>immediateFuture($L)", FUTURES, providedTypeName, moduleCodeBlock);
-        break;
-      case FUTURE:
-        returnCodeBlock = moduleCodeBlock;
-        break;
-      case SET_OF_FUTURE:
-        returnCodeBlock = CodeBlock.of("$T.allAsSet($L)", PRODUCERS, moduleCodeBlock);
-        break;
-      default:
-        throw new AssertionError();
-    }
-    return CodeBlock.of("return $L;", returnCodeBlock);
-  }
-
-  /**
-   * Converts the list of thrown types into type names.
-   *
-   * @param thrownTypes the list of thrown types.
-   */
-  private FluentIterable<? extends TypeName> getThrownTypeNames(
-      Iterable<? extends TypeMirror> thrownTypes) {
-    return FluentIterable.from(thrownTypes).transform(TypeName::get);
-  }
-
-  @Override
-  protected ImmutableSet<Suppression> warningSuppressions() {
-    // TODO(beder): examine if we can remove this or prevent subtypes of Future from being produced
-    return ImmutableSet.of(FUTURE_RETURN_VALUE_IGNORED);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ProducerFromProviderCreationExpression.java b/java/dagger/internal/codegen/writing/ProducerFromProviderCreationExpression.java
deleted file mode 100644
index 9b0d4e8..0000000
--- a/java/dagger/internal/codegen/writing/ProducerFromProviderCreationExpression.java
+++ /dev/null
@@ -1,64 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.javapoet.TypeNames;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import dagger.model.RequestKind;
-import dagger.producers.Producer;
-import java.util.Optional;
-
-/** An {@link Producer} creation expression for provision bindings. */
-final class ProducerFromProviderCreationExpression implements FrameworkInstanceCreationExpression {
-  private final ContributionBinding binding;
-  private final ComponentImplementation componentImplementation;
-  private final ComponentBindingExpressions componentBindingExpressions;
-
-  ProducerFromProviderCreationExpression(
-      ContributionBinding binding,
-      ComponentImplementation componentImplementation,
-      ComponentBindingExpressions componentBindingExpressions) {
-    this.binding = checkNotNull(binding);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    return FrameworkType.PROVIDER.to(
-        RequestKind.PRODUCER,
-        componentBindingExpressions
-            .getDependencyExpression(
-                bindingRequest(binding.key(), FrameworkType.PROVIDER),
-                componentImplementation.name())
-            .codeBlock());
-  }
-
-  @Override
-  public Optional<ClassName> alternativeFrameworkClass() {
-    return Optional.of(TypeNames.PRODUCER);
-  }
-
-  // TODO(ronshapiro): should this have a simple factory if the delegate expression is simple?
-}
diff --git a/java/dagger/internal/codegen/writing/ProducerNodeInstanceBindingExpression.java b/java/dagger/internal/codegen/writing/ProducerNodeInstanceBindingExpression.java
deleted file mode 100644
index 0d3f7e8..0000000
--- a/java/dagger/internal/codegen/writing/ProducerNodeInstanceBindingExpression.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.squareup.javapoet.ClassName;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-
-/** Binding expression for producer node instances. */
-final class ProducerNodeInstanceBindingExpression extends FrameworkInstanceBindingExpression {
-  /** The component defining this binding. */
-  private final ComponentImplementation componentImplementation;
-  private final Key key;
-  private final ProducerEntryPointView producerEntryPointView;
-
-  ProducerNodeInstanceBindingExpression(
-      ContributionBinding binding,
-      FrameworkInstanceSupplier frameworkInstanceSupplier,
-      DaggerTypes types,
-      DaggerElements elements,
-      ComponentImplementation componentImplementation) {
-    super(binding, frameworkInstanceSupplier, types, elements);
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.key = binding.key();
-    this.producerEntryPointView = new ProducerEntryPointView(types);
-  }
-
-  @Override
-  protected FrameworkType frameworkType() {
-    return FrameworkType.PRODUCER_NODE;
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    Expression result = super.getDependencyExpression(requestingClass);
-    componentImplementation.addCancellableProducerKey(key);
-    return result;
-  }
-
-  @Override
-  Expression getDependencyExpressionForComponentMethod(
-      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
-    return producerEntryPointView
-        .getProducerEntryPointField(this, componentMethod, component)
-        .orElseGet(
-            () -> super.getDependencyExpressionForComponentMethod(componentMethod, component));
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ProviderInstanceBindingExpression.java b/java/dagger/internal/codegen/writing/ProviderInstanceBindingExpression.java
deleted file mode 100644
index 400c6a2..0000000
--- a/java/dagger/internal/codegen/writing/ProviderInstanceBindingExpression.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.writing;
-
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-
-/** Binding expression for provider instances. */
-final class ProviderInstanceBindingExpression extends FrameworkInstanceBindingExpression {
-
-  ProviderInstanceBindingExpression(
-      ContributionBinding binding,
-      FrameworkInstanceSupplier frameworkInstanceSupplier,
-      DaggerTypes types,
-      DaggerElements elements) {
-    super(
-        binding,
-        frameworkInstanceSupplier,
-        types,
-        elements);
-  }
-
-  @Override
-  protected FrameworkType frameworkType() {
-    return FrameworkType.PROVIDER;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/SetBindingExpression.java b/java/dagger/internal/codegen/writing/SetBindingExpression.java
deleted file mode 100644
index 0b2e11a..0000000
--- a/java/dagger/internal/codegen/writing/SetBindingExpression.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static javax.lang.model.util.ElementFilter.methodsIn;
-
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.SetBuilder;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.DependencyRequest;
-import java.util.Collections;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/** A binding expression for multibound sets. */
-final class SetBindingExpression extends SimpleInvocationBindingExpression {
-  private final ProvisionBinding binding;
-  private final BindingGraph graph;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final DaggerTypes types;
-  private final DaggerElements elements;
-
-  SetBindingExpression(
-      ProvisionBinding binding,
-      BindingGraph graph,
-      ComponentBindingExpressions componentBindingExpressions,
-      DaggerTypes types,
-      DaggerElements elements) {
-    super(binding);
-    this.binding = binding;
-    this.graph = graph;
-    this.componentBindingExpressions = componentBindingExpressions;
-    this.types = types;
-    this.elements = elements;
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    // TODO(ronshapiro): We should also make an ImmutableSet version of SetFactory
-    boolean isImmutableSetAvailable = isImmutableSetAvailable();
-    // TODO(ronshapiro, gak): Use Sets.immutableEnumSet() if it's available?
-    if (isImmutableSetAvailable && binding.dependencies().stream().allMatch(this::isSingleValue)) {
-      return Expression.create(
-          immutableSetType(),
-          CodeBlock.builder()
-              .add("$T.", ImmutableSet.class)
-              .add(maybeTypeParameter(requestingClass))
-              .add(
-                  "of($L)",
-                  binding
-                      .dependencies()
-                      .stream()
-                      .map(dependency -> getContributionExpression(dependency, requestingClass))
-                      .collect(toParametersCodeBlock()))
-              .build());
-    }
-    switch (binding.dependencies().size()) {
-      case 0:
-        return collectionsStaticFactoryInvocation(requestingClass, CodeBlock.of("emptySet()"));
-      case 1:
-        {
-          DependencyRequest dependency = getOnlyElement(binding.dependencies());
-          CodeBlock contributionExpression = getContributionExpression(dependency, requestingClass);
-          if (isSingleValue(dependency)) {
-            return collectionsStaticFactoryInvocation(
-                requestingClass, CodeBlock.of("singleton($L)", contributionExpression));
-          } else if (isImmutableSetAvailable) {
-            return Expression.create(
-                immutableSetType(),
-                CodeBlock.builder()
-                    .add("$T.", ImmutableSet.class)
-                    .add(maybeTypeParameter(requestingClass))
-                    .add("copyOf($L)", contributionExpression)
-                    .build());
-          }
-        }
-        // fall through
-      default:
-        CodeBlock.Builder instantiation = CodeBlock.builder();
-        instantiation
-            .add("$T.", isImmutableSetAvailable ? ImmutableSet.class : SetBuilder.class)
-            .add(maybeTypeParameter(requestingClass));
-        if (isImmutableSetBuilderWithExpectedSizeAvailable()) {
-          instantiation.add("builderWithExpectedSize($L)", binding.dependencies().size());
-        } else if (isImmutableSetAvailable) {
-          instantiation.add("builder()");
-        } else {
-          instantiation.add("newSetBuilder($L)", binding.dependencies().size());
-        }
-        for (DependencyRequest dependency : binding.dependencies()) {
-          String builderMethod = isSingleValue(dependency) ? "add" : "addAll";
-          instantiation.add(
-              ".$L($L)", builderMethod, getContributionExpression(dependency, requestingClass));
-        }
-        instantiation.add(".build()");
-        return Expression.create(
-            isImmutableSetAvailable ? immutableSetType() : binding.key().type(),
-            instantiation.build());
-    }
-  }
-
-  private DeclaredType immutableSetType() {
-    return types.getDeclaredType(
-        elements.getTypeElement(ImmutableSet.class), SetType.from(binding.key()).elementType());
-  }
-
-  private CodeBlock getContributionExpression(
-      DependencyRequest dependency, ClassName requestingClass) {
-    return componentBindingExpressions
-        .getDependencyExpression(bindingRequest(dependency), requestingClass)
-        .codeBlock();
-  }
-
-  private Expression collectionsStaticFactoryInvocation(
-      ClassName requestingClass, CodeBlock methodInvocation) {
-    return Expression.create(
-        binding.key().type(),
-        CodeBlock.builder()
-            .add("$T.", Collections.class)
-            .add(maybeTypeParameter(requestingClass))
-            .add(methodInvocation)
-            .build());
-  }
-
-  private CodeBlock maybeTypeParameter(ClassName requestingClass) {
-    TypeMirror elementType = SetType.from(binding.key()).elementType();
-    return isTypeAccessibleFrom(elementType, requestingClass.packageName())
-        ? CodeBlock.of("<$T>", elementType)
-        : CodeBlock.of("");
-  }
-
-  private boolean isSingleValue(DependencyRequest dependency) {
-    return graph.contributionBinding(dependency.key())
-        .contributionType()
-        .equals(ContributionType.SET);
-  }
-
-  private boolean isImmutableSetBuilderWithExpectedSizeAvailable() {
-    if (isImmutableSetAvailable()) {
-      return methodsIn(elements.getTypeElement(ImmutableSet.class).getEnclosedElements())
-          .stream()
-          .anyMatch(method -> method.getSimpleName().contentEquals("builderWithExpectedSize"));
-    }
-    return false;
-  }
-
-  private boolean isImmutableSetAvailable() {
-    return elements.getTypeElement(ImmutableSet.class) != null;
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/SetFactoryCreationExpression.java b/java/dagger/internal/codegen/writing/SetFactoryCreationExpression.java
deleted file mode 100644
index 754f909..0000000
--- a/java/dagger/internal/codegen/writing/SetFactoryCreationExpression.java
+++ /dev/null
@@ -1,92 +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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.binding.SourceFiles.setFactoryClassName;
-
-import com.squareup.javapoet.CodeBlock;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.base.SetType;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.BindingType;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.model.DependencyRequest;
-import dagger.producers.Produced;
-
-/** A factory creation expression for a multibound set. */
-final class SetFactoryCreationExpression extends MultibindingFactoryCreationExpression {
-  private final BindingGraph graph;
-  private final ContributionBinding binding;
-
-  SetFactoryCreationExpression(
-      ContributionBinding binding,
-      ComponentImplementation componentImplementation,
-      ComponentBindingExpressions componentBindingExpressions,
-      BindingGraph graph) {
-    super(binding, componentImplementation, componentBindingExpressions);
-    this.binding = checkNotNull(binding);
-    this.graph = checkNotNull(graph);
-  }
-
-  @Override
-  public CodeBlock creationExpression() {
-    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", setFactoryClassName(binding));
-    if (!useRawType()) {
-      SetType setType = SetType.from(binding.key());
-      builder.add(
-          "<$T>",
-          setType.elementsAreTypeOf(Produced.class)
-              ? setType.unwrappedElementType(Produced.class)
-              : setType.elementType());
-    }
-
-    int individualProviders = 0;
-    int setProviders = 0;
-    CodeBlock.Builder builderMethodCalls = CodeBlock.builder();
-    String methodNameSuffix =
-        binding.bindingType().equals(BindingType.PROVISION) ? "Provider" : "Producer";
-
-    for (DependencyRequest dependency : binding.dependencies()) {
-      ContributionType contributionType =
-          graph.contributionBinding(dependency.key()).contributionType();
-      String methodNamePrefix;
-      switch (contributionType) {
-        case SET:
-          individualProviders++;
-          methodNamePrefix = "add";
-          break;
-        case SET_VALUES:
-          setProviders++;
-          methodNamePrefix = "addCollection";
-          break;
-        default:
-          throw new AssertionError(dependency + " is not a set multibinding");
-      }
-
-      builderMethodCalls.add(
-          ".$N$N($L)",
-          methodNamePrefix,
-          methodNameSuffix,
-          multibindingDependencyExpression(dependency));
-    }
-    builder.add("builder($L, $L)", individualProviders, setProviders);
-    builder.add(builderMethodCalls.build());
-
-    return builder.add(".build()").build();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/SimpleInvocationBindingExpression.java b/java/dagger/internal/codegen/writing/SimpleInvocationBindingExpression.java
deleted file mode 100644
index f2062f4..0000000
--- a/java/dagger/internal/codegen/writing/SimpleInvocationBindingExpression.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2016 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import dagger.internal.codegen.binding.ContributionBinding;
-
-/** A simple binding expression for instance requests. Does not scope. */
-abstract class SimpleInvocationBindingExpression extends BindingExpression {
-  private final ContributionBinding binding;
-
-  SimpleInvocationBindingExpression(ContributionBinding binding) {
-    this.binding = checkNotNull(binding);
-  }
-
-  @Override
-  boolean requiresMethodEncapsulation() {
-    return !binding.dependencies().isEmpty();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/SimpleMethodBindingExpression.java b/java/dagger/internal/codegen/writing/SimpleMethodBindingExpression.java
deleted file mode 100644
index 82e6628..0000000
--- a/java/dagger/internal/codegen/writing/SimpleMethodBindingExpression.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2016 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.writing;
-
-import static com.google.auto.common.MoreElements.asExecutable;
-import static com.google.auto.common.MoreElements.asType;
-import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
-import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.writing.InjectionMethods.ProvisionMethod.requiresInjectionMethod;
-
-import com.google.auto.common.MoreTypes;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import dagger.internal.codegen.binding.ComponentRequirement;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import dagger.internal.codegen.writing.InjectionMethods.ProvisionMethod;
-import dagger.model.DependencyRequest;
-import java.util.Optional;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * A binding expression that invokes methods or constructors directly (without attempting to scope)
- * {@link dagger.model.RequestKind#INSTANCE} requests.
- */
-final class SimpleMethodBindingExpression extends SimpleInvocationBindingExpression {
-  private final CompilerOptions compilerOptions;
-  private final ProvisionBinding provisionBinding;
-  private final ComponentBindingExpressions componentBindingExpressions;
-  private final MembersInjectionMethods membersInjectionMethods;
-  private final ComponentRequirementExpressions componentRequirementExpressions;
-  private final DaggerElements elements;
-  private final SourceVersion sourceVersion;
-  private final KotlinMetadataUtil metadataUtil;
-
-  SimpleMethodBindingExpression(
-      ProvisionBinding binding,
-      CompilerOptions compilerOptions,
-      ComponentBindingExpressions componentBindingExpressions,
-      MembersInjectionMethods membersInjectionMethods,
-      ComponentRequirementExpressions componentRequirementExpressions,
-      DaggerElements elements,
-      SourceVersion sourceVersion,
-      KotlinMetadataUtil metadataUtil) {
-    super(binding);
-    this.compilerOptions = compilerOptions;
-    this.provisionBinding = binding;
-    this.metadataUtil = metadataUtil;
-    checkArgument(
-        provisionBinding.implicitDependencies().isEmpty(),
-        "framework deps are not currently supported");
-    checkArgument(provisionBinding.bindingElement().isPresent());
-    this.componentBindingExpressions = componentBindingExpressions;
-    this.membersInjectionMethods = membersInjectionMethods;
-    this.componentRequirementExpressions = componentRequirementExpressions;
-    this.elements = elements;
-    this.sourceVersion = sourceVersion;
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    return requiresInjectionMethod(provisionBinding, compilerOptions, requestingClass)
-        ? invokeInjectionMethod(requestingClass)
-        : invokeMethod(requestingClass);
-  }
-
-  private Expression invokeMethod(ClassName requestingClass) {
-    // TODO(dpb): align this with the contents of InlineMethods.create
-    CodeBlock arguments =
-        makeParametersCodeBlock(
-            ProvisionMethod.invokeArguments(
-                provisionBinding,
-                request -> dependencyArgument(request, requestingClass).codeBlock(),
-                requestingClass));
-    ExecutableElement method = asExecutable(provisionBinding.bindingElement().get());
-    CodeBlock invocation;
-    switch (method.getKind()) {
-      case CONSTRUCTOR:
-        invocation = CodeBlock.of("new $T($L)", constructorTypeName(requestingClass), arguments);
-        break;
-      case METHOD:
-        CodeBlock module;
-        Optional<CodeBlock> requiredModuleInstance = moduleReference(requestingClass);
-        if (requiredModuleInstance.isPresent()) {
-          module = requiredModuleInstance.get();
-        } else if (metadataUtil.isObjectClass(asType(method.getEnclosingElement()))) {
-          // Call through the singleton instance.
-          // See: https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#static-methods
-          module = CodeBlock.of("$T.INSTANCE", provisionBinding.bindingTypeElement().get());
-        } else {
-          module = CodeBlock.of("$T", provisionBinding.bindingTypeElement().get());
-        }
-        invocation = CodeBlock.of("$L.$L($L)", module, method.getSimpleName(), arguments);
-        break;
-      default:
-        throw new IllegalStateException();
-    }
-
-    return Expression.create(simpleMethodReturnType(), invocation);
-  }
-
-  private TypeName constructorTypeName(ClassName requestingClass) {
-    DeclaredType type = MoreTypes.asDeclared(provisionBinding.key().type());
-    TypeName typeName = TypeName.get(type);
-    if (type.getTypeArguments().stream()
-        .allMatch(t -> isTypeAccessibleFrom(t, requestingClass.packageName()))) {
-      return typeName;
-    }
-    return rawTypeName(typeName);
-  }
-
-  private Expression invokeInjectionMethod(ClassName requestingClass) {
-    return injectMembers(
-        ProvisionMethod.invoke(
-            provisionBinding,
-            request -> dependencyArgument(request, requestingClass).codeBlock(),
-            requestingClass,
-            moduleReference(requestingClass),
-            compilerOptions,
-            metadataUtil));
-  }
-
-  private Expression dependencyArgument(DependencyRequest dependency, ClassName requestingClass) {
-    return componentBindingExpressions.getDependencyArgumentExpression(dependency, requestingClass);
-  }
-
-  private Expression injectMembers(CodeBlock instance) {
-    if (provisionBinding.injectionSites().isEmpty()) {
-      return Expression.create(simpleMethodReturnType(), instance);
-    }
-    if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
-      // Java 7 type inference can't figure out that instance in
-      // injectParameterized(Parameterized_Factory.newParameterized()) is Parameterized<T> and not
-      // Parameterized<Object>
-      if (!MoreTypes.asDeclared(provisionBinding.key().type()).getTypeArguments().isEmpty()) {
-        TypeName keyType = TypeName.get(provisionBinding.key().type());
-        instance = CodeBlock.of("($T) ($T) $L", keyType, rawTypeName(keyType), instance);
-      }
-    }
-    MethodSpec membersInjectionMethod = membersInjectionMethods.getOrCreate(provisionBinding.key());
-    TypeMirror returnType =
-        membersInjectionMethod.returnType.equals(TypeName.OBJECT)
-            ? elements.getTypeElement(Object.class).asType()
-            : provisionBinding.key().type();
-    return Expression.create(returnType, CodeBlock.of("$N($L)", membersInjectionMethod, instance));
-  }
-
-  private Optional<CodeBlock> moduleReference(ClassName requestingClass) {
-    return provisionBinding.requiresModuleInstance()
-        ? provisionBinding
-            .contributingModule()
-            .map(Element::asType)
-            .map(ComponentRequirement::forModule)
-            .map(module -> componentRequirementExpressions.getExpression(module, requestingClass))
-        : Optional.empty();
-  }
-
-  private TypeMirror simpleMethodReturnType() {
-    return provisionBinding.contributedPrimitiveType().orElse(provisionBinding.key().type());
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/SubcomponentCreatorBindingExpression.java b/java/dagger/internal/codegen/writing/SubcomponentCreatorBindingExpression.java
deleted file mode 100644
index 3099048..0000000
--- a/java/dagger/internal/codegen/writing/SubcomponentCreatorBindingExpression.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2017 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.writing;
-
-import com.squareup.javapoet.ClassName;
-import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import javax.lang.model.type.TypeMirror;
-
-/** A binding expression for a subcomponent creator that just invokes the constructor. */
-final class SubcomponentCreatorBindingExpression extends SimpleInvocationBindingExpression {
-  private final TypeMirror creatorType;
-  private final String creatorImplementationName;
-
-  SubcomponentCreatorBindingExpression(
-      ContributionBinding binding, String creatorImplementationName) {
-    super(binding);
-    this.creatorType = binding.key().type();
-    this.creatorImplementationName = creatorImplementationName;
-  }
-
-  @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
-    return Expression.create(creatorType, "new $L()", creatorImplementationName);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/SubcomponentNames.java b/java/dagger/internal/codegen/writing/SubcomponentNames.java
deleted file mode 100644
index fa0037b..0000000
--- a/java/dagger/internal/codegen/writing/SubcomponentNames.java
+++ /dev/null
@@ -1,156 +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.writing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
-import static java.lang.Character.isUpperCase;
-import static java.lang.String.format;
-
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimaps;
-import dagger.internal.codegen.base.UniqueNameSet;
-import dagger.internal.codegen.binding.BindingGraph;
-import dagger.internal.codegen.binding.ComponentCreatorDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.KeyFactory;
-import dagger.model.Key;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-
-/**
- * Holds the unique simple names for all subcomponents, keyed by their {@link ComponentDescriptor}
- * and {@link Key} of the subcomponent builder.
- */
-public final class SubcomponentNames {
-  private static final Splitter QUALIFIED_NAME_SPLITTER = Splitter.on('.');
-
-  private final ImmutableMap<ComponentDescriptor, String> namesByDescriptor;
-  private final ImmutableMap<Key, ComponentDescriptor> descriptorsByCreatorKey;
-
-  public SubcomponentNames(BindingGraph graph, KeyFactory keyFactory) {
-    this.namesByDescriptor = namesByDescriptor(graph);
-    this.descriptorsByCreatorKey = descriptorsByCreatorKey(keyFactory, namesByDescriptor.keySet());
-  }
-
-  /** Returns the simple component name for the given {@link ComponentDescriptor}. */
-  String get(ComponentDescriptor componentDescriptor) {
-    return namesByDescriptor.get(componentDescriptor);
-  }
-
-  /**
-   * Returns the simple name for the subcomponent creator implementation with the given {@link Key}.
-   */
-  String getCreatorName(Key key) {
-    return getCreatorName(descriptorsByCreatorKey.get(key));
-  }
-
-  /**
-   * Returns the simple name for the subcomponent creator implementation for the given {@link
-   * ComponentDescriptor}.
-   */
-  String getCreatorName(ComponentDescriptor componentDescriptor) {
-    checkArgument(componentDescriptor.creatorDescriptor().isPresent());
-    ComponentCreatorDescriptor creatorDescriptor = componentDescriptor.creatorDescriptor().get();
-    return get(componentDescriptor) + creatorDescriptor.kind().typeName();
-  }
-
-  private static ImmutableMap<ComponentDescriptor, String> namesByDescriptor(BindingGraph graph) {
-    ImmutableListMultimap<String, ComponentDescriptor> componentDescriptorsBySimpleName =
-        Multimaps.index(graph.componentDescriptors(), SubcomponentNames::simpleName);
-    Map<ComponentDescriptor, String> subcomponentImplSimpleNames = new LinkedHashMap<>();
-    componentDescriptorsBySimpleName
-        .asMap()
-        .values()
-        .stream()
-        .map(SubcomponentNames::disambiguateConflictingSimpleNames)
-        .forEach(subcomponentImplSimpleNames::putAll);
-    subcomponentImplSimpleNames.remove(graph.componentDescriptor());
-    return ImmutableMap.copyOf(subcomponentImplSimpleNames);
-  }
-
-  private static ImmutableMap<Key, ComponentDescriptor> descriptorsByCreatorKey(
-      KeyFactory keyFactory, ImmutableSet<ComponentDescriptor> subcomponents) {
-    return subcomponents.stream()
-        .filter(subcomponent -> subcomponent.creatorDescriptor().isPresent())
-        .collect(
-            toImmutableMap(
-                subcomponent ->
-                    keyFactory.forSubcomponentCreator(
-                        subcomponent.creatorDescriptor().get().typeElement().asType()),
-                subcomponent -> subcomponent));
-  }
-
-  private static ImmutableMap<ComponentDescriptor, String> disambiguateConflictingSimpleNames(
-      Collection<ComponentDescriptor> componentsWithConflictingNames) {
-    // If there's only 1 component there's nothing to disambiguate so return the simple name.
-    if (componentsWithConflictingNames.size() == 1) {
-      ComponentDescriptor component = Iterables.getOnlyElement(componentsWithConflictingNames);
-      return ImmutableMap.of(component, simpleName(component));
-    }
-
-    // There are conflicting simple names, so disambiguate them with a unique prefix.
-    // We keep them small to fix https://github.com/google/dagger/issues/421.
-    UniqueNameSet nameSet = new UniqueNameSet();
-    ImmutableMap.Builder<ComponentDescriptor, String> uniqueNames = ImmutableMap.builder();
-    for (ComponentDescriptor component : componentsWithConflictingNames) {
-      String simpleName = simpleName(component);
-      String basePrefix = uniquingPrefix(component);
-      uniqueNames.put(component, format("%s_%s", nameSet.getUniqueName(basePrefix), simpleName));
-    }
-    return uniqueNames.build();
-  }
-
-  private static String simpleName(ComponentDescriptor component) {
-    return component.typeElement().getSimpleName().toString();
-  }
-
-  /** Returns a prefix that could make the component's simple name more unique. */
-  private static String uniquingPrefix(ComponentDescriptor component) {
-    TypeElement typeElement = component.typeElement();
-    String containerName = typeElement.getEnclosingElement().getSimpleName().toString();
-
-    // If parent element looks like a class, use its initials as a prefix.
-    if (!containerName.isEmpty() && isUpperCase(containerName.charAt(0))) {
-      return CharMatcher.javaLowerCase().removeFrom(containerName);
-    }
-
-    // Not in a normally named class. Prefix with the initials of the elements leading here.
-    Name qualifiedName = typeElement.getQualifiedName();
-    Iterator<String> pieces = QUALIFIED_NAME_SPLITTER.split(qualifiedName).iterator();
-    StringBuilder b = new StringBuilder();
-
-    while (pieces.hasNext()) {
-      String next = pieces.next();
-      if (pieces.hasNext()) {
-        b.append(next.charAt(0));
-      }
-    }
-
-    // Note that a top level class in the root package will be prefixed "$_".
-    return b.length() > 0 ? b.toString() : "$";
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/SwitchingProviders.java b/java/dagger/internal/codegen/writing/SwitchingProviders.java
deleted file mode 100644
index d38b9d9..0000000
--- a/java/dagger/internal/codegen/writing/SwitchingProviders.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * 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.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.getLast;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.internal.codegen.base.UniqueNameSet;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.langmodel.DaggerTypes;
-import dagger.model.Key;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Keeps track of all provider expression requests for a component.
- *
- * <p>The provider expression request will be satisfied by a single generated {@code Provider} inner
- * class that can provide instances for all types by switching on an id.
- */
-// TODO(ronshapiro): either merge this with InnerSwitchingProviders, or repurpose this for
-// SwitchingProducers
-abstract class SwitchingProviders {
-  /**
-   * Defines the {@linkplain Expression expressions} for a switch case in a {@code SwitchProvider}
-   * for a particular binding.
-   */
-  // TODO(bcorso): Consider handling SwitchingProviders with dependency arguments in this class,
-  // then we wouldn't need the getProviderExpression method.
-  // TODO(bcorso): Consider making this an abstract class with equals/hashCode defined by the key
-  // and then using this class directly in Map types instead of Key.
-  interface SwitchCase {
-    /** Returns the {@link Key} for this switch case. */
-    Key key();
-
-    /** Returns the {@link Expression} that returns the provided instance for this case. */
-    Expression getReturnExpression(ClassName switchingProviderClass);
-
-    /**
-     * Returns the {@link Expression} that returns the {@code SwitchProvider} instance for this
-     * case.
-     */
-    Expression getProviderExpression(ClassName switchingProviderClass, int switchId);
-  }
-
-  /**
-   * Each switch size is fixed at 100 cases each and put in its own method. This is to limit the
-   * size of the methods so that we don't reach the "huge" method size limit for Android that will
-   * prevent it from being AOT compiled in some versions of Android (b/77652521). This generally
-   * starts to happen around 1500 cases, but we are choosing 100 to be safe.
-   */
-  // TODO(bcorso): Include a proguard_spec in the Dagger library to prevent inlining these methods?
-  // TODO(ronshapiro): Consider making this configurable via a flag.
-  private static final int MAX_CASES_PER_SWITCH = 100;
-
-  private static final long MAX_CASES_PER_CLASS = MAX_CASES_PER_SWITCH * MAX_CASES_PER_SWITCH;
-  private static final TypeVariableName T = TypeVariableName.get("T");
-
-  /**
-   * Maps a {@link Key} to an instance of a {@link SwitchingProviderBuilder}. Each group of {@code
-   * MAX_CASES_PER_CLASS} keys will share the same instance.
-   */
-  private final Map<Key, SwitchingProviderBuilder> switchingProviderBuilders =
-      new LinkedHashMap<>();
-
-  private final ComponentImplementation componentImplementation;
-  private final ClassName owningComponent;
-  private final DaggerTypes types;
-  private final UniqueNameSet switchingProviderNames = new UniqueNameSet();
-
-  SwitchingProviders(ComponentImplementation componentImplementation, DaggerTypes types) {
-    this.componentImplementation = checkNotNull(componentImplementation);
-    this.types = checkNotNull(types);
-    this.owningComponent = checkNotNull(componentImplementation).name();
-  }
-
-  /** Returns the {@link TypeSpec} for a {@code SwitchingProvider} based on the given builder. */
-  protected abstract TypeSpec createSwitchingProviderType(TypeSpec.Builder builder);
-
-  /**
-   * Returns the {@link Expression} that returns the {@code SwitchProvider} instance for the case.
-   */
-  protected final Expression getProviderExpression(SwitchCase switchCase) {
-    return switchingProviderBuilders
-        .computeIfAbsent(switchCase.key(), key -> getSwitchingProviderBuilder())
-        .getProviderExpression(switchCase);
-  }
-
-  private SwitchingProviderBuilder getSwitchingProviderBuilder() {
-    if (switchingProviderBuilders.size() % MAX_CASES_PER_CLASS == 0) {
-      String name = switchingProviderNames.getUniqueName("SwitchingProvider");
-      SwitchingProviderBuilder switchingProviderBuilder =
-          new SwitchingProviderBuilder(owningComponent.nestedClass(name));
-      componentImplementation.addTypeSupplier(switchingProviderBuilder::build);
-      return switchingProviderBuilder;
-    }
-    return getLast(switchingProviderBuilders.values());
-  }
-
-  // TODO(bcorso): Consider just merging this class with SwitchingProviders.
-  private final class SwitchingProviderBuilder {
-    // Keep the switch cases ordered by switch id. The switch Ids are assigned in pre-order
-    // traversal, but the switch cases are assigned in post-order traversal of the binding graph.
-    private final Map<Integer, CodeBlock> switchCases = new TreeMap<>();
-    private final Map<Key, Integer> switchIds = new HashMap<>();
-    private final ClassName switchingProviderType;
-
-    SwitchingProviderBuilder(ClassName switchingProviderType) {
-      this.switchingProviderType = checkNotNull(switchingProviderType);
-    }
-
-    Expression getProviderExpression(SwitchCase switchCase) {
-      Key key = switchCase.key();
-      if (!switchIds.containsKey(key)) {
-        int switchId = switchIds.size();
-        switchIds.put(key, switchId);
-        switchCases.put(switchId, createSwitchCaseCodeBlock(switchCase));
-      }
-      return switchCase.getProviderExpression(switchingProviderType, switchIds.get(key));
-    }
-
-    private CodeBlock createSwitchCaseCodeBlock(SwitchCase switchCase) {
-      CodeBlock instanceCodeBlock =
-          switchCase.getReturnExpression(switchingProviderType).box(types).codeBlock();
-
-      return CodeBlock.builder()
-          // TODO(bcorso): Is there something else more useful than the key?
-          .add("case $L: // $L \n", switchIds.get(switchCase.key()), switchCase.key())
-          .addStatement("return ($T) $L", T, instanceCodeBlock)
-          .build();
-    }
-
-    private TypeSpec build() {
-      return createSwitchingProviderType(
-          classBuilder(switchingProviderType)
-              .addTypeVariable(T)
-              .addSuperinterface(providerOf(T))
-              .addMethods(getMethods()));
-    }
-
-    private ImmutableList<MethodSpec> getMethods() {
-      ImmutableList<CodeBlock> switchCodeBlockPartitions = switchCodeBlockPartitions();
-      if (switchCodeBlockPartitions.size() == 1) {
-        // There are less than MAX_CASES_PER_SWITCH cases, so no need for extra get methods.
-        return ImmutableList.of(
-            methodBuilder("get")
-                .addModifiers(PUBLIC)
-                .addAnnotation(suppressWarnings(UNCHECKED))
-                .addAnnotation(Override.class)
-                .returns(T)
-                .addCode(getOnlyElement(switchCodeBlockPartitions))
-                .build());
-      }
-
-      // This is the main public "get" method that will route to private getter methods.
-      MethodSpec.Builder routerMethod =
-          methodBuilder("get")
-              .addModifiers(PUBLIC)
-              .addAnnotation(Override.class)
-              .returns(T)
-              .beginControlFlow("switch (id / $L)", MAX_CASES_PER_SWITCH);
-
-      ImmutableList.Builder<MethodSpec> getMethods = ImmutableList.builder();
-      for (int i = 0; i < switchCodeBlockPartitions.size(); i++) {
-        MethodSpec method =
-            methodBuilder("get" + i)
-                .addModifiers(PRIVATE)
-                .addAnnotation(suppressWarnings(UNCHECKED))
-                .returns(T)
-                .addCode(switchCodeBlockPartitions.get(i))
-                .build();
-        getMethods.add(method);
-        routerMethod.addStatement("case $L: return $N()", i, method);
-      }
-
-      routerMethod.addStatement("default: throw new $T(id)", AssertionError.class).endControlFlow();
-
-      return getMethods.add(routerMethod.build()).build();
-    }
-
-    private ImmutableList<CodeBlock> switchCodeBlockPartitions() {
-      return Lists.partition(ImmutableList.copyOf(switchCases.values()), MAX_CASES_PER_SWITCH)
-          .stream()
-          .map(
-              partitionCases ->
-                  CodeBlock.builder()
-                      .beginControlFlow("switch (id)")
-                      .add(CodeBlocks.concat(partitionCases))
-                      .addStatement("default: throw new $T(id)", AssertionError.class)
-                      .endControlFlow()
-                      .build())
-          .collect(toImmutableList());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/TopLevel.java b/java/dagger/internal/codegen/writing/TopLevel.java
deleted file mode 100644
index ce71907..0000000
--- a/java/dagger/internal/codegen/writing/TopLevel.java
+++ /dev/null
@@ -1,29 +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.writing;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/**
- * A {@link Qualifier} for bindings that are associated with the top level component implementation.
- */
-@Retention(RUNTIME)
-@Qualifier
-public @interface TopLevel {}
diff --git a/java/dagger/internal/codegen/writing/UnwrappedMapKeyGenerator.java b/java/dagger/internal/codegen/writing/UnwrappedMapKeyGenerator.java
deleted file mode 100644
index f07b882..0000000
--- a/java/dagger/internal/codegen/writing/UnwrappedMapKeyGenerator.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2016 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.writing;
-
-import dagger.MapKey;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.Set;
-import javax.annotation.processing.Filer;
-import javax.inject.Inject;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.TypeElement;
-
-/**
- * Generates classes that create annotation instances for an unwrapped {@link MapKey} annotation
- * type whose nested value is an annotation. The generated class will have a private empty
- * constructor and a static method that creates each annotation type that is nested in the top-level
- * annotation type.
- *
- * <p>So for an example {@link MapKey} annotation:
- *
- * <pre>
- *   {@literal @MapKey}(unwrapValue = true)
- *   {@literal @interface} Foo {
- *     Bar bar();
- *   }
- *
- *   {@literal @interface} Bar {
- *     {@literal Class<?> baz();}
- *   }
- * </pre>
- *
- * the generated class will look like:
- *
- * <pre>
- *   public final class FooCreator {
- *     private FooCreator() {}
- *
- *     public static Bar createBar({@literal Class<?> baz}) { … }
- *   }
- * </pre>
- */
-public final class UnwrappedMapKeyGenerator extends AnnotationCreatorGenerator {
-
-  @Inject
-  UnwrappedMapKeyGenerator(Filer filer, DaggerElements elements, SourceVersion sourceVersion) {
-    super(filer, elements, sourceVersion);
-  }
-
-  @Override
-  protected Set<TypeElement> annotationsToCreate(TypeElement annotationElement) {
-    Set<TypeElement> nestedAnnotationElements = super.annotationsToCreate(annotationElement);
-    nestedAnnotationElements.remove(annotationElement);
-    return nestedAnnotationElements;
-  }
-}
diff --git a/java/dagger/internal/guava/BUILD b/java/dagger/internal/guava/BUILD
deleted file mode 100644
index 0bd4dcc..0000000
--- a/java/dagger/internal/guava/BUILD
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (C) 2017 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.
-
-# Description:
-#   Aliases from guava libraries to //third_party/java/guava.
-
-package(default_visibility = ["//:src"])
-
-alias(
-    name = "annotations",
-    actual = "@google_bazel_common//third_party/java/guava",
-)
-
-alias(
-    name = "base",
-    actual = "@google_bazel_common//third_party/java/guava",
-)
-
-alias(
-    name = "cache",
-    actual = "@google_bazel_common//third_party/java/guava",
-)
-
-alias(
-    name = "collect",
-    actual = "@google_bazel_common//third_party/java/guava",
-)
-
-alias(
-    name = "graph",
-    actual = "@google_bazel_common//third_party/java/guava",
-)
-
-alias(
-    name = "io",
-    actual = "@google_bazel_common//third_party/java/guava",
-)
-
-alias(
-    name = "concurrent",
-    actual = "@google_bazel_common//third_party/java/guava",
-)
-
-alias(
-    name = "base-android",
-    actual = "@maven//:com_google_guava_guava",
-)
-
-alias(
-    name = "collect-android",
-    actual = "@maven//:com_google_guava_guava",
-)
-
-alias(
-    name = "concurrent-android",
-    actual = "@maven//:com_google_guava_guava",
-)
diff --git a/java/dagger/lint/AndroidManifest.xml b/java/dagger/lint/AndroidManifest.xml
deleted file mode 100644
index f75cee1..0000000
--- a/java/dagger/lint/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
- Copyright (C) 2020 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.lint">
-  <uses-sdk android:minSdkVersion="14" />
-</manifest>
diff --git a/java/dagger/lint/BUILD b/java/dagger/lint/BUILD
deleted file mode 100644
index 3e0ffec..0000000
--- a/java/dagger/lint/BUILD
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Dagger Lint Rules
-
-load("//:build_defs.bzl", "POM_VERSION")
-load("//tools:maven.bzl", "gen_maven_artifact")
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
-
-package(default_visibility = ["//:src"])
-
-kt_jvm_library(
-    name = "lint-artifact-lib",
-    srcs = glob(["*.kt"]),
-    tags = ["maven_coordinates=com.google.dagger:dagger-lint:" + POM_VERSION],
-    deps = [
-        "@google_bazel_common//third_party/java/auto:service",
-        "@maven//:com_android_tools_external_com_intellij_intellij_core",
-        "@maven//:com_android_tools_external_com_intellij_kotlin_compiler",
-        "@maven//:com_android_tools_external_org_jetbrains_uast",
-        "@maven//:com_android_tools_lint_lint",
-        "@maven//:com_android_tools_lint_lint_api",
-    ],
-)
-
-# Current `kt_jvm_library` does not output source jars and gen_maven_artifact expects one.
-# See: https://github.com/bazelbuild/rules_kotlin/issues/324
-genrule(
-    name = "dagger-lint-sources",
-    srcs = glob(["*.kt"]),
-    outs = ["liblint-artifact-lib-src.jar"],
-    cmd = """
-        TEMP="$$(mktemp -d)"
-        for file in $(SRCS); do
-            filename="$$TEMP/$${file#java/}"
-            mkdir -p `dirname $$filename` && cp $$file $$filename
-        done
-        jar cf $@ -C $$TEMP .
-    """,
-)
-
-gen_maven_artifact(
-    name = "lint-artifact",
-    artifact_coordinates = "com.google.dagger:dagger-lint:" + POM_VERSION,
-    artifact_name = "Dagger Lint Rules",
-    artifact_target = ":lint-artifact-lib",
-    artifact_target_maven_deps = [
-        "com.android.tools.external.com-intellij:intellij-core",
-        "com.android.tools.external.com-intellij:kotlin-compiler",
-        "com.android.tools.external.org-jetbrains:uast",
-        "com.android.tools.lint:lint",
-        "com.android.tools.lint:lint-api",
-    ],
-    pom_name = "lint-pom",
-)
-
-# An empty android artifact to distribute and share the Dagger lint rules for
-# the Android sub-projects.
-android_library(
-    name = "lint-android-artifact-lib",
-    tags = ["maven_coordinates=com.google.dagger:dagger-lint-aar:" + POM_VERSION],
-)
-
-gen_maven_artifact(
-    name = "lint-android-artifact",
-    artifact_coordinates = "com.google.dagger:dagger-lint-aar:" + POM_VERSION,
-    artifact_name = "Dagger Lint Rules AAR Distribution",
-    artifact_target = ":lint-android-artifact-lib",
-    lint_deps = [":lint-artifact-lib"],
-    manifest = "AndroidManifest.xml",
-    packaging = "aar",
-    pom_name = "lint-android-pom",
-)
diff --git a/java/dagger/lint/DaggerIssueRegistry.kt b/java/dagger/lint/DaggerIssueRegistry.kt
deleted file mode 100644
index 113e85c..0000000
--- a/java/dagger/lint/DaggerIssueRegistry.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 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.lint
-
-import com.android.tools.lint.client.api.IssueRegistry
-import com.android.tools.lint.detector.api.CURRENT_API
-import com.android.tools.lint.detector.api.Issue
-import com.google.auto.service.AutoService
-
-/**
- * Dagger Lint Issues Registry.
- *
- * A META-INF/services entry is added for this class that Lint will discover and call into for
- * detecting issues.
- */
-@AutoService(IssueRegistry::class)
-@Suppress("unused", "UnstableApiUsage")
-class DaggerIssueRegistry : IssueRegistry() {
-  // The minApi is set to the Api this registry was compiled with, if a user has an older Api, Lint
-  // will show a warning asking users to upgrade.
-  override val minApi: Int = CURRENT_API
-  // The api is meant to be the current api for which this registry was compiled, but we set a
-  // higher number without depending on a newer Lint to avoid Lint warning users of custom checks
-  // that might not work. This value eventually has to be updated as newer Api become available.
-  override val api: Int = 8
-  override val issues: List<Issue> = DaggerKotlinIssueDetector.issues
-}
diff --git a/java/dagger/lint/DaggerKotlinIssueDetector.kt b/java/dagger/lint/DaggerKotlinIssueDetector.kt
deleted file mode 100644
index f3fdbd3..0000000
--- a/java/dagger/lint/DaggerKotlinIssueDetector.kt
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2020 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.lint
-
-import com.android.tools.lint.client.api.JavaEvaluator
-import com.android.tools.lint.client.api.UElementHandler
-import com.android.tools.lint.detector.api.Category
-import com.android.tools.lint.detector.api.Detector
-import com.android.tools.lint.detector.api.Implementation
-import com.android.tools.lint.detector.api.Issue
-import com.android.tools.lint.detector.api.JavaContext
-import com.android.tools.lint.detector.api.LintFix
-import com.android.tools.lint.detector.api.Scope
-import com.android.tools.lint.detector.api.Severity
-import com.android.tools.lint.detector.api.SourceCodeScanner
-import com.android.tools.lint.detector.api.TextFormat
-import com.android.tools.lint.detector.api.isKotlin
-import dagger.lint.DaggerKotlinIssueDetector.Companion.ISSUE_FIELD_SITE_TARGET_ON_QUALIFIER_ANNOTATION
-import dagger.lint.DaggerKotlinIssueDetector.Companion.ISSUE_JVM_STATIC_PROVIDES_IN_OBJECT
-import dagger.lint.DaggerKotlinIssueDetector.Companion.ISSUE_MODULE_COMPANION_OBJECTS
-import dagger.lint.DaggerKotlinIssueDetector.Companion.ISSUE_MODULE_COMPANION_OBJECTS_NOT_IN_MODULE_PARENT
-import java.util.EnumSet
-import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
-import org.jetbrains.kotlin.lexer.KtTokens
-import org.jetbrains.kotlin.psi.KtAnnotationEntry
-import org.jetbrains.kotlin.psi.KtObjectDeclaration
-import org.jetbrains.uast.UClass
-import org.jetbrains.uast.UElement
-import org.jetbrains.uast.UField
-import org.jetbrains.uast.UMethod
-import org.jetbrains.uast.getUastParentOfType
-import org.jetbrains.uast.kotlin.KotlinUClass
-import org.jetbrains.uast.toUElement
-
-/**
- * This is a simple lint check to catch common Dagger+Kotlin usage issues.
- *
- * - [ISSUE_FIELD_SITE_TARGET_ON_QUALIFIER_ANNOTATION] covers using `field:` site targets for member
- * injections, which are redundant as of Dagger 2.25.
- * - [ISSUE_JVM_STATIC_PROVIDES_IN_OBJECT] covers using `@JvmStatic` for object
- * `@Provides`-annotated functions, which are redundant as of Dagger 2.25. @JvmStatic on companion
- * object functions are redundant as of Dagger 2.26.
- * - [ISSUE_MODULE_COMPANION_OBJECTS] covers annotating companion objects with `@Module`, as they
- * are now part of the enclosing module class's API in Dagger 2.26. This will also error if the
- * enclosing class is _not_ in a `@Module`-annotated class, as this object just should be moved to a
- * top-level object to avoid confusion.
- * - [ISSUE_MODULE_COMPANION_OBJECTS_NOT_IN_MODULE_PARENT] covers annotating companion objects with
- * `@Module` when the parent class is _not_ also annotated with `@Module`. While technically legal,
- * these should be moved up to top-level objects to avoid confusion.
- */
-@Suppress("UnstableApiUsage") // Lots of Lint APIs are marked with @Beta.
-class DaggerKotlinIssueDetector : Detector(), SourceCodeScanner {
-
-  companion object {
-    // We use the overloaded constructor that takes a varargs of `Scope` as the last param.
-    // This is to enable on-the-fly IDE checks. We are telling lint to run on both
-    // JAVA and TEST_SOURCES in the `scope` parameter but by providing the `analysisScopes`
-    // params, we're indicating that this check can run on either JAVA or TEST_SOURCES and
-    // doesn't require both of them together.
-    // From discussion on lint-dev https://groups.google.com/d/msg/lint-dev/ULQMzW1ZlP0/1dG4Vj3-AQAJ
-    // This was supposed to be fixed in AS 3.4 but still required as recently as 3.6.
-    private val SCOPES = Implementation(
-      DaggerKotlinIssueDetector::class.java,
-      EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES),
-      EnumSet.of(Scope.JAVA_FILE),
-      EnumSet.of(Scope.TEST_SOURCES)
-    )
-
-    private val ISSUE_JVM_STATIC_PROVIDES_IN_OBJECT: Issue = Issue.create(
-      id = "JvmStaticProvidesInObjectDetector",
-      briefDescription = "@JvmStatic used for @Provides function in an object class",
-      explanation =
-        """
-        It's redundant to annotate @Provides functions in object classes with @JvmStatic.
-        """,
-      category = Category.CORRECTNESS,
-      priority = 5,
-      severity = Severity.WARNING,
-      implementation = SCOPES
-    )
-
-    private val ISSUE_FIELD_SITE_TARGET_ON_QUALIFIER_ANNOTATION: Issue = Issue.create(
-      id = "FieldSiteTargetOnQualifierAnnotation",
-      briefDescription = "Redundant 'field:' used for Dagger qualifier annotation.",
-      explanation =
-        """
-        It's redundant to use 'field:' site-targets for qualifier annotations.
-        """,
-      category = Category.CORRECTNESS,
-      priority = 5,
-      severity = Severity.WARNING,
-      implementation = SCOPES
-    )
-
-    private val ISSUE_MODULE_COMPANION_OBJECTS: Issue = Issue.create(
-      id = "ModuleCompanionObjects",
-      briefDescription = "Module companion objects should not be annotated with @Module.",
-      explanation =
-        """
-        Companion objects in @Module-annotated classes are considered part of the API.
-        """,
-      category = Category.CORRECTNESS,
-      priority = 5,
-      severity = Severity.WARNING,
-      implementation = SCOPES
-    )
-
-    private val ISSUE_MODULE_COMPANION_OBJECTS_NOT_IN_MODULE_PARENT: Issue = Issue.create(
-      id = "ModuleCompanionObjectsNotInModuleParent",
-      briefDescription = "Companion objects should not be annotated with @Module.",
-      explanation =
-        """
-        Companion objects in @Module-annotated classes are considered part of the API. This
-        companion object is not a companion to an @Module-annotated class though, and should be
-        moved to a top-level object declaration instead otherwise Dagger will ignore companion
-        object.
-        """,
-      category = Category.CORRECTNESS,
-      priority = 5,
-      severity = Severity.WARNING,
-      implementation = SCOPES
-    )
-
-    private const val PROVIDES_ANNOTATION = "dagger.Provides"
-    private const val JVM_STATIC_ANNOTATION = "kotlin.jvm.JvmStatic"
-    private const val INJECT_ANNOTATION = "javax.inject.Inject"
-    private const val QUALIFIER_ANNOTATION = "javax.inject.Qualifier"
-    private const val MODULE_ANNOTATION = "dagger.Module"
-
-    val issues: List<Issue> = listOf(
-      ISSUE_JVM_STATIC_PROVIDES_IN_OBJECT,
-      ISSUE_FIELD_SITE_TARGET_ON_QUALIFIER_ANNOTATION,
-      ISSUE_MODULE_COMPANION_OBJECTS,
-      ISSUE_MODULE_COMPANION_OBJECTS_NOT_IN_MODULE_PARENT
-    )
-  }
-
-  override fun getApplicableUastTypes(): List<Class<out UElement>>? {
-    return listOf(UMethod::class.java, UField::class.java, UClass::class.java)
-  }
-
-  override fun createUastHandler(context: JavaContext): UElementHandler? {
-    if (!isKotlin(context.psiFile)) {
-      // This is only relevant for Kotlin files.
-      return null
-    }
-    return object : UElementHandler() {
-      override fun visitField(node: UField) {
-        if (!context.evaluator.isLateInit(node)) {
-          return
-        }
-        // Can't use hasAnnotation because it doesn't capture all annotations!
-        val injectAnnotation =
-          node.annotations.find { it.qualifiedName == INJECT_ANNOTATION } ?: return
-        // Look for qualifier annotations
-        node.annotations.forEach { annotation ->
-          if (annotation === injectAnnotation) {
-            // Skip the inject annotation
-            return@forEach
-          }
-          // Check if it's a FIELD site target
-          val sourcePsi = annotation.sourcePsi
-          if (sourcePsi is KtAnnotationEntry &&
-            sourcePsi.useSiteTarget?.getAnnotationUseSiteTarget() == AnnotationUseSiteTarget.FIELD
-          ) {
-            // Check if this annotation is a qualifier annotation
-            if (annotation.resolve()?.hasAnnotation(QUALIFIER_ANNOTATION) == true) {
-              context.report(
-                ISSUE_FIELD_SITE_TARGET_ON_QUALIFIER_ANNOTATION,
-                context.getLocation(annotation),
-                ISSUE_FIELD_SITE_TARGET_ON_QUALIFIER_ANNOTATION
-                  .getBriefDescription(TextFormat.TEXT),
-                LintFix.create()
-                  .name("Remove 'field:'")
-                  .replace()
-                  .text("field:")
-                  .with("")
-                  .autoFix()
-                  .build()
-              )
-            }
-          }
-        }
-      }
-
-      override fun visitMethod(node: UMethod) {
-        if (!node.isConstructor &&
-          node.hasAnnotation(PROVIDES_ANNOTATION) &&
-          node.hasAnnotation(JVM_STATIC_ANNOTATION)
-        ) {
-          val containingClass = node.containingClass?.toUElement(UClass::class.java) ?: return
-          if (containingClass.isObject()) {
-            val annotation = node.findAnnotation(JVM_STATIC_ANNOTATION)!!
-            context.report(
-              ISSUE_JVM_STATIC_PROVIDES_IN_OBJECT,
-              context.getLocation(annotation),
-              ISSUE_JVM_STATIC_PROVIDES_IN_OBJECT.getBriefDescription(TextFormat.TEXT),
-              LintFix.create()
-                .name("Remove @JvmStatic")
-                .replace()
-                .pattern("(@(kotlin\\.jvm\\.)?JvmStatic)")
-                .with("")
-                .autoFix()
-                .build()
-            )
-          }
-        }
-      }
-
-      override fun visitClass(node: UClass) {
-        if (node.hasAnnotation(MODULE_ANNOTATION) && node.isCompanionObject(context.evaluator)) {
-          val parent = node.getUastParentOfType(UClass::class.java, false)!!
-          if (parent.hasAnnotation(MODULE_ANNOTATION)) {
-            context.report(
-              ISSUE_MODULE_COMPANION_OBJECTS,
-              context.getLocation(node as UElement),
-              ISSUE_MODULE_COMPANION_OBJECTS.getBriefDescription(TextFormat.TEXT),
-              LintFix.create()
-                .name("Remove @Module")
-                .replace()
-                .pattern("(@(dagger\\.)?Module)")
-                .with("")
-                .autoFix()
-                .build()
-
-            )
-          } else {
-            context.report(
-              ISSUE_MODULE_COMPANION_OBJECTS_NOT_IN_MODULE_PARENT,
-              context.getLocation(node as UElement),
-              ISSUE_MODULE_COMPANION_OBJECTS_NOT_IN_MODULE_PARENT
-                .getBriefDescription(TextFormat.TEXT)
-            )
-          }
-        }
-      }
-    }
-  }
-
-  /** @return whether or not the [this] is a Kotlin `companion object` type. */
-  private fun UClass.isCompanionObject(evaluator: JavaEvaluator): Boolean {
-    return isObject() && evaluator.hasModifier(this, KtTokens.COMPANION_KEYWORD)
-  }
-
-  /** @return whether or not the [this] is a Kotlin `object` type. */
-  private fun UClass.isObject(): Boolean {
-    return this is KotlinUClass && ktClass is KtObjectDeclaration
-  }
-}
diff --git a/java/dagger/model/BUILD b/java/dagger/model/BUILD
index 0be8fc5..5fe0db3 100644
--- a/java/dagger/model/BUILD
+++ b/java/dagger/model/BUILD
@@ -15,23 +15,14 @@
 # Description:
 #   Dagger's core APIs exposed for plugins
 
-load("@rules_java//java:defs.bzl", "java_library")
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
     "DOCLINT_REFERENCES",
 )
 
-package(
-    default_visibility = [
-        # The dagger/spi should be the only direct dependent on this target.
-        # If you need to depend on :model, depend on dagger/spi instead so
-        # that pom files correctly pick up the spi maven dependency.
-        # TODO(bcorso): Consider if :model should have its own maven coordinates.
-        "//java/dagger/spi:__pkg__",
-    ],
-)
-
 INTERNAL_PROXIES = ["BindingGraphProxies.java"]
 
 filegroup(
@@ -48,16 +39,14 @@
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     deps = [
         "//java/dagger:core",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:graph",
+        "//java/dagger/internal/codegen:jdk-and-guava-extras",
         "//java/dagger/producers",
+        "@google_bazel_common//third_party/java/auto:common",
         "@google_bazel_common//third_party/java/auto:value",
         "@google_bazel_common//third_party/java/error_prone:annotations",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/javapoet",
         "@google_bazel_common//third_party/java/jsr330_inject",
-        "@maven//:com_google_auto_auto_common",
     ],
 )
 
@@ -65,11 +54,8 @@
     name = "internal-proxies",
     srcs = INTERNAL_PROXIES,
     tags = ["maven:merged"],
-    visibility = ["//:src"],
     deps = [
         ":model",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:graph",
-        "@google_bazel_common//third_party/java/auto:value",
+        "@google_bazel_common//third_party/java/guava",
     ],
 )
diff --git a/java/dagger/model/BindingGraph.java b/java/dagger/model/BindingGraph.java
index 1ccba43..748bf38 100644
--- a/java/dagger/model/BindingGraph.java
+++ b/java/dagger/model/BindingGraph.java
@@ -20,10 +20,12 @@
 import static com.google.common.graph.Graphs.inducedSubgraph;
 import static com.google.common.graph.Graphs.reachableNodes;
 import static com.google.common.graph.Graphs.transpose;
-import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSetMultimap;
+import static dagger.internal.codegen.DaggerStreams.instancesOf;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSetMultimap;
 
+import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.graph.EndpointPair;
@@ -46,8 +48,8 @@
  *   <li>an entire component hierarchy rooted at a {@link dagger.Component} or {@link
  *       dagger.producers.ProductionComponent}
  *   <li>a partial component hierarchy rooted at a {@link dagger.Subcomponent} or {@link
- *       dagger.producers.ProductionSubcomponent} (only when the value of {@code
- *       -Adagger.fullBindingGraphValidation} is not {@code NONE})
+ *       dagger.producers.ProductionSubcomponent} (only when {@code
+ *       -Adagger.experimentalAheadOfTimeSubcomponents=enabled} is passed to the compiler)
  *   <li>the bindings installed by a {@link Module} or {@link dagger.producers.ProducerModule},
  *       including all subcomponents generated by {@link Module#subcomponents()} ()} and {@link
  *       dagger.producers.ProducerModule#subcomponents()} ()}
@@ -86,12 +88,20 @@
  *
  * <p><b>Note that this API is experimental and will change.</b>
  */
+@AutoValue
 public abstract class BindingGraph {
+
+  static BindingGraph create(Network<Node, Edge> network, boolean isFullBindingGraph) {
+    return new AutoValue_BindingGraph(ImmutableNetwork.copyOf(network), isFullBindingGraph);
+  }
+
+  BindingGraph() {}
+
   /** Returns the graph in its {@link Network} representation. */
   public abstract ImmutableNetwork<Node, Edge> network();
 
   @Override
-  public String toString() {
+  public final String toString() {
     return network().toString();
   }
 
@@ -105,7 +115,7 @@
    *     full binding graphs for components and subcomponents as well as modules.
    */
   @Deprecated
-  public boolean isModuleBindingGraph() {
+  public final boolean isModuleBindingGraph() {
     return !rootComponentNode().isRealComponent();
   }
 
@@ -121,54 +131,54 @@
 
   /**
    * Returns {@code true} if the {@link #rootComponentNode()} is a subcomponent. This occurs in
-   * when {@code -Adagger.fullBindingGraphValidation} is used in a compilation with a subcomponent.
+   * ahead-of-time-subcomponents mode.
    *
    * @deprecated use {@link ComponentNode#isSubcomponent() rootComponentNode().isSubcomponent()}
    *     instead
    */
   @Deprecated
-  public boolean isPartialBindingGraph() {
+  public final boolean isPartialBindingGraph() {
     return rootComponentNode().isSubcomponent();
   }
 
   /** Returns the bindings. */
-  public ImmutableSet<Binding> bindings() {
+  public final ImmutableSet<Binding> bindings() {
     return nodes(Binding.class);
   }
 
   /** Returns the bindings for a key. */
-  public ImmutableSet<Binding> bindings(Key key) {
+  public final ImmutableSet<Binding> bindings(Key key) {
     return nodes(Binding.class).stream()
         .filter(binding -> binding.key().equals(key))
         .collect(toImmutableSet());
   }
 
   /** Returns the nodes that represent missing bindings. */
-  public ImmutableSet<MissingBinding> missingBindings() {
+  public final ImmutableSet<MissingBinding> missingBindings() {
     return nodes(MissingBinding.class);
   }
 
   /** Returns the component nodes. */
-  public ImmutableSet<ComponentNode> componentNodes() {
+  public final ImmutableSet<ComponentNode> componentNodes() {
     return nodes(ComponentNode.class);
   }
 
   /** Returns the component node for a component. */
-  public Optional<ComponentNode> componentNode(ComponentPath component) {
+  public final Optional<ComponentNode> componentNode(ComponentPath component) {
     return componentNodes().stream()
         .filter(node -> node.componentPath().equals(component))
         .findFirst();
   }
 
   /** Returns the component nodes for a component. */
-  public ImmutableSet<ComponentNode> componentNodes(TypeElement component) {
+  public final ImmutableSet<ComponentNode> componentNodes(TypeElement component) {
     return componentNodes().stream()
         .filter(node -> node.componentPath().currentComponent().equals(component))
         .collect(toImmutableSet());
   }
 
   /** Returns the component node for the root component. */
-  public ComponentNode rootComponentNode() {
+  public final ComponentNode rootComponentNode() {
     return componentNodes().stream()
         .filter(node -> node.componentPath().atRoot())
         .findFirst()
@@ -176,7 +186,7 @@
   }
 
   /** Returns the dependency edges. */
-  public ImmutableSet<DependencyEdge> dependencyEdges() {
+  public final ImmutableSet<DependencyEdge> dependencyEdges() {
     return dependencyEdgeStream().collect(toImmutableSet());
   }
 
@@ -187,14 +197,14 @@
    * have no binding for a key will have an edge whose {@linkplain EndpointPair#target() target
    * node} is a {@link MissingBinding}.
    */
-  public ImmutableSetMultimap<DependencyRequest, DependencyEdge> dependencyEdges(
+  public final ImmutableSetMultimap<DependencyRequest, DependencyEdge> dependencyEdges(
       Binding binding) {
     return dependencyEdgeStream(binding)
         .collect(toImmutableSetMultimap(DependencyEdge::dependencyRequest, edge -> edge));
   }
 
   /** Returns the dependency edges for a dependency request. */
-  public ImmutableSet<DependencyEdge> dependencyEdges(DependencyRequest dependencyRequest) {
+  public final ImmutableSet<DependencyEdge> dependencyEdges(DependencyRequest dependencyRequest) {
     return dependencyEdgeStream()
         .filter(edge -> edge.dependencyRequest().equals(dependencyRequest))
         .collect(toImmutableSet());
@@ -204,7 +214,7 @@
    * Returns the dependency edges for the entry points of a given {@code component}. Each edge's
    * source node is that component's component node.
    */
-  public ImmutableSet<DependencyEdge> entryPointEdges(ComponentPath component) {
+  public final ImmutableSet<DependencyEdge> entryPointEdges(ComponentPath component) {
     return dependencyEdgeStream(componentNode(component).get()).collect(toImmutableSet());
   }
 
@@ -216,12 +226,12 @@
    * Returns the dependency edges for all entry points for all components and subcomponents. Each
    * edge's source node is a component node.
    */
-  public ImmutableSet<DependencyEdge> entryPointEdges() {
+  public final ImmutableSet<DependencyEdge> entryPointEdges() {
     return entryPointEdgeStream().collect(toImmutableSet());
   }
 
   /** Returns the binding or missing binding nodes that directly satisfy entry points. */
-  public ImmutableSet<MaybeBinding> entryPointBindings() {
+  public final ImmutableSet<MaybeBinding> entryPointBindings() {
     return entryPointEdgeStream()
         .map(edge -> (MaybeBinding) network().incidentNodes(edge).target())
         .collect(toImmutableSet());
@@ -231,7 +241,7 @@
    * Returns the edges for entry points that transitively depend on a binding or missing binding for
    * a key.
    */
-  public ImmutableSet<DependencyEdge> entryPointEdgesDependingOnBinding(
+  public final ImmutableSet<DependencyEdge> entryPointEdgesDependingOnBinding(
       MaybeBinding binding) {
     ImmutableNetwork<Node, DependencyEdge> dependencyGraph = dependencyGraph();
     Network<Node, DependencyEdge> subgraphDependingOnBinding =
@@ -241,19 +251,19 @@
   }
 
   /** Returns the bindings that directly request a given binding as a dependency. */
-  public ImmutableSet<Binding> requestingBindings(MaybeBinding binding) {
+  public final ImmutableSet<Binding> requestingBindings(MaybeBinding binding) {
     return network().predecessors(binding).stream()
         .flatMap(instancesOf(Binding.class))
         .collect(toImmutableSet());
   }
 
   /**
-   * Returns the bindings that a given binding directly requests as a dependency. Does not include
+   * Returns the bindings that a given binding directly request as a dependency. Does not include
    * any {@link MissingBinding}s.
    *
    * @see #requestedMaybeMissingBindings(Binding)
    */
-  public ImmutableSet<Binding> requestedBindings(Binding binding) {
+  public final ImmutableSet<Binding> requestedBindings(Binding binding) {
     return network().successors(binding).stream()
         .flatMap(instancesOf(Binding.class))
         .collect(toImmutableSet());
@@ -265,7 +275,7 @@
    *
    * @see #requestedBindings(Binding)
    */
-  public ImmutableSet<MaybeBinding> requestedMaybeMissingBindings(Binding binding) {
+  public final ImmutableSet<MaybeBinding> requestedMaybeMissingBindings(Binding binding) {
     return network().successors(binding).stream()
         .flatMap(instancesOf(MaybeBinding.class))
         .collect(toImmutableSet());
@@ -297,7 +307,8 @@
   private static final ImmutableSet<Class<? extends Node>> NODE_TYPES =
       ImmutableSet.of(Binding.class, MissingBinding.class, ComponentNode.class);
 
-  protected ImmutableSetMultimap<Class<? extends Node>, ? extends Node> nodesByClass() {
+  @Memoized
+  ImmutableSetMultimap<Class<? extends Node>, ? extends Node> nodesByClass() {
     return network().nodes().stream()
         .collect(
             toImmutableSetMultimap(
@@ -391,26 +402,37 @@
   }
 
   /** A node in the binding graph that represents a missing binding for a key in a component. */
+  @AutoValue
   public abstract static class MissingBinding implements MaybeBinding {
+    static MissingBinding create(ComponentPath component, Key key) {
+      return new AutoValue_BindingGraph_MissingBinding(component, key);
+    }
+
     /** The component in which the binding is missing. */
     @Override
     public abstract ComponentPath componentPath();
 
     /** The key for which there is no binding. */
-    @Override
     public abstract Key key();
 
     /** @deprecated This always returns {@code Optional.empty()}. */
     @Override
     @Deprecated
-    public Optional<Binding> binding() {
+    public final Optional<Binding> binding() {
       return Optional.empty();
     }
 
     @Override
-    public String toString() {
+    public final String toString() {
       return String.format("missing binding for %s in %s", key(), componentPath());
     }
+
+    @Memoized
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public abstract boolean equals(Object o);
   }
 
   /**
diff --git a/java/dagger/model/BindingGraphProxies.java b/java/dagger/model/BindingGraphProxies.java
index 85d4df8..c450475 100644
--- a/java/dagger/model/BindingGraphProxies.java
+++ b/java/dagger/model/BindingGraphProxies.java
@@ -16,10 +16,6 @@
 
 package dagger.model;
 
-import com.google.auto.value.AutoValue;
-import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.graph.ImmutableNetwork;
 import com.google.common.graph.Network;
 import dagger.model.BindingGraph.Edge;
 import dagger.model.BindingGraph.MissingBinding;
@@ -31,35 +27,14 @@
  * API.</em>
  */
 public final class BindingGraphProxies {
-
-  @AutoValue
-  abstract static class BindingGraphImpl extends BindingGraph {
-    @Override
-    @Memoized
-    public ImmutableSetMultimap<Class<? extends Node>, ? extends Node> nodesByClass() {
-      return super.nodesByClass();
-    }
-  }
-
-  @AutoValue
-  abstract static class MissingBindingImpl extends MissingBinding {
-    @Memoized
-    @Override
-    public abstract int hashCode();
-
-    @Override
-    public abstract boolean equals(Object o);
-  }
-
   /** Creates a new {@link BindingGraph}. */
   public static BindingGraph bindingGraph(Network<Node, Edge> network, boolean isFullBindingGraph) {
-    return new AutoValue_BindingGraphProxies_BindingGraphImpl(
-        ImmutableNetwork.copyOf(network), isFullBindingGraph);
+    return BindingGraph.create(network, isFullBindingGraph);
   }
 
   /** Creates a new {@link MissingBinding}. */
   public static MissingBinding missingBindingNode(ComponentPath component, Key key) {
-    return new AutoValue_BindingGraphProxies_MissingBindingImpl(component, key);
+    return MissingBinding.create(component, key);
   }
 
   private BindingGraphProxies() {}
diff --git a/java/dagger/model/BindingKind.java b/java/dagger/model/BindingKind.java
index 9bef8fc..20d7b42 100644
--- a/java/dagger/model/BindingKind.java
+++ b/java/dagger/model/BindingKind.java
@@ -25,15 +25,6 @@
   PROVISION,
 
   /**
-   * A binding for an {@link javax.inject.Inject}-annotated constructor that contains at least one
-   * {@link dagger.assisted.Assisted}-annotated parameter.
-   */
-  ASSISTED_INJECTION,
-
-  /** A binding for an {@link dagger.assisted.AssistedFactory}-annotated type. */
-  ASSISTED_FACTORY,
-
-  /**
    * An implicit binding for a {@link dagger.Component}- or {@link
    * dagger.producers.ProductionComponent}-annotated type.
    */
diff --git a/java/dagger/model/testing/BUILD b/java/dagger/model/testing/BUILD
index 9c9f44a..a9d5f19 100644
--- a/java/dagger/model/testing/BUILD
+++ b/java/dagger/model/testing/BUILD
@@ -15,27 +15,25 @@
 # Description:
 #   Test utilities for the Dagger model
 
-load("@rules_java//java:defs.bzl", "java_library")
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
     "DOCLINT_REFERENCES",
 )
 
-package(default_visibility = ["//:src"])
-
 java_library(
     name = "testing",
     testonly = 1,
     srcs = glob(["*.java"]),
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     deps = [
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/spi",
+        "//java/dagger/internal/codegen:jdk-and-guava-extras",
+        "//java/dagger/model",
         "@google_bazel_common//third_party/java/auto:value",
         "@google_bazel_common//third_party/java/checker_framework_annotations",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/truth",
     ],
 )
diff --git a/java/dagger/model/testing/BindingGraphSubject.java b/java/dagger/model/testing/BindingGraphSubject.java
index 2f032cd..dc17c1d 100644
--- a/java/dagger/model/testing/BindingGraphSubject.java
+++ b/java/dagger/model/testing/BindingGraphSubject.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.common.truth.Truth.assertAbout;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.truth.FailureMetadata;
@@ -29,7 +29,7 @@
 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
 
 /** A Truth subject for making assertions on a {@link BindingGraph}. */
-public final class BindingGraphSubject extends Subject {
+public final class BindingGraphSubject extends Subject<BindingGraphSubject, BindingGraph> {
 
   /** Starts a fluent assertion about a {@link BindingGraph}. */
   public static BindingGraphSubject assertThat(BindingGraph bindingGraph) {
@@ -107,7 +107,7 @@
   }
 
   /** A Truth subject for a {@link Binding}. */
-  public final class BindingSubject extends Subject {
+  public final class BindingSubject extends Subject<BindingSubject, Binding> {
 
     private final Binding actual;
 
diff --git a/java/dagger/producers/BUILD b/java/dagger/producers/BUILD
index 41762e6..ad065a1 100644
--- a/java/dagger/producers/BUILD
+++ b/java/dagger/producers/BUILD
@@ -15,17 +15,15 @@
 # Description:
 #   An asynchronous dependency injection system that extends JSR-330.
 
-load("@rules_java//java:defs.bzl", "java_library")
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
     "DOCLINT_REFERENCES",
-    "POM_VERSION",
     "SOURCE_7_TARGET_7",
 )
-load("//tools:maven.bzl", "gen_maven_artifact")
-
-package(default_visibility = ["//:src"])
+load("//tools:maven.bzl", "pom_file", "POM_VERSION")
 
 # Work around b/70476182 which prevents Kythe from connecting :producers to the .java files it
 # contains.
@@ -42,38 +40,35 @@
     javacopts = SOURCE_7_TARGET_7 + DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     tags = ["maven_coordinates=com.google.dagger:dagger-producers:" + POM_VERSION],
     exports = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:concurrent",
+        # TODO(dpb): Don't export any of Guava.
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/jsr330_inject",
     ],
     deps = [
         "//java/dagger:core",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
         "@google_bazel_common//third_party/java/checker_framework_annotations",
         "@google_bazel_common//third_party/java/error_prone:annotations",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/jsr330_inject",
     ],
 )
 
-gen_maven_artifact(
-    name = "artifact",
-    artifact_coordinates = "com.google.dagger:dagger-producers:" + POM_VERSION,
+pom_file(
+    name = "pom",
+    artifact_id = "dagger-producers",
     artifact_name = "Dagger Producers",
-    artifact_target = ":producers",
-    artifact_target_maven_deps = [
-        "com.google.dagger:dagger",
-        "com.google.guava:failureaccess",
-        "com.google.guava:guava",  # TODO(bcorso): Remove guava dependency and ban it?
-        "javax.inject:javax.inject",
-        "org.checkerframework:checker-compat-qual",
-    ],
-    javadoc_exclude_packages = [
+    targets = [":producers"],
+)
+
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+
+javadoc_library(
+    name = "producers-javadoc",
+    srcs = SRCS,
+    exclude_packages = [
         "dagger.producers.internal",
         "dagger.producers.monitoring.internal",
     ],
-    javadoc_root_packages = ["dagger.producers"],
-    javadoc_srcs = SRCS,
-    # TODO(bcorso): Look more into why auto/common shading isn't needed here.
+    root_packages = ["dagger.producers"],
+    deps = [":producers"],
 )
diff --git a/java/dagger/producers/internal/MissingBindingProducer.java b/java/dagger/producers/internal/MissingBindingProducer.java
new file mode 100644
index 0000000..5721569
--- /dev/null
+++ b/java/dagger/producers/internal/MissingBindingProducer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.producers.internal;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import dagger.producers.Producer;
+
+/**
+ * A {@link Producer} that always throws on calls to {@link Producer#get()}. This is necessary in
+ * ahead-of-time subcomponents mode, where modifiable binding methods need to return a {@code
+ * Producer<T>} to a framework instance initialization that is pruned and no longer in the binding
+ * graph, but was present in a superclass implementation. This class fulfills that requirement but
+ * is still practically unusable.
+ */
+public final class MissingBindingProducer<T> extends AbstractProducer<T> {
+  private static final MissingBindingProducer<Object> INSTANCE = new MissingBindingProducer<>();
+
+  private MissingBindingProducer() {}
+
+  @SuppressWarnings({"unchecked", "rawtypes"}) // safe covariant cast
+  public static <T> Producer<T> create() {
+    return (Producer) INSTANCE;
+  }
+
+  @Override
+  protected ListenableFuture<T> compute() {
+    throw new AssertionError(
+        "This binding is not part of the final binding graph. The key was requested by a binding "
+            + "that was believed to possibly be part of the graph, but is no longer requested. "
+            + "If this exception is thrown, it is the result of a Dagger bug.");
+  }
+}
diff --git a/java/dagger/producers/monitoring/TimingProducerMonitor.java b/java/dagger/producers/monitoring/TimingProducerMonitor.java
index ebb90cf..c63e108 100644
--- a/java/dagger/producers/monitoring/TimingProducerMonitor.java
+++ b/java/dagger/producers/monitoring/TimingProducerMonitor.java
@@ -25,7 +25,6 @@
  * A monitor that measures the timing of the execution of a producer method, and logs those timings
  * with the given recorder.
  */
-@SuppressWarnings("GoodTime") // should use java.time.Duration
 final class TimingProducerMonitor extends ProducerMonitor {
   private final ProducerTimingRecorder recorder;
   private final Stopwatch stopwatch;
diff --git a/java/dagger/producers/monitoring/TimingRecorders.java b/java/dagger/producers/monitoring/TimingRecorders.java
index be89319..5fbe3e3 100644
--- a/java/dagger/producers/monitoring/TimingRecorders.java
+++ b/java/dagger/producers/monitoring/TimingRecorders.java
@@ -30,7 +30,6 @@
  */
 // TODO(beder): Reduce the visibility of this class to package-private.
 @Beta
-@SuppressWarnings("GoodTime") // Should be using java.time.Instant/Duration as opposed to nanos
 public final class TimingRecorders {
   private static final Logger logger = Logger.getLogger(TimingRecorders.class.getName());
 
diff --git a/java/dagger/spi/BUILD b/java/dagger/spi/BUILD
index cbec465..9c04582 100644
--- a/java/dagger/spi/BUILD
+++ b/java/dagger/spi/BUILD
@@ -15,67 +15,42 @@
 # Description:
 #   The Service Provider Interface for Dagger's binding graph model
 
-load("@rules_java//java:defs.bzl", "java_library")
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
     "DOCLINT_REFERENCES",
-    "POM_VERSION",
 )
-load("//tools:maven.bzl", "gen_maven_artifact")
-
-package(default_visibility = ["//:src"])
 
 filegroup(
     name = "spi-srcs",
-    srcs = glob(["*.java"]) + [
-        "//java/dagger/model:model-srcs",
-    ],
+    srcs = glob(["*.java"]),
 )
 
+load("//tools:maven.bzl", "POM_VERSION", "pom_file")
+
 java_library(
     name = "spi",
-    srcs = glob(["*.java"]),
+    srcs = [":spi-srcs"],
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     tags = ["maven_coordinates=com.google.dagger:dagger-spi:" + POM_VERSION],
-    exports = [
-        "//java/dagger/model",
-    ],
     deps = [
         "//java/dagger:core",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
         "//java/dagger/model",
         "@google_bazel_common//third_party/java/auto:value",
         "@google_bazel_common//third_party/java/error_prone:annotations",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/jsr330_inject",
     ],
 )
 
-gen_maven_artifact(
-    name = "artifact",
-    artifact_coordinates = "com.google.dagger:dagger-spi:" + POM_VERSION,
+pom_file(
+    name = "pom",
+    artifact_id = "dagger-spi",
     artifact_name = "Dagger SPI",
-    artifact_target = ":spi",
-    artifact_target_libs = [
-        "//java/dagger/internal/codegen/extension",
+    targets = [
         "//java/dagger/model",
+        ":spi",
     ],
-    artifact_target_maven_deps = [
-        "com.google.auto:auto-common",
-        "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger-producers",
-        "com.google.dagger:dagger",
-        "com.google.guava:failureaccess",
-        "com.google.guava:guava",
-        "com.squareup:javapoet",
-        "javax.inject:javax.inject",
-    ],
-    javadoc_root_packages = [
-        "dagger.model",
-        "dagger.spi",
-    ],
-    javadoc_srcs = [":spi-srcs"],
-    shaded_deps = ["@maven//:com_google_auto_auto_common"],
-    shaded_rules = ["rule com.google.auto.common.** dagger.spi.shaded.auto.common.@1"],
 )
diff --git a/java/dagger/testing/compile/BUILD b/java/dagger/testing/compile/BUILD
deleted file mode 100644
index 20e6a3d..0000000
--- a/java/dagger/testing/compile/BUILD
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Helpers class for java compiler tests.
-
-load("@rules_java//java:defs.bzl", "java_library")
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "compile",
-    testonly = 1,
-    srcs = ["CompilerTests.java"],
-    deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:io",
-        "@google_bazel_common//third_party/java/compile_testing",
-    ],
-)
diff --git a/java/dagger/testing/compile/CompilerTests.java b/java/dagger/testing/compile/CompilerTests.java
deleted file mode 100644
index 6750d0c..0000000
--- a/java/dagger/testing/compile/CompilerTests.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing.compile;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static com.google.common.collect.MoreCollectors.onlyElement;
-import static com.google.common.collect.Streams.stream;
-import static com.google.testing.compile.Compiler.javac;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.io.Files;
-import com.google.testing.compile.Compiler;
-import java.io.File;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Map;
-import java.util.NoSuchElementException;
-
-/**
- * A helper class for working with java compiler tests.
- */
-public final class CompilerTests {
-  private CompilerTests() {}
-
-  /** Returns the {@plainlink File jar file} containing the compiler deps. */
-  public static File compilerDepsJar() {
-    try {
-      return stream(Files.fileTraverser().breadthFirst(getRunfilesDir()))
-          .filter(file -> file.getName().endsWith("_compiler_deps_deploy.jar"))
-          .collect(onlyElement());
-    } catch (NoSuchElementException e) {
-      throw new IllegalStateException(
-          "No compiler deps jar found. Are you using the Dagger compiler_test macro?", e);
-    }
-  }
-
-  /** Returns a {@link Compiler} with the compiler deps jar added to the class path. */
-  public static Compiler compiler() {
-    return javac().withClasspath(ImmutableList.of(compilerDepsJar()));
-  }
-
-  private static File getRunfilesDir() {
-    return getRunfilesPath().toFile();
-  }
-
-  private static Path getRunfilesPath() {
-    Path propPath = getRunfilesPath(System.getProperties());
-    if (propPath != null) {
-      return propPath;
-    }
-
-    Path envPath = getRunfilesPath(System.getenv());
-    if (envPath != null) {
-      return envPath;
-    }
-
-    Path cwd = Paths.get("").toAbsolutePath();
-    return cwd.getParent();
-  }
-
-  private static Path getRunfilesPath(Map<?, ?> map) {
-    String runfilesPath = (String) map.get("TEST_SRCDIR");
-    return isNullOrEmpty(runfilesPath) ? null : Paths.get(runfilesPath);
-  }
-}
diff --git a/java/dagger/testing/compile/macros.bzl b/java/dagger/testing/compile/macros.bzl
deleted file mode 100644
index 9543e0e..0000000
--- a/java/dagger/testing/compile/macros.bzl
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (C) 2020 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.
-
-"""Macros for building compiler tests."""
-
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
-
-def compiler_test(name, size = "large", compiler_deps = None, **kwargs):
-    """Generates a java_test that tests java compilation with the given compiler deps.
-
-    This macro separates the compiler dependencies from the test dependencies to avoid
-    1-version violations. For example, this often happens when the java_test uses java
-    dependencies but the compiler test expects the android version of the dependencies.
-
-    Args:
-      name: The name of the java_test.
-      size: The size of the test (default "large" since this test does disk I/O).
-      compiler_deps: The deps needed during compilation.
-      **kwargs: The parameters to pass to the generated java_test.
-
-    Returns:
-      None
-    """
-
-    # This JAR is loaded at runtime and contains the dependencies used by the compiler during tests.
-    # We separate these dependencies from the java_test dependencies to avoid 1 version violations.
-    native.java_binary(
-        name = name + "_compiler_deps",
-        testonly = 1,
-        tags = ["notap"],
-        visibility = ["//visibility:private"],
-        main_class = "Object.class",
-        runtime_deps = compiler_deps,
-    )
-
-    # Add the compiler deps jar, generated above, to the test's data.
-    kwargs["data"] = kwargs.get("data", []) + [name + "_compiler_deps_deploy.jar"]
-
-    # Need to check for srcs since for Kotlin tests we use a runtime dep on the kt_jvm_library
-    # target. We don't need to worry about adding a compile testing dep since kt_compiler_test
-    # adds that in the kt_jvm_library. Adding this dep automatically is merely a convenience
-    # for cases with srcs anyway.
-    if kwargs.get("srcs", None):
-        # Add a dep to allow usage of CompilerTests.
-        kwargs["deps"] = kwargs.get("deps", []) + ["//java/dagger/testing/compile"]
-
-    native.java_test(name = name, size = size, **kwargs)
-
-def kt_compiler_test(name, srcs = [], deps = [], **kwargs):
-    """Generates a java_test that tests java compilation with the given compiler deps.
-
-    This macro works the same as the above compiler_test, but for Kotlin sources.
-
-    Args:
-      name: The name of the java_test.
-      srcs: Source files for the test (typically should include Kotlin sources). If no
-            sources are needed, just use compiler_test with runtime_deps.
-      deps: Deps for compiling the files in srcs.
-      **kwargs: The parameters to pass to compiler_test
-
-    Returns:
-      None
-    """
-    kt_jvm_library(
-        name = name + "_ktlib",
-        testonly = 1,
-        srcs = srcs,
-        deps = deps + ["//java/dagger/testing/compile"],
-        visibility = ["//visibility:private"],
-    )
-
-    compiler_test(
-        name = name,
-        runtime_deps = [
-            ":" + name + "_ktlib",
-        ],
-        **kwargs
-    )
diff --git a/javatests/artifacts/BUILD b/javatests/artifacts/BUILD
deleted file mode 100644
index 9b282de..0000000
--- a/javatests/artifacts/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   This package contains gradle tests of the LOCAL-SNAPSHOT artifacts.
-
-package(default_visibility = ["//:src"])
diff --git a/javatests/artifacts/dagger-android/simple/app/build.gradle b/javatests/artifacts/dagger-android/simple/app/build.gradle
deleted file mode 100644
index 20a3734..0000000
--- a/javatests/artifacts/dagger-android/simple/app/build.gradle
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-apply plugin: 'com.android.application'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        applicationId "dagger.android.simple"
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-    testOptions {
-        unitTests.includeAndroidResources = true
-    }
-    sourceSets {
-        String sharedTestDir = 'src/sharedTest/java'
-        test {
-            java.srcDirs += sharedTestDir
-        }
-        androidTest {
-            java.srcDirs += sharedTestDir
-        }
-    }
-}
-
-dependencies {
-  implementation 'androidx.appcompat:appcompat:1.2.0'
-  implementation 'com.google.dagger:dagger:LOCAL-SNAPSHOT'
-  implementation 'com.google.dagger:dagger-android-support:LOCAL-SNAPSHOT'
-  annotationProcessor 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
-  annotationProcessor 'com.google.dagger:dagger-android-processor:LOCAL-SNAPSHOT'
-
-  testImplementation 'com.google.truth:truth:1.0.1'
-  testImplementation 'org.robolectric:robolectric:4.5-alpha-3'
-  testImplementation 'androidx.core:core:1.3.2'
-  testImplementation 'androidx.test.ext:junit:1.1.2'
-  testImplementation 'androidx.test:runner:1.3.0'
-  testImplementation 'androidx.test.espresso:espresso-core:3.3.0'
-  testImplementation 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
-  testAnnotationProcessor 'com.google.dagger:dagger-android-processor:LOCAL-SNAPSHOT'
-
-  androidTestImplementation 'com.google.truth:truth:1.0.1'
-  androidTestImplementation 'androidx.test.ext:junit:1.1.2'
-  androidTestImplementation 'androidx.test:runner:1.3.0'
-  androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
-  androidTestImplementation 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
-  androidTestAnnotationProcessor 'com.google.dagger:dagger-android-processor:LOCAL-SNAPSHOT'
-
-  // To help us catch usages of Guava APIs for Java 8 in the '-jre' variant.
-  annotationProcessor'com.google.guava:guava:28.1-android'
-  testAnnotationProcessor'com.google.guava:guava:28.1-android'
-  androidTestAnnotationProcessor'com.google.guava:guava:28.1-android'
-}
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/AndroidManifest.xml b/javatests/artifacts/dagger-android/simple/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 0f765b5..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="dagger.android.simple">
-
-  <application
-    android:name=".SimpleApplication"
-    android:label="@string/appName"
-    android:theme="@style/Theme.AppCompat.Light">
-    <activity android:name=".SimpleActivity" android:exported="true">
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN" />
-        <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
-    </activity>
-  </application>
-</manifest>
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/Model.java b/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/Model.java
deleted file mode 100644
index d74a501..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/Model.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.simple;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifies bindings relating to {@link android.os.Build#MODEL}. */
-@Qualifier
-@Retention(RUNTIME)
-@Documented
-@interface Model {}
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/ModelModule.java b/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/ModelModule.java
deleted file mode 100644
index 5e04071..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/ModelModule.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.simple;
-
-import static android.os.Build.MODEL;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-final class ModelModule {
-  @Provides
-  @Model
-  static String provideModel() {
-    return MODEL;
-  }
-}
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/SimpleActivity.java b/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/SimpleActivity.java
deleted file mode 100644
index 39a88e3..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/SimpleActivity.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.simple;
-
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.TextView;
-import dagger.Binds;
-import dagger.Module;
-import dagger.Subcomponent;
-import dagger.android.AndroidInjector;
-import dagger.android.support.DaggerAppCompatActivity;
-import dagger.multibindings.ClassKey;
-import dagger.multibindings.IntoMap;
-import javax.inject.Inject;
-
-/**
- * The main activity of the application.
- *
- * <p>It can be injected with any binding from both {@link SimpleActivityComponent} and {@link
- * SimpleApplication.SimpleComponent}.
- */
-public class SimpleActivity extends DaggerAppCompatActivity {
-  @Subcomponent
-  interface SimpleActivityComponent extends AndroidInjector<SimpleActivity> {
-
-    @Subcomponent.Factory
-    interface Factory extends AndroidInjector.Factory<SimpleActivity> {}
-  }
-
-  @Module(
-      subcomponents = SimpleActivityComponent.class,
-      includes = UserNameModule.class
-  )
-  abstract static class InjectorModule {
-
-    @Binds
-    @IntoMap
-    @ClassKey(SimpleActivity.class)
-    abstract AndroidInjector.Factory<?> bind(SimpleActivityComponent.Factory factory);
-  }
-
-  private static final String TAG = SimpleActivity.class.getSimpleName();
-
-  @Inject @UserName String userName;
-  @Inject @Model String model;
-
-  @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    Log.i(TAG, "Injected with userName and model: " + userName + ", " + model);
-
-    setContentView(R.layout.activity_main);
-
-    TextView greeting = (TextView) findViewById(R.id.greeting);
-    String text = getResources().getString(R.string.welcome, userName, model);
-    greeting.setText(text);
-  }
-}
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/SimpleApplication.java b/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/SimpleApplication.java
deleted file mode 100644
index dcc7bcb..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/SimpleApplication.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.simple;
-
-import android.util.Log;
-import dagger.Component;
-import dagger.android.AndroidInjectionModule;
-import dagger.android.AndroidInjector;
-import dagger.android.DaggerApplication;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/**
- * A simple, skeletal application that demonstrates a dependency-injected application using the
- * utilities in {@code dagger.android}.
- */
-public class SimpleApplication extends DaggerApplication {
-  private static final String TAG = SimpleApplication.class.getSimpleName();
-
-  @Singleton
-  @Component(
-      modules = {
-        AndroidInjectionModule.class,
-        SimpleActivity.InjectorModule.class,
-        ModelModule.class
-      }
-  )
-  interface SimpleComponent extends AndroidInjector<SimpleApplication> {
-    @Component.Factory
-    interface Factory extends AndroidInjector.Factory<SimpleApplication> {}
-  }
-
-  @Inject @Model String model;
-
-  @Override
-  public void onCreate() {
-    super.onCreate();
-    Log.i(TAG, "Injected with model: " + model);
-  }
-
-  @Override
-  protected AndroidInjector<SimpleApplication> applicationInjector() {
-    return DaggerSimpleApplication_SimpleComponent.factory().create(this);
-  }
-}
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/UserName.java b/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/UserName.java
deleted file mode 100644
index 2f861b1..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/UserName.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.simple;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifies bindings relating to the user name. */
-@Qualifier
-@Retention(RUNTIME)
-@Documented
-@interface UserName {}
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/UserNameModule.java b/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/UserNameModule.java
deleted file mode 100644
index d6bc0ac..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/java/dagger/android/simple/UserNameModule.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.simple;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-final class UserNameModule {
-  @UserName
-  @Provides
-  static String provideUserName() {
-    return "ProdUser";
-  }
-
-  private UserNameModule() {}
-}
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/res/layout/activity_main.xml b/javatests/artifacts/dagger-android/simple/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index 3cecc4c..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:background="@android:color/background_light">
-
-  <TextView
-    android:id="@+id/greeting"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_alignParentTop="true"
-    android:textColor="@android:color/primary_text_light"
-    />
-</RelativeLayout>
diff --git a/javatests/artifacts/dagger-android/simple/app/src/main/res/values/strings.xml b/javatests/artifacts/dagger-android/simple/app/src/main/res/values/strings.xml
deleted file mode 100644
index 579f478..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<resources>
-  <!--The app name [CHAR_LIMIT=25]-->
-  <string name="appName">Simple Dagger Android</string>
-
-  <!--The greeting message [CHAR_LIMIT=100]-->
-  <string name="welcome">Hello, %1$s! You are on build %2$s.</string>
-</resources>
diff --git a/javatests/artifacts/dagger-android/simple/app/src/sharedTest/java/dagger/android/simple/SimpleActivityTest.java b/javatests/artifacts/dagger-android/simple/app/src/sharedTest/java/dagger/android/simple/SimpleActivityTest.java
deleted file mode 100644
index 024da5c..0000000
--- a/javatests/artifacts/dagger-android/simple/app/src/sharedTest/java/dagger/android/simple/SimpleActivityTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 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.android.simple;
-
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.Build;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-/** A simple test using dagger-android that can be run with instrumentation or Robolectric tests. */
-@RunWith(AndroidJUnit4.class)
-// Robolectric requires Java9 to run API 29 and above, so use API 28 instead
-@Config(sdk = Build.VERSION_CODES.P)
-public final class SimpleActivityTest {
-
-  @Test
-  public void testActivityInject() throws Exception {
-    try (ActivityScenario<SimpleActivity> scenario =
-        ActivityScenario.launch(SimpleActivity.class)) {
-      scenario.onActivity(
-          activity -> {
-            onView(withId(R.id.greeting))
-                .check(matches(withText("Hello, ProdUser! You are on build robolectric.")));
-          });
-    }
-  }
-
-  @Test
-  public void verifyApplicationInstance() {
-    assertThat((Context) ApplicationProvider.getApplicationContext())
-        .isInstanceOf(SimpleApplication.class);
-  }
-}
diff --git a/javatests/artifacts/dagger-android/simple/build.gradle b/javatests/artifacts/dagger-android/simple/build.gradle
deleted file mode 100644
index 8c179e5..0000000
--- a/javatests/artifacts/dagger-android/simple/build.gradle
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-buildscript {
-    ext {
-        agp_version = System.getenv('AGP_VERSION') ?: "4.2.0-beta04"
-    }
-    repositories {
-        google()
-        jcenter()
-    }
-    dependencies {
-        classpath "com.android.tools.build:gradle:$agp_version"
-    }
-}
-
-allprojects {
-    repositories {
-      google()
-      jcenter()
-      mavenCentral()
-      mavenLocal()
-    }
-}
-
diff --git a/javatests/artifacts/dagger-android/simple/gradle.properties b/javatests/artifacts/dagger-android/simple/gradle.properties
deleted file mode 100644
index 2d8d1e4..0000000
--- a/javatests/artifacts/dagger-android/simple/gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-android.useAndroidX=true
\ No newline at end of file
diff --git a/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/dagger-android/simple/gradlew b/javatests/artifacts/dagger-android/simple/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/javatests/artifacts/dagger-android/simple/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/dagger-android/simple/settings.gradle b/javatests/artifacts/dagger-android/simple/settings.gradle
deleted file mode 100644
index c5a07bc..0000000
--- a/javatests/artifacts/dagger-android/simple/settings.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-include ':app'
-rootProject.name='Simple Dagger Android'
\ No newline at end of file
diff --git a/javatests/artifacts/dagger/simple/build.gradle b/javatests/artifacts/dagger/simple/build.gradle
deleted file mode 100644
index 97c966e..0000000
--- a/javatests/artifacts/dagger/simple/build.gradle
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-plugins {
-  id 'java'
-  id 'application'
-}
-
-repositories {
-  mavenCentral()
-  mavenLocal()
-}
-
-java {
-    // Make sure the generated source is compatible with Java 7.
-    sourceCompatibility = JavaVersion.VERSION_1_7
-}
-
-dependencies {
-  implementation 'com.google.dagger:dagger:LOCAL-SNAPSHOT'
-  annotationProcessor 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
-}
-
-mainClassName = 'dagger.simple.SimpleApplication'
\ No newline at end of file
diff --git a/javatests/artifacts/dagger/simple/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/dagger/simple/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/javatests/artifacts/dagger/simple/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/javatests/artifacts/dagger/simple/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/dagger/simple/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/javatests/artifacts/dagger/simple/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/dagger/simple/gradlew b/javatests/artifacts/dagger/simple/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/javatests/artifacts/dagger/simple/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/dagger/simple/src/main/java/dagger/simple/AssistedInjects.java b/javatests/artifacts/dagger/simple/src/main/java/dagger/simple/AssistedInjects.java
deleted file mode 100644
index eb4946f..0000000
--- a/javatests/artifacts/dagger/simple/src/main/java/dagger/simple/AssistedInjects.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2021 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.simple;
-
-import dagger.Component;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import javax.inject.Inject;
-
-// This is a regression test for https://github.com/google/dagger/issues/2309
-/** A simple, skeletal application that defines an assisted inject binding. */
-public class AssistedInjects {
-  @Component
-  interface MyComponent {
-    FooFactory fooFactory();
-
-    ParameterizedFooFactory<Bar, String> parameterizedFooFactory();
-  }
-
-  static final class Bar {
-    @Inject
-    Bar() {}
-  }
-
-  static class Foo {
-    @AssistedInject
-    Foo(Bar bar, @Assisted String str) {}
-  }
-
-  @AssistedFactory
-  interface FooFactory {
-    Foo create(String str);
-  }
-
-  static class ParameterizedFoo<T1, T2> {
-    @AssistedInject
-    ParameterizedFoo(T1 t1, @Assisted T2 t2) {}
-  }
-
-  @AssistedFactory
-  interface ParameterizedFooFactory<T1, T2> {
-    ParameterizedFoo<T1, T2> create(T2 t2);
-  }
-
-  public static void main(String[] args) {
-    Foo foo = DaggerAssistedInjects_MyComponent.create().fooFactory().create("");
-
-    ParameterizedFoo<Bar, String> parameterizedFoo =
-        DaggerAssistedInjects_MyComponent.create().parameterizedFooFactory().create("");
-  }
-}
diff --git a/javatests/artifacts/dagger/simple/src/main/java/dagger/simple/SimpleApplication.java b/javatests/artifacts/dagger/simple/src/main/java/dagger/simple/SimpleApplication.java
deleted file mode 100644
index f136101..0000000
--- a/javatests/artifacts/dagger/simple/src/main/java/dagger/simple/SimpleApplication.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 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.simple;
-
-import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** A simple, skeletal application that defines a simple component. */
-public class SimpleApplication {
-  static final class Foo {
-    @Inject Foo() {}
-  }
-
-  @Module
-  static final class SimpleModule {
-    @Provides
-    static Foo provideFoo() {
-      return new Foo();
-    }
-  }
-
-  @Singleton
-  @Component(modules = { SimpleModule.class })
-  interface SimpleComponent {
-    Foo foo();
-  }
-
-  public static void main(String[] args) {
-    Foo foo = DaggerSimpleApplication_SimpleComponent.create().foo();
-  }
-}
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/build.gradle b/javatests/artifacts/hilt-android/gradleConfigCache/app/build.gradle
deleted file mode 100644
index 43ccd1d..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/build.gradle
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-kapt'
-apply plugin: 'dagger.hilt.android.plugin'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        applicationId "dagger.hilt.android.gradleConfigCache"
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-        testInstrumentationRunner "dagger.hilt.android.gradleConfigCache.TestRunner"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-    testOptions {
-        unitTests.includeAndroidResources = true
-    }
-}
-
-hilt {
-    enableTransformForLocalTests = true
-}
-
-dependencies {
-    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation 'androidx.appcompat:appcompat:1.2.0'
-    implementation 'androidx.activity:activity-ktx:1.1.0'
-    implementation 'androidx.multidex:multidex:2.0.0'
-    implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-    kapt 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-
-    testImplementation 'junit:junit:4.13'
-    testImplementation 'androidx.test.ext:junit:1.1.2'
-    testImplementation 'androidx.test:runner:1.3.0'
-    testImplementation 'org.robolectric:robolectric:4.5-alpha-3'
-    testImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
-    kaptTest 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-
-    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
-    androidTestImplementation 'androidx.test:runner:1.3.0'
-    androidTestImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
-    kaptAndroidTest 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-}
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/androidTest/java/dagger/hilt/android/gradleConfigCache/EmulatorTest.kt b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/androidTest/java/dagger/hilt/android/gradleConfigCache/EmulatorTest.kt
deleted file mode 100644
index 9099db4..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/androidTest/java/dagger/hilt/android/gradleConfigCache/EmulatorTest.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.gradleConfigCache
-
-import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import org.junit.Assert.assertNotNull
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@HiltAndroidTest
-@RunWith(AndroidJUnit4::class)
-class EmulatorTest {
-
-  @get:Rule
-  val rule = HiltAndroidRule(this)
-
-  @Test
-  fun testFooInjected() {
-    ActivityScenario.launch(MainActivity::class.java).use {
-      it.onActivity { activity ->
-        assertNotNull(activity.foo)
-      }
-    }
-  }
-}
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/androidTest/java/dagger/hilt/android/gradleConfigCache/TestRunner.kt b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/androidTest/java/dagger/hilt/android/gradleConfigCache/TestRunner.kt
deleted file mode 100644
index 9fce7cd..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/androidTest/java/dagger/hilt/android/gradleConfigCache/TestRunner.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.gradleConfigCache
-
-import android.app.Application
-import android.content.Context
-import androidx.test.runner.AndroidJUnitRunner
-import dagger.hilt.android.testing.HiltTestApplication
-
-class TestRunner : AndroidJUnitRunner() {
-  override fun newApplication(cl: ClassLoader, appName: String, context: Context): Application {
-    return super.newApplication(cl, HiltTestApplication::class.java.name, context)
-  }
-}
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/AndroidManifest.xml
deleted file mode 100644
index ce1fb71..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.gradleConfigCache">
-
-    <application
-        android:name=".App"
-        android:allowBackup="true"
-        android:label="@string/app_name"
-        android:supportsRtl="true"
-        android:theme="@style/Theme.AppCompat.Light">
-        <activity android:name=".MainActivity" android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/App.kt b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/App.kt
deleted file mode 100644
index 1cbd4b0..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/App.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.gradleConfigCache
-
-import androidx.multidex.MultiDexApplication
-import dagger.hilt.android.HiltAndroidApp
-
-@HiltAndroidApp
-class App : MultiDexApplication()
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/Foo.kt b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/Foo.kt
deleted file mode 100644
index 969e183..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/Foo.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package dagger.hilt.android.gradleConfigCache
-
-import javax.inject.Inject
-
-class Foo @Inject constructor()
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/MainActivity.kt b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/MainActivity.kt
deleted file mode 100644
index 0011bde..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/java/dagger/hilt/android/gradleConfigCache/MainActivity.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.gradleConfigCache
-
-import android.os.Bundle
-import android.util.Log
-import androidx.appcompat.app.AppCompatActivity
-import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class MainActivity : AppCompatActivity() {
-
-  @Inject
-  lateinit var foo: Foo
-
-  override fun onCreate(savedInstanceState: Bundle?) {
-    super.onCreate(savedInstanceState)
-    setContentView(R.layout.activity_main)
-    Log.d("Hilt", "Foo is $foo")
-  }
-}
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/res/layout/activity_main.xml b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index cb5a8df..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:background="@android:color/background_light">
-</RelativeLayout>
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/res/values/strings.xml b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/res/values/strings.xml
deleted file mode 100644
index 05afdbf..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<resources>
-    <!--The app name [CHAR_LIMIT=40]-->
-    <string name="app_name">Gradle Configuration Cache App</string>
-</resources>
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/test/java/dagger/hilt/android/gradleConfigCache/LocalTest.kt b/javatests/artifacts/hilt-android/gradleConfigCache/app/src/test/java/dagger/hilt/android/gradleConfigCache/LocalTest.kt
deleted file mode 100644
index 527d887..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/app/src/test/java/dagger/hilt/android/gradleConfigCache/LocalTest.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.gradleConfigCache
-
-import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import dagger.hilt.android.testing.HiltTestApplication
-import org.junit.Assert.assertNotNull
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.annotation.Config
-
-@HiltAndroidTest
-@RunWith(AndroidJUnit4::class)
-@Config(application = HiltTestApplication::class)
-class LocalTest {
-
-  @get:Rule
-  val rule = HiltAndroidRule(this)
-
-  @Test
-  fun testFooInjected() {
-    ActivityScenario.launch(MainActivity::class.java).use {
-      it.onActivity { activity ->
-        assertNotNull(activity.foo)
-      }
-    }
-  }
-}
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/build.gradle b/javatests/artifacts/hilt-android/gradleConfigCache/build.gradle
deleted file mode 100644
index 3b0cdde..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/build.gradle
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-buildscript {
-    ext {
-        kotlin_version = '1.4.20'
-        agp_version = "4.2.0-beta04"
-    }
-    repositories {
-        google()
-        jcenter()
-        mavenLocal()
-    }
-    dependencies {
-        classpath "com.android.tools.build:gradle:$agp_version"
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-        classpath 'com.google.dagger:hilt-android-gradle-plugin:LOCAL-SNAPSHOT'
-    }
-}
-
-allprojects {
-    repositories {
-      google()
-      jcenter()
-      mavenCentral()
-      mavenLocal()
-    }
-}
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/gradle.properties b/javatests/artifacts/hilt-android/gradleConfigCache/gradle.properties
deleted file mode 100644
index 1813493..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/gradle.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-android.useAndroidX=true
-android.enableJetifier=true
-
-# Error out if an issue is found that disallows the configuration cache.
-# These options along with this app being built in presubmit helps us cache
-# changes that would cause config cache to be disabled via the HiltGradlePlugin.
-org.gradle.unsafe.configuration-cache=ERROR
-org.gradle.unsafe.configuration-cache.max-problems=0
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/hilt-android/gradleConfigCache/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 62d4c05..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/hilt-android/gradleConfigCache/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/gradlew b/javatests/artifacts/hilt-android/gradleConfigCache/gradlew
deleted file mode 100755
index fbd7c51..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/gradlew
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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
-#
-#      https://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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=`expr $i + 1`
-    done
-    case $i in
-        0) set -- ;;
-        1) set -- "$args0" ;;
-        2) set -- "$args0" "$args1" ;;
-        3) set -- "$args0" "$args1" "$args2" ;;
-        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=`save "$@"`
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/gradlew.bat b/javatests/artifacts/hilt-android/gradleConfigCache/gradlew.bat
deleted file mode 100644
index a9f778a..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/gradlew.bat
+++ /dev/null
@@ -1,104 +0,0 @@
-@rem

-@rem Copyright 2015 the original author or authors.

-@rem

-@rem Licensed under the Apache License, Version 2.0 (the "License");

-@rem you may not use this file except in compliance with the License.

-@rem You may obtain a copy of the License at

-@rem

-@rem      https://www.apache.org/licenses/LICENSE-2.0

-@rem

-@rem Unless required by applicable law or agreed to in writing, software

-@rem distributed under the License is distributed on an "AS IS" BASIS,

-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-@rem See the License for the specific language governing permissions and

-@rem limitations under the License.

-@rem

-

-@if "%DEBUG%" == "" @echo off

-@rem ##########################################################################

-@rem

-@rem  Gradle startup script for Windows

-@rem

-@rem ##########################################################################

-

-@rem Set local scope for the variables with windows NT shell

-if "%OS%"=="Windows_NT" setlocal

-

-set DIRNAME=%~dp0

-if "%DIRNAME%" == "" set DIRNAME=.

-set APP_BASE_NAME=%~n0

-set APP_HOME=%DIRNAME%

-

-@rem Resolve any "." and ".." in APP_HOME to make it shorter.

-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

-

-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

-

-@rem Find java.exe

-if defined JAVA_HOME goto findJavaFromJavaHome

-

-set JAVA_EXE=java.exe

-%JAVA_EXE% -version >NUL 2>&1

-if "%ERRORLEVEL%" == "0" goto init

-

-echo.

-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

-echo.

-echo Please set the JAVA_HOME variable in your environment to match the

-echo location of your Java installation.

-

-goto fail

-

-:findJavaFromJavaHome

-set JAVA_HOME=%JAVA_HOME:"=%

-set JAVA_EXE=%JAVA_HOME%/bin/java.exe

-

-if exist "%JAVA_EXE%" goto init

-

-echo.

-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%

-echo.

-echo Please set the JAVA_HOME variable in your environment to match the

-echo location of your Java installation.

-

-goto fail

-

-:init

-@rem Get command-line arguments, handling Windows variants

-

-if not "%OS%" == "Windows_NT" goto win9xME_args

-

-:win9xME_args

-@rem Slurp the command line arguments.

-set CMD_LINE_ARGS=

-set _SKIP=2

-

-:win9xME_args_slurp

-if "x%~1" == "x" goto execute

-

-set CMD_LINE_ARGS=%*

-

-:execute

-@rem Setup the command line

-

-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

-

-

-@rem Execute Gradle

-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

-

-:end

-@rem End local scope for the variables with windows NT shell

-if "%ERRORLEVEL%"=="0" goto mainEnd

-

-:fail

-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

-rem the _cmd.exe /c_ return code!

-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

-exit /b 1

-

-:mainEnd

-if "%OS%"=="Windows_NT" endlocal

-

-:omega

diff --git a/javatests/artifacts/hilt-android/gradleConfigCache/settings.gradle b/javatests/artifacts/hilt-android/gradleConfigCache/settings.gradle
deleted file mode 100644
index d0d5fee..0000000
--- a/javatests/artifacts/hilt-android/gradleConfigCache/settings.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-rootProject.name='Gradle Configuration Cache App'
-include ':app'
diff --git a/javatests/artifacts/hilt-android/simple/app/build.gradle b/javatests/artifacts/hilt-android/simple/app/build.gradle
deleted file mode 100644
index 98b79e1..0000000
--- a/javatests/artifacts/hilt-android/simple/app/build.gradle
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-apply plugin: 'com.android.application'
-apply plugin: 'dagger.hilt.android.plugin'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        applicationId "dagger.hilt.android.simple"
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-        testInstrumentationRunner "dagger.hilt.android.simple.SimpleEmulatorTestRunner"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-    testOptions {
-        unitTests.includeAndroidResources = true
-    }
-    lintOptions {
-        checkReleaseBuilds = false
-    }
-    sourceSets {
-        String sharedTestDir = 'src/sharedTest/java'
-        test {
-            java.srcDirs += sharedTestDir
-        }
-        androidTest {
-            java.srcDirs += sharedTestDir
-        }
-    }
-}
-
-hilt {
-    enableExperimentalClasspathAggregation = true
-    enableTransformForLocalTests = true
-}
-
-configurations.all {
-    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
-        if ("$dagger_version" == 'LOCAL-SNAPSHOT'
-                && details.requested.group == 'com.google.dagger') {
-            details.useVersion 'LOCAL-SNAPSHOT'
-            details.because 'LOCAL-SNAPSHOT should act as latest version.'
-        }
-    }
-}
-
-dependencies {
-  implementation project(':feature')
-  implementation project(':lib')
-  implementation 'androidx.appcompat:appcompat:1.2.0'
-  implementation "com.google.dagger:hilt-android:$dagger_version"
-  annotationProcessor "com.google.dagger:hilt-compiler:$dagger_version"
-
-  testImplementation 'com.google.truth:truth:1.0.1'
-  testImplementation 'junit:junit:4.13'
-  testImplementation 'org.robolectric:robolectric:4.5-alpha-3'
-  testImplementation 'androidx.core:core:1.3.2'
-  testImplementation 'androidx.test.ext:junit:1.1.2'
-  testImplementation 'androidx.test:runner:1.3.0'
-  testImplementation 'androidx.test.espresso:espresso-core:3.3.0'
-  testImplementation "com.google.dagger:hilt-android-testing:$dagger_version"
-  testAnnotationProcessor "com.google.dagger:hilt-compiler:$dagger_version"
-
-  androidTestImplementation 'com.google.truth:truth:1.0.1'
-  androidTestImplementation 'junit:junit:4.13'
-  androidTestImplementation 'androidx.test.ext:junit:1.1.2'
-  androidTestImplementation 'androidx.test:runner:1.3.0'
-  androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
-  androidTestImplementation "com.google.dagger:hilt-android-testing:$dagger_version"
-  androidTestAnnotationProcessor "com.google.dagger:hilt-compiler:$dagger_version"
-
-  // To help us catch usages of Guava APIs for Java 8 in the '-jre' variant.
-  annotationProcessor'com.google.guava:guava:28.1-android'
-  testAnnotationProcessor'com.google.guava:guava:28.1-android'
-  androidTestAnnotationProcessor'com.google.guava:guava:28.1-android'
-
-  // To help us catch version skew related issues in hilt extensions.
-  // TODO(bcorso): Add examples testing the actual API.
-  implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'
-  implementation 'androidx.hilt:hilt-work:1.0.0-alpha01'
-  annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
-  testAnnotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
-  androidTestAnnotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/androidTest/java/dagger/hilt/android/simple/SimpleEmulatorTestRunner.java b/javatests/artifacts/hilt-android/simple/app/src/androidTest/java/dagger/hilt/android/simple/SimpleEmulatorTestRunner.java
deleted file mode 100644
index 6ee721c..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/androidTest/java/dagger/hilt/android/simple/SimpleEmulatorTestRunner.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import android.app.Application;
-import android.content.Context;
-import androidx.test.runner.AndroidJUnitRunner;
-import dagger.hilt.android.testing.HiltTestApplication;
-
-/** A custom runner to setup the emulator application class for tests. */
-public final class SimpleEmulatorTestRunner extends AndroidJUnitRunner {
-
-  @Override
-  public Application newApplication(ClassLoader cl, String className, Context context)
-      throws ClassNotFoundException, IllegalAccessException, InstantiationException {
-    return super.newApplication(cl, HiltTestApplication.class.getName(), context);
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/debug/AndroidManifest.xml b/javatests/artifacts/hilt-android/simple/app/src/debug/AndroidManifest.xml
deleted file mode 100644
index 14d33b0..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/debug/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="dagger.hilt.android.simple">
-
-  <application>
-    <activity
-        android:name=".Injection1Test$TestActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="false" />
-    <activity
-        android:name=".Injection2Test$TestActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="false"/>
-    <activity
-        android:name=".ActivityScenarioRuleTest$TestActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="false"/>
-  </application>
-</manifest>
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/simple/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 0b12b13..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="dagger.hilt.android.simple">
-
-  <application android:name=".SimpleApplication" android:label="@string/appName">
-    <activity
-        android:name=".SimpleActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="true">
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN" />
-        <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
-    </activity>
-    <activity
-        android:name=".SettingsActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="false">
-    </activity>
-  </application>
-</manifest>
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/Model.java b/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/Model.java
deleted file mode 100644
index 9965b2e..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/Model.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifies bindings relating to {@link android.os.Build#MODEL}. */
-@Qualifier
-@Retention(RUNTIME)
-@Documented
-@interface Model {}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/ModelModule.java b/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/ModelModule.java
deleted file mode 100644
index 9a63f17..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/ModelModule.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static android.os.Build.MODEL;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.components.SingletonComponent;
-
-@Module
-@InstallIn(SingletonComponent.class)
-final class ModelModule {
-  @Provides
-  @Model
-  static String provideModel() {
-    return MODEL;
-  }
-
-  private ModelModule() {}
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/SimpleActivity.java b/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/SimpleActivity.java
deleted file mode 100644
index 5d16cd4..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/SimpleActivity.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.Button;
-import android.widget.TextView;
-import androidx.appcompat.app.AppCompatActivity;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.simple.feature.FeatureActivity;
-import dagger.hilt.android.simple.lib.Thing;
-import javax.inject.Inject;
-
-/** The main activity of the application. */
-@AndroidEntryPoint
-public class SimpleActivity extends AppCompatActivity {
-  private static final String TAG = SimpleActivity.class.getSimpleName();
-
-  @Inject @UserName String userName;
-  @Inject @Model String model;
-  @Inject Thing thing;
-
-  @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    Log.i(TAG, "Injected with userName and model: " + userName + ", " + model);
-
-    setContentView(R.layout.activity_main);
-
-    ((TextView) findViewById(R.id.greeting))
-        .setText(getResources().getString(R.string.welcome, userName, model));
-
-    Button featureButton = (Button) findViewById(R.id.goto_feature);
-    featureButton.setOnClickListener(
-        view -> startActivity(new Intent(this, FeatureActivity.class)));
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/SimpleApplication.java b/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/SimpleApplication.java
deleted file mode 100644
index 3c7d1f3..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/SimpleApplication.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import android.app.Application;
-import android.util.Log;
-import dagger.hilt.android.HiltAndroidApp;
-import javax.inject.Inject;
-
-/**
- * A simple, skeletal application that demonstrates a dependency-injected application using the
- * utilities in {@code Hilt} in Android.
- */
-@HiltAndroidApp
-public class SimpleApplication extends Application {
-  private static final String TAG = SimpleApplication.class.getSimpleName();
-
-  @Inject @Model String model;
-
-  @Override
-  public void onCreate() {
-    super.onCreate();
-    Log.i(TAG, "Injected with model: " + model);
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/UserName.java b/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/UserName.java
deleted file mode 100644
index 19f0679..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/UserName.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-/** Qualifies bindings relating to the user name. */
-@Qualifier
-@Retention(RUNTIME)
-@Documented
-@interface UserName {}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/UserNameModule.java b/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/UserNameModule.java
deleted file mode 100644
index 26d52df..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/java/dagger/hilt/android/simple/UserNameModule.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-
-@Module
-@InstallIn(ActivityComponent.class)
-final class UserNameModule {
-  @UserName
-  @Provides
-  static String provideUserName() {
-    return "ProdUser";
-  }
-
-  private UserNameModule() {}
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/res/layout/activity_main.xml b/javatests/artifacts/hilt-android/simple/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index b786106..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:background="@android:color/background_light">
-
-  <TextView
-    android:id="@+id/greeting"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_alignParentTop="true"
-    android:textColor="@android:color/primary_text_light"
-    />
-
-  <Button
-    android:id="@+id/goto_feature"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_below="@id/greeting"
-    android:text="@string/navigateToFeature"
-    />
-</RelativeLayout>
diff --git a/javatests/artifacts/hilt-android/simple/app/src/main/res/values/strings.xml b/javatests/artifacts/hilt-android/simple/app/src/main/res/values/strings.xml
deleted file mode 100644
index c8f9b8a..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<resources>
-  <!--The app name [CHAR_LIMIT=20]-->
-  <string name="appName">Simple Hilt Android</string>
-
-  <!--The greeting message [CHAR_LIMIT=100]-->
-  <string name="welcome">Hello, %1$s! You are on build %2$s.</string>
-
-  <!--The feature button message [CHAR_LIMIT=100]-->
-  <string name="navigateToFeature">Navigate to a feature!</string>
-</resources>
diff --git a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/ActivityScenarioRuleTest.java b/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/ActivityScenarioRuleTest.java
deleted file mode 100644
index b49e666..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/ActivityScenarioRuleTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static androidx.lifecycle.Lifecycle.State.RESUMED;
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.rules.ActivityScenarioRule;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests that {@link ActivityScenarioRule} works with Hilt tests. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class ActivityScenarioRuleTest {
-  private static final String STR_VALUE = "STR_VALUE";
-
-  /** An activity to test injection. */
-  @AndroidEntryPoint
-  public static final class TestActivity extends AppCompatActivity {
-    @Inject String str;
-  }
-
-  @Rule(order = 0) public HiltAndroidRule hiltRule = new HiltAndroidRule(this);
-
-  @Rule(order = 1)
-  public ActivityScenarioRule<TestActivity> scenarioRule =
-      new ActivityScenarioRule<>(TestActivity.class);
-
-  @BindValue String str = STR_VALUE;
-
-  @Test
-  public void testState() {
-    assertThat(scenarioRule.getScenario().getState()).isEqualTo(RESUMED);
-  }
-
-  @Test
-  public void testInjection() {
-    scenarioRule
-        .getScenario()
-        .onActivity(activity -> assertThat(activity.str).isEqualTo(STR_VALUE));
-  }
-
-
-  @Test
-  public void verifyMainActivity() {
-    try (ActivityScenario<TestActivity> scenario =
-        ActivityScenario.launch(TestActivity.class)) {
-      scenario.onActivity(
-          activity -> {
-            assertThat(activity.getClass().getSuperclass().getSimpleName())
-              .isEqualTo("Hilt_ActivityScenarioRuleTest_TestActivity");
-          }
-      );
-    }
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/BindValueTest.java b/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/BindValueTest.java
deleted file mode 100644
index e77f605..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/BindValueTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.google.common.collect.ImmutableSet;
-import dagger.MapKey;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.testing.BindElementsIntoSet;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.BindValueIntoMap;
-import dagger.hilt.android.testing.BindValueIntoSet;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.components.SingletonComponent;
-import java.util.Map;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** A simple test using Hilt. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class BindValueTest {
-  private static final String BIND_VALUE_STRING = "BIND_VALUE_STRING";
-  private static final String TEST_QUALIFIER = "TEST_QUALIFIER";
-
-  private static final String SET_STRING_1 = "SetString1";
-  private static final String SET_STRING_2 = "SetString2";
-  private static final String SET_STRING_3 = "SetString3";
-
-  private static final String KEY_1 = "Key1";
-  private static final String KEY_2 = "Key2";
-  private static final String VALUE_1 = "Value1";
-  private static final String VALUE_2 = "Value2";
-  private static final String VALUE_3 = "Value3";
-
-  private static final Integer SET_INT_1 = 1;
-  private static final Integer SET_INT_2 = 2;
-  private static final Integer SET_INT_3 = 3;
-
-  @EntryPoint
-  @InstallIn(SingletonComponent.class)
-  interface BindValueEntryPoint {
-    @Named(TEST_QUALIFIER)
-    String bindValueString();
-
-    Set<String> getStringSet();
-  }
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @BindValue
-  @Named(TEST_QUALIFIER)
-  String bindValueString = BIND_VALUE_STRING;
-
-  @BindElementsIntoSet Set<String> bindElementsSet1 = ImmutableSet.of(SET_STRING_1);
-  @BindElementsIntoSet Set<String> bindElementsSet2 = ImmutableSet.of(SET_STRING_2);
-
-  @BindValueIntoMap
-  @MyMapKey(KEY_1)
-  String boundValue1 = VALUE_1;
-
-  @BindValueIntoMap
-  @MyMapKey(KEY_2)
-  String boundValue2 = VALUE_2;
-
-  @BindValueIntoSet Integer bindValueSetInt1 = SET_INT_1;
-  @BindValueIntoSet Integer bindValueSetInt2 = SET_INT_2;
-
-  @Inject Set<String> stringSet;
-  @Inject Provider<Set<String>> providedStringSet;
-  @Inject Provider<Map<String, String>> mapProvider;
-  @Inject Set<Integer> intSet;
-  @Inject Provider<Set<Integer>> providedIntSet;
-
-  @Test
-  public void testBindValueFieldIsProvided() throws Exception {
-    assertThat(bindValueString).isEqualTo(BIND_VALUE_STRING);
-    assertThat(getBinding()).isEqualTo(BIND_VALUE_STRING);
-  }
-
-  @Test
-  public void testBindValueIsMutable() throws Exception {
-    bindValueString = "newValue";
-    assertThat(getBinding()).isEqualTo("newValue");
-  }
-
-  @Test
-  public void testElementsIntoSet() throws Exception {
-    rule.inject();
-    // basic check that initial/default values are properly injected
-    assertThat(providedStringSet.get()).containsExactly(SET_STRING_1, SET_STRING_2);
-    // Test empty sets (something that cannot be done with @BindValueIntoSet)
-    bindElementsSet1 = ImmutableSet.of();
-    bindElementsSet2 = ImmutableSet.of();
-    assertThat(providedStringSet.get()).isEmpty();
-    // Test multiple elements in set.
-    bindElementsSet1 = ImmutableSet.of(SET_STRING_1, SET_STRING_2, SET_STRING_3);
-    assertThat(providedStringSet.get()).containsExactly(SET_STRING_1, SET_STRING_2, SET_STRING_3);
-  }
-
-  @Test
-  public void testBindValueIntoMap() throws Exception {
-    rule.inject();
-    Map<String, String> oldMap = mapProvider.get();
-    assertThat(oldMap).containsExactly(KEY_1, VALUE_1, KEY_2, VALUE_2);
-    boundValue1 = VALUE_3;
-    Map<String, String> newMap = mapProvider.get();
-    assertThat(oldMap).containsExactly(KEY_1, VALUE_1, KEY_2, VALUE_2);
-    assertThat(newMap).containsExactly(KEY_1, VALUE_3, KEY_2, VALUE_2);
-  }
-
-  @Test
-  public void testBindValueIntoSet() throws Exception {
-    rule.inject();
-    // basic check that initial/default values are properly injected
-    assertThat(providedIntSet.get()).containsExactly(SET_INT_1, SET_INT_2);
-    bindValueSetInt1 = SET_INT_3;
-    // change the value for bindValueSetString from 1 to 3
-    assertThat(providedIntSet.get()).containsExactly(SET_INT_2, SET_INT_3);
-  }
-
-  @MapKey
-  @interface MyMapKey {
-    String value();
-  }
-
-  private static String getBinding() {
-    return EntryPoints.get(getApplicationContext(), BindValueEntryPoint.class).bindValueString();
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/DelayComponentReadyTest.java b/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/DelayComponentReadyTest.java
deleted file mode 100644
index 81afb6e..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/DelayComponentReadyTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertThrows;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.android.testing.OnComponentReadyRunner;
-import dagger.hilt.components.SingletonComponent;
-import java.util.concurrent.atomic.AtomicReference;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** A simple test using Hilt. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class DelayComponentReadyTest {
-
-  private static final String EXPECTED_VALUE = "expected";
-
-  @EntryPoint
-  @InstallIn(SingletonComponent.class)
-  public interface FooEntryPoint {
-    String foo();
-  }
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this).delayComponentReady();
-
-  @BindValue String foo;
-
-  @Test
-  public void testLateBindValue() throws Exception {
-    AtomicReference<String> fooRef = new AtomicReference<>();
-    OnComponentReadyRunner.addListener(
-        ApplicationProvider.getApplicationContext(),
-        FooEntryPoint.class,
-        entryPoint -> fooRef.set(entryPoint.foo()));
-
-    // Test that setting the listener before the component is ready doesn't run the listener.
-    assertThat(fooRef.get()).isNull();
-
-    foo = EXPECTED_VALUE;
-    rule.componentReady().inject();
-    assertThat(EntryPoints.get(getApplicationContext(), FooEntryPoint.class).foo())
-        .isEqualTo(EXPECTED_VALUE);
-  }
-
-  @Test
-  public void testUnitializedBindValue_fails() throws Exception {
-    OnComponentReadyRunner.addListener(
-        ApplicationProvider.getApplicationContext(), FooEntryPoint.class, FooEntryPoint::foo);
-
-    // foo not set
-    NullPointerException expected = assertThrows(NullPointerException.class, rule::componentReady);
-    // This is not the best error message, but it is equivalent to the message from a regular
-    // (non-delayed) @BindValue returning null;
-    assertThat(expected)
-        .hasMessageThat()
-        .isEqualTo("Cannot return null from a non-@Nullable @Provides method");
-  }
-
-  @Test
-  public void testDoubleComponentReady_fails() throws Exception {
-    foo = EXPECTED_VALUE;
-    rule.componentReady();
-    IllegalStateException expected =
-        assertThrows(IllegalStateException.class, rule::componentReady);
-    assertThat(expected).hasMessageThat().isEqualTo("Called componentReady() multiple times");
-  }
-
-  @Test
-  public void testMissingComponentReady_fails() throws Exception {
-    // componentReady not called
-    foo = EXPECTED_VALUE;
-    IllegalStateException expected = assertThrows(IllegalStateException.class, rule::inject);
-    assertThat(expected)
-        .hasMessageThat()
-        .isEqualTo("Called inject() before calling componentReady()");
-  }
-
-  @Test
-  public void testDelayComponentReadyAfterStart_fails() throws Exception {
-    IllegalStateException expected =
-        assertThrows(IllegalStateException.class, rule::delayComponentReady);
-    assertThat(expected)
-        .hasMessageThat()
-        .isEqualTo("Called delayComponentReady after test execution started");
-    // Prevents failure due to never calling componentReady()
-    foo = EXPECTED_VALUE;
-    rule.componentReady();
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/Injection1Test.java b/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/Injection1Test.java
deleted file mode 100644
index 6e5ad6a..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/Injection1Test.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.components.SingletonComponent;
-import javax.inject.Inject;
-import javax.inject.Named;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests basic injection APIs, and that bindings don't conflict with {@link Injection2Test}. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class Injection1Test {
-  private static final String APPLICATION_QUALIFIER = "APPLICATION_QUALIFIER";
-  private static final String ACTIVITY_QUALIFIER = "ACTIVITY_QUALIFIER";
-  private static final String APPLICATION_VALUE = "Injection1Test_ApplicationValue";
-  private static final String ACTIVITY_VALUE = "Injection1Test_ActivityValue";
-
-  @Module
-  @InstallIn(SingletonComponent.class)
-  interface TestApplicationModule {
-    @Provides
-    @Named(APPLICATION_QUALIFIER)
-    static String provideString() {
-      return APPLICATION_VALUE;
-    }
-  }
-
-  @Module
-  @InstallIn(ActivityComponent.class)
-  interface TestActivityModule {
-    @Provides
-    @Named(ACTIVITY_QUALIFIER)
-    static String provideString() {
-      return ACTIVITY_VALUE;
-    }
-  }
-
-  /** Test activity used to test activity injection */
-  @AndroidEntryPoint
-  public static final class TestActivity extends AppCompatActivity {
-    @Inject @Named(ACTIVITY_QUALIFIER) String activityValue;
-  }
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @Inject @Named(APPLICATION_QUALIFIER) String applicationValue;
-
-  @Test
-  public void testApplicationInjection() throws Exception {
-    assertThat(applicationValue).isNull();
-    rule.inject();
-    assertThat(applicationValue).isEqualTo(APPLICATION_VALUE);
-  }
-
-  @Test
-  public void testActivityInjection() throws Exception {
-    try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
-      scenario.onActivity(activity -> assertThat(activity.activityValue).isEqualTo(ACTIVITY_VALUE));
-    }
-  }
-
-  @Test
-  public void testSuperClassTransformation() {
-    try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
-      scenario.onActivity(
-          activity ->
-              assertThat(activity.getClass().getSuperclass().getSimpleName())
-                  .isEqualTo("Hilt_Injection1Test_TestActivity"));
-    }
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/Injection2Test.java b/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/Injection2Test.java
deleted file mode 100644
index 1ba3c2f..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/Injection2Test.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.AndroidEntryPoint;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.components.SingletonComponent;
-import javax.inject.Inject;
-import javax.inject.Named;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests basic injection APIs, and that bindings don't conflict with {@link Injection1Test}. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class Injection2Test {
-  private static final String APPLICATION_QUALIFIER = "APPLICATION_QUALIFIER";
-  private static final String ACTIVITY_QUALIFIER = "ACTIVITY_QUALIFIER";
-  private static final String APPLICATION_VALUE = "Injection2Test_ApplicationValue";
-  private static final String ACTIVITY_VALUE = "Injection2Test_ActivityValue";
-
-  @Module
-  @InstallIn(SingletonComponent.class)
-  interface TestApplicationModule {
-    @Provides
-    @Named(APPLICATION_QUALIFIER)
-    static String provideString() {
-      return APPLICATION_VALUE;
-    }
-  }
-
-  @Module
-  @InstallIn(ActivityComponent.class)
-  interface TestActivityModule {
-    @Provides
-    @Named(ACTIVITY_QUALIFIER)
-    static String provideString() {
-      return ACTIVITY_VALUE;
-    }
-  }
-
-  /** Test activity used to test activity injection */
-  @AndroidEntryPoint
-  public static final class TestActivity extends AppCompatActivity {
-    @Inject @Named(ACTIVITY_QUALIFIER) String activityValue;
-  }
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @Inject @Named(APPLICATION_QUALIFIER) String applicationValue;
-
-  @Test
-  public void testApplicationInjection() throws Exception {
-    assertThat(applicationValue).isNull();
-    rule.inject();
-    assertThat(applicationValue).isEqualTo(APPLICATION_VALUE);
-  }
-
-  @Test
-  public void testActivityInjection() throws Exception {
-    try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
-      scenario.onActivity(activity -> assertThat(activity.activityValue).isEqualTo(ACTIVITY_VALUE));
-    }
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/ModuleTest.java b/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/ModuleTest.java
deleted file mode 100644
index e1f4421..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/ModuleTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static org.junit.Assert.assertEquals;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.Binds;
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.components.SingletonComponent;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-import javax.inject.Inject;
-import javax.inject.Qualifier;
-import javax.inject.Singleton;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests basic functionality of using modules in test. */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class ModuleTest {
-  @Rule public final HiltAndroidRule rules = new HiltAndroidRule(this);
-
-  /** Qualifier for distinguishing test Strings, */
-  @Qualifier
-  @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
-  public @interface TestQualifier {
-    int value();
-  }
-
-  @Inject
-  @TestQualifier(1)
-  String testString1;
-
-  @Inject
-  @TestQualifier(2)
-  String testString2;
-
-  @Inject
-  @TestQualifier(3)
-  String testString3;
-
-  @Inject
-  @TestQualifier(4)
-  String testString4;
-
-  @Inject FooImpl fooImpl;
-  @Inject Foo foo;
-
-  /**
-   * Module which is used to test if non-static test modules get registered in the component
-   * correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public final class NonStaticModuleNonStaticProvides {
-    @Provides
-    @TestQualifier(1)
-    String provideString() {
-      return "1";
-    }
-  }
-
-  /**
-   * Module which is used to test if static test modules get registered in the component correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public static final class StaticModuleStaticProvides {
-    @Provides
-    @TestQualifier(2)
-    static String provideString() {
-      return "2";
-    }
-
-    private StaticModuleStaticProvides() {}
-  }
-
-  /**
-   * Module which is used to test if static test modules with a non-static methods get registered in
-   * the component correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public static final class StaticModuleNonStaticProvidesDefaultConstructor {
-    @Provides
-    @TestQualifier(3)
-    String provideString() {
-      return "3";
-    }
-  }
-
-  /**
-   * Module which is used to test if abstract test modules get registered in the component
-   * correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public abstract static class AbstractModuleStaticProvides {
-    @Provides
-    @TestQualifier(4)
-    static String provideString() {
-      return "4";
-    }
-
-    private AbstractModuleStaticProvides() {}
-  }
-
-  /**
-   * Module which is used to test if abstract test modules with a binds method get registered in the
-   * component correctly.
-   */
-  @Module
-  @InstallIn(SingletonComponent.class)
-  public abstract static class AbstractModuleBindsMethod {
-    @Binds
-    abstract Foo foo(FooImpl fooImpl);
-  }
-
-  interface Foo {}
-
-  @Singleton
-  static final class FooImpl implements Foo {
-    @Inject
-    FooImpl() {}
-  }
-
-  @Test
-  public void testInjection() throws Exception {
-    rules.inject();
-    assertEquals("1", testString1);
-    assertEquals("2", testString2);
-    assertEquals("3", testString3);
-    assertEquals("4", testString4);
-    assertEquals(fooImpl, foo);
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/SimpleActivityTest.java b/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/SimpleActivityTest.java
deleted file mode 100644
index f2e2e77..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/SimpleActivityTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import dagger.hilt.android.simple.lib.ThingImpl;
-import dagger.hilt.android.testing.BindValue;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import dagger.hilt.android.testing.UninstallModules;
-import javax.inject.Inject;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** A simple test using Hilt that can be run with instrumentation or Robolectric tests. */
-@UninstallModules({
-  UserNameModule.class,
-  ModelModule.class
-})
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public final class SimpleActivityTest {
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @BindValue @UserName String fakeUserName = "FakeUser";
-  @BindValue @Model String fakeModel = "FakeModel";
-
-  @Inject @UserName String injectedUserName;
-  @Inject @Model String injectedModel;
-
-  @Test
-  public void testInjectedUserName() throws Exception {
-    assertThat(injectedUserName).isNull();
-    rule.inject();
-    assertThat(injectedUserName).isEqualTo("FakeUser");
-  }
-
-  @Test
-  public void testInjectedModel() throws Exception {
-    assertThat(injectedModel).isNull();
-    rule.inject();
-    assertThat(injectedModel).isEqualTo("FakeModel");
-  }
-
-  @Test
-  public void testActivityInject() throws Exception {
-    try (ActivityScenario<SimpleActivity> scenario =
-        ActivityScenario.launch(SimpleActivity.class)) {
-      onView(withId(R.id.greeting))
-          .check(matches(withText("Hello, FakeUser! You are on build FakeModel.")));
-    } catch (RuntimeException e) {
-      // Just skip this test if the root view never becomes active.
-      // This issue occurs sporadically in emulator tests and causes the test to be flaky.
-      // It is likely caused by a race between our activity and a dialog or lock screen but
-      // it's difficult to debug this since it only fails in CI builds.
-      // TODO(b/176111885): Remove this once this bug is fixed.
-      if (!e.getMessage().startsWith("Waited for the root of the view hierarchy")) {
-        throw e;
-      }
-    }
-  }
-
-  @Test
-  public void verifyMainActivity() {
-    try (ActivityScenario<SimpleActivity> scenario =
-        ActivityScenario.launch(SimpleActivity.class)) {
-      scenario.onActivity(
-          activity -> {
-            assertThat(activity.getClass().getSuperclass().getSimpleName())
-              .isEqualTo("Hilt_SimpleActivity");
-          }
-      );
-    }
-  }
-
-  @Test
-  public void verifyThing() {
-    try (ActivityScenario<SimpleActivity> scenario =
-        ActivityScenario.launch(SimpleActivity.class)) {
-      scenario.onActivity(activity -> assertThat(activity.thing).isInstanceOf(ThingImpl.class));
-    }
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/TransitiveDependenciesTest.java b/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/TransitiveDependenciesTest.java
deleted file mode 100644
index a4f900d..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/sharedTest/java/dagger/hilt/android/simple/TransitiveDependenciesTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.platform.app.InstrumentationRegistry;
-import dagger.hilt.android.simple.feature.FeatureEntryPoints;
-import dagger.hilt.android.testing.HiltAndroidRule;
-import dagger.hilt.android.testing.HiltAndroidTest;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests that entry points in deep dependencies with `implementation` boundaries are available at
- * runtime.
- */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4.class)
-public class TransitiveDependenciesTest {
-
-  @Rule public HiltAndroidRule rule = new HiltAndroidRule(this);
-
-  @Test
-  public void testEntryPoint() {
-    FeatureEntryPoints.invokeEntryPoints(
-        InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext());
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/app/src/test/resources/dagger/hilt/android/simple/robolectric.properties b/javatests/artifacts/hilt-android/simple/app/src/test/resources/dagger/hilt/android/simple/robolectric.properties
deleted file mode 100644
index 0234ffe..0000000
--- a/javatests/artifacts/hilt-android/simple/app/src/test/resources/dagger/hilt/android/simple/robolectric.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sdk=28
-application=dagger.hilt.android.testing.HiltTestApplication
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simple/build.gradle b/javatests/artifacts/hilt-android/simple/build.gradle
deleted file mode 100644
index 770fabd..0000000
--- a/javatests/artifacts/hilt-android/simple/build.gradle
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-buildscript {
-    ext {
-        dagger_version = 'LOCAL-SNAPSHOT'
-        kotlin_version = '1.3.61'
-        agp_version = System.getenv('AGP_VERSION') ?: "4.2.0-beta04"
-    }
-    repositories {
-        google()
-        jcenter()
-        mavenLocal()
-    }
-    dependencies {
-        classpath "com.android.tools.build:gradle:$agp_version"
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-        classpath "com.google.dagger:hilt-android-gradle-plugin:$dagger_version"
-    }
-}
-
-allprojects {
-    repositories {
-      google()
-      jcenter()
-      mavenCentral()
-      mavenLocal()
-    }
-}
diff --git a/javatests/artifacts/hilt-android/simple/deep-android-lib/build.gradle b/javatests/artifacts/hilt-android/simple/deep-android-lib/build.gradle
deleted file mode 100644
index e5ed046..0000000
--- a/javatests/artifacts/hilt-android/simple/deep-android-lib/build.gradle
+++ /dev/null
@@ -1,26 +0,0 @@
-plugins {
-    id 'com.android.library'
-    id 'dagger.hilt.android.plugin'
-}
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-}
-
-dependencies {
-    implementation "com.google.dagger:hilt-android:$dagger_version"
-    annotationProcessor "com.google.dagger:hilt-compiler:$dagger_version"
-}
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simple/deep-android-lib/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/simple/deep-android-lib/src/main/AndroidManifest.xml
deleted file mode 100644
index 49a304e..0000000
--- a/javatests/artifacts/hilt-android/simple/deep-android-lib/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.simple.deep">
-
-</manifest>
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simple/deep-android-lib/src/main/java/dagger/hilt/android/simple/deep/DeepAndroidLib.java b/javatests/artifacts/hilt-android/simple/deep-android-lib/src/main/java/dagger/hilt/android/simple/deep/DeepAndroidLib.java
deleted file mode 100644
index 57fd803..0000000
--- a/javatests/artifacts/hilt-android/simple/deep-android-lib/src/main/java/dagger/hilt/android/simple/deep/DeepAndroidLib.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple.deep;
-
-import android.content.Context;
-import dagger.hilt.EntryPoint;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.EntryPointAccessors;
-import dagger.hilt.components.SingletonComponent;
-import javax.inject.Inject;
-
-public class DeepAndroidLib {
-
-  @EntryPoint
-  @InstallIn(SingletonComponent.class)
-  interface LibEntryPoint {
-    DeepAndroidLib getDeepAndroidInstance();
-  }
-
-  @Inject
-  public DeepAndroidLib() {}
-
-  public static DeepAndroidLib getInstance(Context context) {
-    return EntryPointAccessors.fromApplication(context, LibEntryPoint.class)
-        .getDeepAndroidInstance();
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/deep-lib/build.gradle b/javatests/artifacts/hilt-android/simple/deep-lib/build.gradle
deleted file mode 100644
index 22f815c..0000000
--- a/javatests/artifacts/hilt-android/simple/deep-lib/build.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-plugins {
-    id 'java-library'
-}
-
-java {
-    sourceCompatibility = JavaVersion.VERSION_1_7
-    targetCompatibility = JavaVersion.VERSION_1_7
-}
-
-dependencies {
-    implementation "com.google.dagger:hilt-core:$dagger_version"
-    annotationProcessor "com.google.dagger:hilt-compiler:$dagger_version"
-}
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simple/deep-lib/src/main/java/dagger/hilt/android/deep/DeepLib.java b/javatests/artifacts/hilt-android/simple/deep-lib/src/main/java/dagger/hilt/android/deep/DeepLib.java
deleted file mode 100644
index 419e539..0000000
--- a/javatests/artifacts/hilt-android/simple/deep-lib/src/main/java/dagger/hilt/android/deep/DeepLib.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.deep;
-
-import dagger.hilt.EntryPoint;
-import dagger.hilt.EntryPoints;
-import dagger.hilt.InstallIn;
-import dagger.hilt.components.SingletonComponent;
-import javax.inject.Inject;
-
-public class DeepLib {
-
-  @EntryPoint
-  @InstallIn(SingletonComponent.class)
-  interface LibEntryPoint {
-    DeepLib getDeepInstance();
-  }
-
-  @Inject
-  public DeepLib() {}
-
-  public static DeepLib getInstance(Object componentManager) {
-    return EntryPoints.get(componentManager, LibEntryPoint.class).getDeepInstance();
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/feature/build.gradle b/javatests/artifacts/hilt-android/simple/feature/build.gradle
deleted file mode 100644
index 0e772a8..0000000
--- a/javatests/artifacts/hilt-android/simple/feature/build.gradle
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-apply plugin: 'com.android.library'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-kapt'
-apply plugin: 'dagger.hilt.android.plugin'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-}
-
-kapt {
- correctErrorTypes true
-}
-
-hilt {
-    enableTransformForLocalTests = true
-}
-
-dependencies {
-    // This is api instead of implementation since Kotlin modules here consumed
-    // by the app need to expose @kotlin.Metadata
-    api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-
-    implementation project(":deep-android-lib")
-    implementation project(":deep-lib")
-
-    implementation 'androidx.appcompat:appcompat:1.2.0'
-    implementation "com.google.dagger:hilt-android:$dagger_version"
-    kapt "com.google.dagger:hilt-compiler:$dagger_version"
-}
diff --git a/javatests/artifacts/hilt-android/simple/feature/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/simple/feature/src/main/AndroidManifest.xml
deleted file mode 100644
index fe583e5..0000000
--- a/javatests/artifacts/hilt-android/simple/feature/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.simple.feature">
-  <application>
-    <activity
-        android:name=".FeatureActivity"
-        android:theme="@style/Theme.AppCompat.Light"
-        android:exported="true"/>
-  </application>
-</manifest>
diff --git a/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureActivity.kt b/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureActivity.kt
deleted file mode 100644
index c1931ac..0000000
--- a/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureActivity.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple.feature
-
-import android.os.Bundle
-import android.widget.Button
-import android.widget.TextView
-import androidx.appcompat.app.AppCompatActivity
-import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class FeatureActivity : AppCompatActivity() {
-  @Inject lateinit var counter: FeatureCounter
-
-  override fun onCreate(savedInstanceState: Bundle?) {
-    super.onCreate(savedInstanceState)
-
-    setContentView(R.layout.activity_feature)
-
-    findViewById<Button>(R.id.feature_button).setOnClickListener {
-      counter.count++
-      updateCountText()
-    }
-
-    updateCountText()
-  }
-
-  private fun updateCountText() {
-    findViewById<TextView>(R.id.feature_count).text = "The count: ${counter.count}"
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureCounter.kt b/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureCounter.kt
deleted file mode 100644
index d55bb5a..0000000
--- a/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureCounter.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple.feature
-
-class FeatureCounter(var count: Int)
diff --git a/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureEntryPoints.java b/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureEntryPoints.java
deleted file mode 100644
index c1ca22f..0000000
--- a/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureEntryPoints.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple.feature;
-
-import android.content.Context;
-import dagger.hilt.android.deep.DeepLib;
-import dagger.hilt.android.simple.deep.DeepAndroidLib;
-
-public final class FeatureEntryPoints {
-
-  public static void invokeEntryPoints(Context context) {
-    DeepAndroidLib.getInstance(context);
-    DeepLib.getInstance(context);
-  }
-
-  private FeatureEntryPoints() {}
-}
diff --git a/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureModule.kt b/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureModule.kt
deleted file mode 100644
index d513f37..0000000
--- a/javatests/artifacts/hilt-android/simple/feature/src/main/java/dagger/hilt/android/simple/feature/FeatureModule.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple.feature
-
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.components.ActivityRetainedComponent
-import dagger.hilt.android.scopes.ActivityRetainedScoped
-
-@Module
-@InstallIn(ActivityRetainedComponent::class)
-object FeatureModule {
-  @Provides
-  @ActivityRetainedScoped
-  fun provideData() = FeatureCounter(0)
-}
diff --git a/javatests/artifacts/hilt-android/simple/feature/src/main/res/layout/activity_feature.xml b/javatests/artifacts/hilt-android/simple/feature/src/main/res/layout/activity_feature.xml
deleted file mode 100644
index 99adcfd..0000000
--- a/javatests/artifacts/hilt-android/simple/feature/src/main/res/layout/activity_feature.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@android:color/background_light">
-
-  <TextView
-      android:id="@+id/feature_count"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:layout_alignParentTop="true"
-      android:textColor="@android:color/primary_text_light"
-      />
-
-  <Button
-      android:id="@+id/feature_button"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_below="@id/feature_count"
-      android:text="Count++"
-      />
-</RelativeLayout>
diff --git a/javatests/artifacts/hilt-android/simple/gradle.properties b/javatests/artifacts/hilt-android/simple/gradle.properties
deleted file mode 100644
index 646c51b..0000000
--- a/javatests/artifacts/hilt-android/simple/gradle.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-android.useAndroidX=true
-android.enableJetifier=true
diff --git a/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/hilt-android/simple/gradlew b/javatests/artifacts/hilt-android/simple/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/javatests/artifacts/hilt-android/simple/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/hilt-android/simple/lib/build.gradle b/javatests/artifacts/hilt-android/simple/lib/build.gradle
deleted file mode 100644
index d67be3b..0000000
--- a/javatests/artifacts/hilt-android/simple/lib/build.gradle
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-plugins {
-    id 'java-library'
-}
-
-java {
-    sourceCompatibility = JavaVersion.VERSION_1_8
-    targetCompatibility = JavaVersion.VERSION_1_8
-}
-
-dependencies {
-    implementation "com.google.dagger:hilt-core:$dagger_version"
-    annotationProcessor "com.google.dagger:hilt-compiler:$dagger_version"
-}
diff --git a/javatests/artifacts/hilt-android/simple/lib/src/main/java/dagger/hilt/android/simple/lib/Thing.java b/javatests/artifacts/hilt-android/simple/lib/src/main/java/dagger/hilt/android/simple/lib/Thing.java
deleted file mode 100644
index baded09..0000000
--- a/javatests/artifacts/hilt-android/simple/lib/src/main/java/dagger/hilt/android/simple/lib/Thing.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple.lib;
-
-/** A thing. */
-public interface Thing {}
diff --git a/javatests/artifacts/hilt-android/simple/lib/src/main/java/dagger/hilt/android/simple/lib/ThingImpl.java b/javatests/artifacts/hilt-android/simple/lib/src/main/java/dagger/hilt/android/simple/lib/ThingImpl.java
deleted file mode 100644
index f6a628e..0000000
--- a/javatests/artifacts/hilt-android/simple/lib/src/main/java/dagger/hilt/android/simple/lib/ThingImpl.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simple.lib;
-
-import dagger.Binds;
-import dagger.Module;
-import dagger.hilt.InstallIn;
-import dagger.hilt.components.SingletonComponent;
-import javax.inject.Inject;
-
-/** An implementation of a thing. */
-public final class ThingImpl implements Thing {
-  @Inject
-  ThingImpl() {}
-
-  @Module
-  @InstallIn(SingletonComponent.class)
-  interface FooStringModule {
-    @Binds Thing bind(ThingImpl impl);
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simple/settings.gradle b/javatests/artifacts/hilt-android/simple/settings.gradle
deleted file mode 100644
index bad895d..0000000
--- a/javatests/artifacts/hilt-android/simple/settings.gradle
+++ /dev/null
@@ -1,6 +0,0 @@
-rootProject.name='Simple Hilt Android'
-include ':app'
-include ':feature'
-include ':lib'
-include ':deep-android-lib'
-include ':deep-lib'
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle
deleted file mode 100644
index 383c4be..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle
+++ /dev/null
@@ -1,31 +0,0 @@
-plugins {
-    id 'com.android.library'
-    id 'kotlin-android'
-    id 'kotlin-kapt'
-}
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-}
-
-dependencies {
-    implementation project(':deep-android-lib')
-    implementation project(':deep-kotlin-lib')
-    implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-    kapt 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-}
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/android-library/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/simpleKotlin/android-library/src/main/AndroidManifest.xml
deleted file mode 100644
index c60ba73..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/android-library/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.simpleKotlin.lib">
-
-</manifest>
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/android-library/src/main/java/dagger/hilt/android/simpleKotlin/lib/AndroidLibraryEntryPoints.kt b/javatests/artifacts/hilt-android/simpleKotlin/android-library/src/main/java/dagger/hilt/android/simpleKotlin/lib/AndroidLibraryEntryPoints.kt
deleted file mode 100644
index cb10c8b..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/android-library/src/main/java/dagger/hilt/android/simpleKotlin/lib/AndroidLibraryEntryPoints.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package dagger.hilt.android.simpleKotlin.lib
-
-import android.content.Context
-import dagger.hilt.android.simpleKotlin.deep.DeepAndroidLib
-import dagger.hilt.android.simpleKotlin.deep.DeepLib
-
-object AndroidLibraryEntryPoints {
-  fun invokeEntryPoints(context: Context) {
-    DeepAndroidLib.getInstance(context)
-    DeepLib.getInstance(context)
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle
deleted file mode 100644
index ecfaf6e..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'dagger.hilt.android.plugin'
-apply plugin: 'kotlin-kapt'
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        applicationId "dagger.hilt.android.simpleKotlin"
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-        testInstrumentationRunner "dagger.hilt.android.example.gradle.simpleKotlin.TestRunner"
-    }
-    buildTypes {
-        release {
-            minifyEnabled true
-            shrinkResources true
-        }
-    }
-    compileOptions {
-        sourceCompatibility 1.8
-        targetCompatibility 1.8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-    testOptions {
-        unitTests.includeAndroidResources = true
-    }
-    lintOptions {
-        checkReleaseBuilds = false
-    }
-    sourceSets {
-        String sharedTestDir = 'src/sharedTest/java'
-        test {
-            java.srcDirs += sharedTestDir
-        }
-        androidTest {
-            java.srcDirs += sharedTestDir
-        }
-    }
-}
-
-hilt {
-    enableExperimentalClasspathAggregation = true
-    enableTransformForLocalTests = true
-}
-
-dependencies {
-    implementation project(':android-library')
-    implementation project(':kotlin-library')
-    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation 'androidx.appcompat:appcompat:1.2.0'
-    implementation 'androidx.activity:activity-ktx:1.1.0'
-
-    implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-    kapt 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-
-    testImplementation 'androidx.test.ext:junit:1.1.2'
-    testImplementation 'androidx.test:runner:1.3.0'
-    testImplementation 'com.google.truth:truth:1.0.1'
-    testImplementation 'junit:junit:4.13'
-    testImplementation 'org.robolectric:robolectric:4.5-alpha-3'
-    testImplementation 'androidx.core:core:1.3.2'
-    // TODO(bcorso): This multidex dep shouldn't be required -- it's a dep for the generated code.
-    testImplementation 'androidx.multidex:multidex:2.0.0'
-    testImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
-    kaptTest 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-
-    androidTestImplementation 'androidx.fragment:fragment-ktx:1.2.5'
-    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
-    androidTestImplementation 'androidx.test:runner:1.3.0'
-    androidTestImplementation 'com.google.truth:truth:1.0.1'
-    androidTestImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
-    kaptAndroidTest 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/SimpleEmulatorTestRunner.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/SimpleEmulatorTestRunner.kt
deleted file mode 100644
index d790265..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/SimpleEmulatorTestRunner.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import android.app.Application
-import android.content.Context
-import androidx.test.runner.AndroidJUnitRunner
-import dagger.hilt.android.testing.HiltTestApplication
-
-/** A custom runner to setup the emulator application class for tests.  */
-class SimpleEmulatorTestRunner : AndroidJUnitRunner() {
-  override fun newApplication(cl: ClassLoader, className: String, context: Context): Application {
-    return super.newApplication(cl, HiltTestApplication::class.java.name, context)
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/TestRunner.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/TestRunner.kt
deleted file mode 100644
index 29ffc9e..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/TestRunner.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.example.gradle.simpleKotlin
-
-import android.app.Application
-import android.content.Context
-import androidx.test.runner.AndroidJUnitRunner
-import dagger.hilt.android.testing.HiltTestApplication
-
-class TestRunner : AndroidJUnitRunner() {
-  override fun newApplication(cl: ClassLoader, appName: String, context: Context): Application {
-    return super.newApplication(cl, HiltTestApplication::class.java.name, context)
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/ActivityInjectionTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/ActivityInjectionTest.kt
deleted file mode 100644
index 6786e9d..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/ActivityInjectionTest.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.viewmodel
-
-import androidx.activity.viewModels
-import androidx.fragment.app.FragmentActivity
-import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@HiltAndroidTest
-@RunWith(AndroidJUnit4::class)
-class ActivityInjectionTest {
-
-  @get:Rule
-  val rule = HiltAndroidRule(this)
-
-  @Test
-  fun verifyInjection() {
-    ActivityScenario.launch(TestActivity::class.java).use {
-      it.onActivity { activity ->
-        assertThat(activity.myAndroidViewModel).isNotNull()
-        assertThat(activity.myViewModel).isNotNull()
-        assertThat(activity.myInjectedViewModel).isNotNull()
-        assertThat(activity.myNestedInjectedViewModel).isNotNull()
-        assertThat(activity.myInjectedViewModelWithSavedState).isNotNull()
-      }
-    }
-  }
-
-  @AndroidEntryPoint
-  class TestActivity : FragmentActivity() {
-    val myAndroidViewModel by viewModels<MyAndroidViewModel>()
-    val myViewModel by viewModels<MyViewModel>()
-    val myInjectedViewModel by viewModels<MyInjectedViewModel>()
-    val myNestedInjectedViewModel by viewModels<TopClass.MyNestedInjectedViewModel>()
-    val myInjectedViewModelWithSavedState by viewModels<MyInjectedViewModelWithSavedState>()
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/BaseActivityInjectionTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/BaseActivityInjectionTest.kt
deleted file mode 100644
index 7ac4ebf..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/BaseActivityInjectionTest.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.viewmodel
-
-import androidx.activity.viewModels
-import androidx.fragment.app.FragmentActivity
-import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@HiltAndroidTest
-@RunWith(AndroidJUnit4::class)
-class BaseActivityInjectionTest {
-
-  @get:Rule
-  val rule = HiltAndroidRule(this)
-
-  @Test
-  fun verifyInjection() {
-    ActivityScenario.launch(TestActivity::class.java).use {
-      it.onActivity { activity ->
-        assertThat(activity.myAndroidViewModel).isNotNull()
-        assertThat(activity.myViewModel).isNotNull()
-        assertThat(activity.myInjectedViewModel).isNotNull()
-      }
-    }
-  }
-
-  @AndroidEntryPoint
-  class TestActivity : BaseActivity()
-
-  abstract class BaseActivity : FragmentActivity() {
-    val myAndroidViewModel by viewModels<MyAndroidViewModel>()
-    val myViewModel by viewModels<MyViewModel>()
-    val myInjectedViewModel by viewModels<MyInjectedViewModel>()
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/BaseFragmentInjectionTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/BaseFragmentInjectionTest.kt
deleted file mode 100644
index 679a0d9..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/BaseFragmentInjectionTest.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.viewmodel
-
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.fragment.app.viewModels
-import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@HiltAndroidTest
-@RunWith(AndroidJUnit4::class)
-class BaseFragmentInjectionTest {
-
-  @get:Rule
-  val rule = HiltAndroidRule(this)
-
-  @Test
-  fun verifyInjection() {
-    ActivityScenario.launch(TestActivity::class.java).use {
-      it.onActivity { activity ->
-        val fragment = activity.supportFragmentManager.fragmentFactory.instantiate(
-          TestFragment::class.java.classLoader!!,
-          TestFragment::class.java.name
-        ) as TestFragment
-        activity.supportFragmentManager.beginTransaction()
-          .add(0, fragment, FragmentInjectionTest.FRAGMENT_TAG)
-          .commitNow()
-        assertThat(fragment.myAndroidViewModel).isNotNull()
-        assertThat(fragment.myViewModel).isNotNull()
-        assertThat(fragment.myInjectedViewModel).isNotNull()
-      }
-    }
-  }
-
-  @AndroidEntryPoint
-  class TestActivity : FragmentActivity()
-
-  @AndroidEntryPoint
-  class TestFragment : BaseFragment()
-
-  abstract class BaseFragment : Fragment() {
-    val myAndroidViewModel by viewModels<MyAndroidViewModel>()
-    val myViewModel by viewModels<MyViewModel>()
-    val myInjectedViewModel by viewModels<MyInjectedViewModel>()
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/Bindings.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/Bindings.kt
deleted file mode 100644
index 480aea1..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/Bindings.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.viewmodel
-
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.components.SingletonComponent
-import javax.inject.Inject
-import javax.inject.Named
-
-class Foo @Inject constructor()
-
-class Bar
-
-@Module
-@InstallIn(SingletonComponent::class)
-object StringModule {
-  @Provides
-  @Named("SayMyName")
-  fun provide() = "Heisenberg"
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/FragmentInjectionTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/FragmentInjectionTest.kt
deleted file mode 100644
index 8d98e92..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/FragmentInjectionTest.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.viewmodel
-
-import android.os.Bundle
-import androidx.activity.viewModels
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.fragment.app.FragmentManager
-import androidx.fragment.app.activityViewModels
-import androidx.fragment.app.viewModels
-import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.LargeTest
-import com.google.common.truth.Truth.assertThat
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@LargeTest
-@HiltAndroidTest
-@RunWith(AndroidJUnit4::class)
-class FragmentInjectionTest {
-
-  @get:Rule
-  val rule = HiltAndroidRule(this)
-
-  @Test
-  fun verifyInjection() {
-    ActivityScenario.launch(TestActivity::class.java).use {
-      it.onActivity { activity ->
-        activity.addTestFragment()
-        activity.supportFragmentManager.findTestFragment().let { fragment ->
-          assertThat(fragment.myAndroidViewModel).isNotNull()
-          assertThat(fragment.myViewModel).isNotNull()
-          assertThat(fragment.myInjectedViewModel).isNotNull()
-          assertThat(fragment.myInjectedViewModelWithSavedState).isNotNull()
-        }
-      }
-    }
-  }
-
-  @Test
-  fun verifyActivityViewModelInjection() {
-    ActivityScenario.launch(TestActivity::class.java).use {
-      it.onActivity { activity ->
-        activity.addTestFragment()
-        activity.supportFragmentManager.findTestFragment().let { fragment ->
-          assertThat(fragment.myInjectedViewModel).isNotNull()
-          assertThat(fragment.myActivityLevelInjectedViewModel).isNotNull()
-          assertThat(fragment.myInjectedViewModel)
-            .isNotEqualTo(fragment.myActivityLevelInjectedViewModel)
-          assertThat(fragment.myActivityLevelInjectedViewModel)
-            .isEqualTo(activity.myInjectedViewModel)
-        }
-        activity.removeTestFragment()
-        activity.addTestFragment()
-        activity.supportFragmentManager.findTestFragment().let { fragment ->
-          assertThat(fragment.myInjectedViewModel).isNotNull()
-          assertThat(fragment.myActivityLevelInjectedViewModel).isNotNull()
-          assertThat(fragment.myInjectedViewModel)
-            .isNotEqualTo(fragment.myActivityLevelInjectedViewModel)
-          assertThat(fragment.myActivityLevelInjectedViewModel)
-            .isEqualTo(activity.myInjectedViewModel)
-        }
-      }
-    }
-  }
-
-  @AndroidEntryPoint
-  class TestActivity : FragmentActivity() {
-
-    val myInjectedViewModel by viewModels<MyInjectedViewModel>()
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-      super.onCreate(savedInstanceState)
-      addTestFragment()
-    }
-
-    fun addTestFragment() {
-      val fragment = supportFragmentManager.fragmentFactory.instantiate(
-        TestFragment::class.java.classLoader!!,
-        TestFragment::class.java.name
-      )
-      supportFragmentManager.beginTransaction()
-        .add(0, fragment, FRAGMENT_TAG)
-        .commitNow()
-    }
-
-    fun removeTestFragment() {
-      supportFragmentManager.beginTransaction()
-        .remove(supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)!!)
-        .commitNow()
-    }
-  }
-
-  @AndroidEntryPoint
-  class TestFragment : Fragment() {
-    val myAndroidViewModel by viewModels<MyAndroidViewModel>()
-    val myViewModel by viewModels<MyViewModel>()
-    val myInjectedViewModel by viewModels<MyInjectedViewModel>()
-    val myInjectedViewModelWithSavedState by viewModels<MyInjectedViewModelWithSavedState>()
-    val myActivityLevelInjectedViewModel by activityViewModels<MyInjectedViewModel>()
-  }
-
-  private fun FragmentManager.findTestFragment() =
-    findFragmentByTag(FRAGMENT_TAG) as TestFragment
-
-  companion object {
-    const val FRAGMENT_TAG = "tag"
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/MyViewModels.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/MyViewModels.kt
deleted file mode 100644
index c24c6b7..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/MyViewModels.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.viewmodel
-
-import android.app.Application
-import androidx.lifecycle.AndroidViewModel
-import androidx.lifecycle.SavedStateHandle
-import androidx.lifecycle.ViewModel
-import dagger.hilt.android.lifecycle.HiltViewModel
-import javax.inject.Inject
-import javax.inject.Named
-
-class MyAndroidViewModel(app: Application) : AndroidViewModel(app)
-
-class MyViewModel() : ViewModel()
-
-@Suppress("UNUSED_PARAMETER")
-@HiltViewModel
-class MyInjectedViewModel @Inject constructor(
-  foo: Foo,
-  @Named("SayMyName") theName: String
-) : ViewModel()
-
-object TopClass {
-  @Suppress("UNUSED_PARAMETER")
-  @HiltViewModel
-  class MyNestedInjectedViewModel @Inject constructor(foo: Foo) : ViewModel()
-}
-
-@Suppress("UNUSED_PARAMETER")
-@HiltViewModel
-class MyInjectedViewModelWithSavedState @Inject constructor(
-  foo: Foo,
-  handle: SavedStateHandle
-) : ViewModel()
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/ViewModelScopedTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/ViewModelScopedTest.kt
deleted file mode 100644
index cdf6a65..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/androidTest/java/dagger/hilt/android/simpleKotlin/viewmodel/ViewModelScopedTest.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.viewmodel
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.fragment.app.FragmentManager
-import androidx.fragment.app.viewModels
-import androidx.lifecycle.ViewModel
-import androidx.test.core.app.ActivityScenario
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.components.ViewModelComponent
-import dagger.hilt.android.lifecycle.HiltViewModel
-import dagger.hilt.android.scopes.ViewModelScoped
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import javax.inject.Inject
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@HiltAndroidTest
-@RunWith(AndroidJUnit4::class)
-class ViewModelScopedTest {
-
-  @get:Rule
-  val rule = HiltAndroidRule(this)
-
-  @Test
-  fun testViewModelScopeInFragment() {
-    ActivityScenario.launch(TestActivity::class.java).use {
-      it.onActivity { activity ->
-        activity.supportFragmentManager.findTestFragment().let { fragment ->
-          val vm = fragment.vm
-          assertThat(vm.one.bar).isEqualTo(vm.two.bar)
-        }
-      }
-    }
-  }
-
-  @Module
-  @InstallIn(ViewModelComponent::class)
-  object ScopedModule {
-    @Provides
-    @ViewModelScoped
-    fun provideBar() = Bar()
-  }
-
-  @AndroidEntryPoint
-  class TestActivity : FragmentActivity() {
-    override fun onCreate(savedInstanceState: Bundle?) {
-      super.onCreate(savedInstanceState)
-
-      if (savedInstanceState == null) {
-        val fragment = supportFragmentManager.fragmentFactory.instantiate(
-          TestFragment::class.java.classLoader!!,
-          TestFragment::class.java.name
-        )
-        supportFragmentManager.beginTransaction()
-          .add(0, fragment, FRAGMENT_TAG)
-          .commitNow()
-      }
-    }
-  }
-
-  @AndroidEntryPoint
-  class TestFragment : Fragment() {
-    val vm by viewModels<TestViewModel>()
-  }
-
-  @HiltViewModel
-  class TestViewModel @Inject constructor(
-    val one: DependsOnBarOne,
-    val two: DependsOnBarTwo
-  ) : ViewModel()
-
-  class DependsOnBarOne @Inject constructor(val bar: Bar)
-  class DependsOnBarTwo @Inject constructor(val bar: Bar)
-
-  private fun FragmentManager.findTestFragment() =
-    findFragmentByTag(FRAGMENT_TAG) as TestFragment
-
-  companion object {
-    const val FRAGMENT_TAG = "tag"
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/debug/AndroidManifest.xml b/javatests/artifacts/hilt-android/simpleKotlin/app/src/debug/AndroidManifest.xml
deleted file mode 100644
index 0a0270e..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/debug/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.simpleKotlin">
-
-  <application>
-    <activity android:name=".SimpleTest$TestActivity" android:exported="false"/>
-    <activity android:name=".viewmodel.ActivityInjectionTest$TestActivity" android:exported="false"/>
-    <activity android:name=".viewmodel.BaseActivityInjectionTest$TestActivity" android:exported="false"/>
-    <activity android:name=".viewmodel.FragmentInjectionTest$TestActivity" android:exported="false"/>
-    <activity android:name=".viewmodel.BaseFragmentInjectionTest$TestActivity" android:exported="false"/>
-    <activity android:name=".viewmodel.ViewModelScopedTest$TestActivity" android:exported="false"/>
-  </application>
-</manifest>
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/AndroidManifest.xml
deleted file mode 100644
index ca700b2..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.simpleKotlin">
-
-    <application
-        android:name=".KotlinApplication"
-        android:allowBackup="true"
-        android:label="@string/app_name"
-        android:supportsRtl="true"
-        android:theme="@style/Theme.AppCompat.Light">
-        <activity android:name=".MainActivity" android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/ActivityRetainedModule.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/ActivityRetainedModule.kt
deleted file mode 100644
index b830f31..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/ActivityRetainedModule.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.components.ActivityRetainedComponent
-
-@Module
-@InstallIn(ActivityRetainedComponent::class)
-object ActivityRetainedModule {
-  @UserName
-  @Provides
-  fun provideUserName(): String {
-    return "Android User"
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/ApplicationModule.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/ApplicationModule.kt
deleted file mode 100644
index 59b79bb..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/ApplicationModule.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import android.os.Build
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.components.SingletonComponent
-
-@Module
-@InstallIn(SingletonComponent::class)
-object ApplicationModule {
-  @Provides
-  @Model
-  fun provideModel(): String {
-    return Build.MODEL
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/DefinedStrings.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/DefinedStrings.kt
deleted file mode 100644
index b22e588..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/DefinedStrings.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2021 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.hilt.android.simpleKotlin
-
-object DefinedStrings {
-  internal val morningSweet = "Mallorca"
-  internal fun getInternalSweet() = "Sugar Donuts"
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/KotlinApplication.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/KotlinApplication.kt
deleted file mode 100644
index c638706..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/KotlinApplication.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import android.app.Application
-import dagger.hilt.android.HiltAndroidApp
-import javax.inject.Inject
-
-@HiltAndroidApp
-class KotlinApplication : Application() {
-  // Shows that we can inject ApplicationComponent bindings into an application.
-  @Inject
-  @Model
-  @JvmField
-  var model: String? = null
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/MainActivity.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/MainActivity.kt
deleted file mode 100644
index bd7f8a7..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/MainActivity.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import android.os.Bundle
-import android.view.View
-import android.widget.TextView
-import androidx.activity.viewModels
-import androidx.appcompat.app.AppCompatActivity
-import androidx.lifecycle.ViewModel
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.lifecycle.HiltViewModel
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class MainActivity : AppCompatActivity() {
-
-  val viewModel by viewModels<MainViewModel>()
-
-  override fun onCreate(savedInstanceState: Bundle?) {
-    super.onCreate(savedInstanceState)
-    setContentView(R.layout.activity_main)
-    val greeting = findViewById<View>(R.id.greeting) as TextView
-    val text = resources.getString(R.string.welcome, viewModel.name, viewModel.model)
-    greeting.text = text
-  }
-
-  // Shows that we can inject bindings into a ViewModel
-  @HiltViewModel
-  class MainViewModel @Inject constructor(
-    @Model val model: String,
-    @UserName val name: String
-  ) : ViewModel()
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/Model.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/Model.kt
deleted file mode 100644
index 7e7e9ae..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/Model.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import javax.inject.Qualifier
-
-/** Qualifies bindings relating to [android.os.Build.MODEL].  */
-@Qualifier
-@Retention(AnnotationRetention.RUNTIME)
-internal annotation class Model
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/UserName.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/UserName.kt
deleted file mode 100644
index 352e48c..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/java/dagger/hilt/android/simpleKotlin/UserName.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import javax.inject.Qualifier
-
-/** Qualifies bindings relating to the user name.  */
-@Qualifier
-@Retention(AnnotationRetention.RUNTIME)
-internal annotation class UserName
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/res/layout/activity_main.xml b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index 0d7637d..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:background="@android:color/background_light">
-
-  <TextView
-    android:id="@+id/greeting"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_alignParentTop="true"
-    android:textColor="@android:color/primary_text_light"
-    />
-</RelativeLayout>
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/res/values/strings.xml b/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/res/values/strings.xml
deleted file mode 100644
index c1e4f27..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<resources>
-    <!--The app name [CHAR_LIMIT=40]-->
-    <string name="app_name">Simple Hilt Kotlin Android App</string>
-
-    <!--The greeting message [CHAR_LIMIT=100]-->
-    <string name="welcome">Hello, %1$s! You are on build %2$s.</string>
-</resources>
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/sharedTest/java/dagger/hilt/android/simpleKotlin/InternalAccessTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/sharedTest/java/dagger/hilt/android/simpleKotlin/InternalAccessTest.kt
deleted file mode 100644
index 43a1abc..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/sharedTest/java/dagger/hilt/android/simpleKotlin/InternalAccessTest.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 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.hilt.android.simpleKotlin
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/**
- * Verifies internal Kotlin classes are accessible with classpath aggregation.
- */
-@RunWith(AndroidJUnit4::class)
-class InternalAccessTest {
-  @Test
-  fun verifyInternalMembersAreAccessible() {
-    assertThat(DefinedStrings.morningSweet).isNotNull()
-    assertThat(DefinedStrings.getInternalSweet()).isNotNull()
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/sharedTest/java/dagger/hilt/android/simpleKotlin/TransitiveDependenciesTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/sharedTest/java/dagger/hilt/android/simpleKotlin/TransitiveDependenciesTest.kt
deleted file mode 100644
index 10e6515..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/sharedTest/java/dagger/hilt/android/simpleKotlin/TransitiveDependenciesTest.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.platform.app.InstrumentationRegistry
-import dagger.hilt.android.simpleKotlin.lib.AndroidLibraryEntryPoints
-import dagger.hilt.android.simpleKotlin.lib.KotlinLibraryEntryPoints
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/**
- * Tests that entry points in deep dependencies with `implementation` boundaries are available at
- * runtime.
- */
-@HiltAndroidTest
-@RunWith(AndroidJUnit4::class)
-class TransitiveDependenciesTest {
-  @get:Rule
-  val rule = HiltAndroidRule(this)
-
-  @Test
-  fun testEntryPointFromAndroidLib() {
-    AndroidLibraryEntryPoints.invokeEntryPoints(
-      InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
-    )
-  }
-
-  @Test
-  fun testEntryPointFromKotlinLib() {
-    KotlinLibraryEntryPoints.invokeEntryPoints(
-      InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
-    )
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/java/dagger/hilt/android/simpleKotlin/SimpleTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/java/dagger/hilt/android/simpleKotlin/SimpleTest.kt
deleted file mode 100644
index 1e04606..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/java/dagger/hilt/android/simpleKotlin/SimpleTest.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin
-
-import android.os.Build
-import androidx.appcompat.app.AppCompatActivity
-import androidx.test.core.app.ActivityScenario
-import com.google.common.truth.Truth.assertThat
-import dagger.hilt.android.AndroidEntryPoint
-import dagger.hilt.android.testing.BindValue
-import dagger.hilt.android.testing.HiltAndroidRule
-import dagger.hilt.android.testing.HiltAndroidTest
-import dagger.hilt.android.testing.HiltTestApplication
-import javax.inject.Inject
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.RobolectricTestRunner
-import org.robolectric.annotation.Config
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
-@HiltAndroidTest
-@RunWith(RobolectricTestRunner::class)
-// Robolectric requires Java9 to run API 29 and above, so use API 28 instead
-@Config(sdk = [Build.VERSION_CODES.P], application = HiltTestApplication::class)
-class SimpleTest {
-  @get:Rule val rule = HiltAndroidRule(this)
-
-  @BindValue val bindStr = "STRING_BINDING"
-
-  @Inject @JvmField
-  var str: String? = null
-
-  @AndroidEntryPoint
-  class TestActivity : AppCompatActivity()
-
-  @Test
-  fun testBindValue() {
-    assertThat(str).isNull()
-    rule.inject()
-    assertThat(str).isEqualTo(bindStr)
-  }
-
-  @Test
-  fun verifyMainActivity() {
-    ActivityScenario.launch(MainActivity::class.java).use { scenario ->
-      scenario.onActivity { activity ->
-        assertThat(activity::class.java.getSuperclass()?.getSimpleName())
-          .isEqualTo("Hilt_MainActivity")
-        assertThat(activity.viewModel.model).isNotNull()
-        assertThat(activity.viewModel.name).isNotNull()
-      }
-    }
-  }
-
-  @Test
-  fun verifyTestActivity() {
-    ActivityScenario.launch(TestActivity::class.java).use { scenario ->
-      scenario.onActivity { activity ->
-        assertThat(activity::class.java.getSuperclass()?.getSimpleName())
-          .isEqualTo("Hilt_SimpleTest_TestActivity")
-      }
-    }
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/resources/dagger/hilt/android/simpleKotlin/robolectric.properties b/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/resources/dagger/hilt/android/simpleKotlin/robolectric.properties
deleted file mode 100644
index 0234ffe..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/resources/dagger/hilt/android/simpleKotlin/robolectric.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sdk=28
-application=dagger.hilt.android.testing.HiltTestApplication
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/build.gradle
deleted file mode 100644
index d594476..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/build.gradle
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-buildscript {
-    ext {
-        kotlin_version = '1.3.61'
-        agp_version = System.getenv('AGP_VERSION') ?: "4.2.0-beta04"
-    }
-    repositories {
-        google()
-        jcenter()
-        mavenLocal()
-    }
-    dependencies {
-        classpath "com.android.tools.build:gradle:$agp_version"
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-        classpath 'com.google.dagger:hilt-android-gradle-plugin:LOCAL-SNAPSHOT'
-    }
-}
-
-allprojects {
-    repositories {
-      google()
-      jcenter()
-      mavenCentral()
-      mavenLocal()
-    }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle
deleted file mode 100644
index 3a1923a..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle
+++ /dev/null
@@ -1,46 +0,0 @@
-plugins {
-    id 'com.android.library'
-    id 'kotlin-android'
-    id 'kotlin-kapt'
-    id 'dagger.hilt.android.plugin'
-}
-
-android {
-    compileSdkVersion 30
-    buildToolsVersion "30.0.2"
-
-    defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 30
-        versionCode 1
-        versionName "1.0"
-
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-    lintOptions {
-        checkReleaseBuilds = false
-    }
-}
-
-dependencies {
-    implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
-    kapt 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'
-
-    testImplementation 'androidx.test.ext:junit:1.1.2'
-    testImplementation 'com.google.truth:truth:1.0.1'
-
-    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
-    androidTestImplementation 'androidx.test:runner:1.3.0'
-    androidTestImplementation 'com.google.truth:truth:1.0.1'
-}
-
-hilt {
-    enableExperimentalClasspathAggregation = true
-}
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/androidTest/java/dagger/hilt/android/simpleKotlin/deep/InternalAccessEmulatorTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/androidTest/java/dagger/hilt/android/simpleKotlin/deep/InternalAccessEmulatorTest.kt
deleted file mode 100644
index 4ea4c09..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/androidTest/java/dagger/hilt/android/simpleKotlin/deep/InternalAccessEmulatorTest.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2021 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.hilt.android.simpleKotlin.deep
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/**
- * Verifies internal Kotlin classes are accessible with classpath aggregation in Android library.
- */
-@RunWith(AndroidJUnit4::class)
-class InternalAccessEmulatorTest {
-  @Test
-  fun verifyInternalMembersAreAccessible() {
-    assertThat(DeepAndroidLib.internalFunction()).isNotNull()
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/main/AndroidManifest.xml
deleted file mode 100644
index ae2a5e3..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="dagger.hilt.android.simpleKotlin.deep">
-
-</manifest>
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/main/java/dagger/hilt/android/simpleKotlin/deep/DeepAndroidLib.kt b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/main/java/dagger/hilt/android/simpleKotlin/deep/DeepAndroidLib.kt
deleted file mode 100644
index a2fcb73..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/main/java/dagger/hilt/android/simpleKotlin/deep/DeepAndroidLib.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.deep
-
-import android.content.Context
-import dagger.hilt.EntryPoint
-import dagger.hilt.InstallIn
-import dagger.hilt.android.EntryPointAccessors
-import dagger.hilt.components.SingletonComponent
-import javax.inject.Inject
-
-class DeepAndroidLib @Inject constructor() {
-  @EntryPoint
-  @InstallIn(SingletonComponent::class)
-  internal interface LibEntryPoint {
-    fun getDeepAndroidInstance(): DeepAndroidLib
-  }
-
-  companion object {
-    fun getInstance(context: Context) =
-      EntryPointAccessors.fromApplication(context, LibEntryPoint::class.java)
-        .getDeepAndroidInstance()
-
-    internal fun internalFunction() = Any()
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/test/java/dagger/hilt/android/simpleKotlin/deep/InternalAccessLocalTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/test/java/dagger/hilt/android/simpleKotlin/deep/InternalAccessLocalTest.kt
deleted file mode 100644
index 508e7d5..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/src/test/java/dagger/hilt/android/simpleKotlin/deep/InternalAccessLocalTest.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2021 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.hilt.android.simpleKotlin.deep
-
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-/**
- * Verifies internal Kotlin classes are accessible with classpath aggregation in Android library.
- */
-class InternalAccessLocalTest {
-  @Test
-  fun verifyInternalMembersAreAccessible() {
-    assertThat(DeepAndroidLib.internalFunction()).isNotNull()
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-kotlin-lib/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/deep-kotlin-lib/build.gradle
deleted file mode 100644
index 306c171..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/deep-kotlin-lib/build.gradle
+++ /dev/null
@@ -1,16 +0,0 @@
-plugins {
-    id 'java-library'
-    id 'kotlin'
-    id 'kotlin-kapt'
-}
-
-java {
-    sourceCompatibility = JavaVersion.VERSION_1_8
-    targetCompatibility = JavaVersion.VERSION_1_8
-}
-
-dependencies {
-    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation "com.google.dagger:hilt-core:LOCAL-SNAPSHOT"
-    kapt "com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT"
-}
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-kotlin-lib/src/main/java/dagger/hilt/android/simpleKotlin/deep/DeepLib.kt b/javatests/artifacts/hilt-android/simpleKotlin/deep-kotlin-lib/src/main/java/dagger/hilt/android/simpleKotlin/deep/DeepLib.kt
deleted file mode 100644
index 0d2bc61..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/deep-kotlin-lib/src/main/java/dagger/hilt/android/simpleKotlin/deep/DeepLib.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.simpleKotlin.deep
-
-import dagger.hilt.EntryPoint
-import dagger.hilt.EntryPoints
-import dagger.hilt.InstallIn
-import dagger.hilt.components.SingletonComponent
-import javax.inject.Inject
-
-class DeepLib @Inject constructor() {
-  @EntryPoint
-  @InstallIn(SingletonComponent::class)
-  internal interface LibEntryPoint {
-    fun getDeepInstance(): DeepLib
-  }
-
-  companion object {
-    fun getInstance(componentManager: Any) =
-      EntryPoints.get(componentManager, LibEntryPoint::class.java)
-        .getDeepInstance()
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/gradle.properties b/javatests/artifacts/hilt-android/simpleKotlin/gradle.properties
deleted file mode 100644
index 646c51b..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/gradle.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-android.useAndroidX=true
-android.enableJetifier=true
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 5c2d1cf..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 4d9ca16..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/gradlew b/javatests/artifacts/hilt-android/simpleKotlin/gradlew
deleted file mode 100755
index b0d6d0a..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or 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.
-#
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/kotlin-library/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/kotlin-library/build.gradle
deleted file mode 100644
index 7c8462f..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/kotlin-library/build.gradle
+++ /dev/null
@@ -1,17 +0,0 @@
-plugins {
-    id 'java-library'
-    id 'kotlin'
-    id 'kotlin-kapt'
-}
-
-java {
-    sourceCompatibility = JavaVersion.VERSION_1_8
-    targetCompatibility = JavaVersion.VERSION_1_8
-}
-
-dependencies {
-    implementation project(':deep-kotlin-lib')
-    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation "com.google.dagger:hilt-core:LOCAL-SNAPSHOT"
-    kapt "com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT"
-}
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/kotlin-library/src/main/java/dagger/hilt/android/simpleKotlin/lib/KotlinLibraryEntryPoints.kt b/javatests/artifacts/hilt-android/simpleKotlin/kotlin-library/src/main/java/dagger/hilt/android/simpleKotlin/lib/KotlinLibraryEntryPoints.kt
deleted file mode 100644
index 8989ebb..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/kotlin-library/src/main/java/dagger/hilt/android/simpleKotlin/lib/KotlinLibraryEntryPoints.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package dagger.hilt.android.simpleKotlin.lib
-
-import dagger.hilt.android.simpleKotlin.deep.DeepLib
-
-object KotlinLibraryEntryPoints {
-  fun invokeEntryPoints(component: Any) {
-    DeepLib.getInstance(component)
-  }
-}
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/settings.gradle b/javatests/artifacts/hilt-android/simpleKotlin/settings.gradle
deleted file mode 100644
index cea0913..0000000
--- a/javatests/artifacts/hilt-android/simpleKotlin/settings.gradle
+++ /dev/null
@@ -1,6 +0,0 @@
-rootProject.name='Simple Kotlin Hilt Android'
-include ':app'
-include ':android-library'
-include ':kotlin-library'
-include ':deep-android-lib'
-include ':deep-kotlin-lib'
diff --git a/javatests/dagger/BUILD b/javatests/dagger/BUILD
index c6ab360..3debec5 100644
--- a/javatests/dagger/BUILD
+++ b/javatests/dagger/BUILD
@@ -15,11 +15,11 @@
 # Description:
 #   A JSR-330 compliant dependency injection system for android and java
 
+package(default_visibility = ["//:src"])
+
 load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "DOCLINT_REFERENCES")
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "core_tests",
     srcs = glob(["**/*.java"]),
@@ -27,8 +27,7 @@
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     deps = [
         "//java/dagger:core",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/jsr330_inject",
         "@google_bazel_common//third_party/java/junit",
         "@google_bazel_common//third_party/java/truth",
diff --git a/javatests/dagger/android/AndroidInjectionTest.java b/javatests/dagger/android/AndroidInjectionTest.java
index 7e60ebd..19b6e84 100644
--- a/javatests/dagger/android/AndroidInjectionTest.java
+++ b/javatests/dagger/android/AndroidInjectionTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.fail;
-import static org.robolectric.annotation.LooperMode.Mode.LEGACY;
 
 import android.app.Activity;
 import android.app.Application;
@@ -28,10 +27,9 @@
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
-import org.robolectric.annotation.LooperMode;
 import org.robolectric.util.FragmentTestUtil;
 
-@LooperMode(LEGACY)
+@Config(manifest = Config.NONE)
 @RunWith(RobolectricTestRunner.class)
 public final class AndroidInjectionTest {
 
@@ -41,7 +39,7 @@
     String tag;
   }
 
-  private static AndroidInjector<Object> fakeFragmentInjector(String tag) {
+  private static AndroidInjector<Fragment> fakeFragmentInjector(String tag) {
     return instance -> {
       if (instance instanceof InjectableFragment) {
         ((InjectableFragment) instance).tag = tag;
@@ -49,14 +47,15 @@
     };
   }
 
-  public static class ApplicationInjectsFragment extends Application implements HasAndroidInjector {
+  public static class ApplicationInjectsFragment extends Application
+      implements HasFragmentInjector {
     @Override
-    public AndroidInjector<Object> androidInjector() {
+    public AndroidInjector<Fragment> fragmentInjector() {
       return fakeFragmentInjector("injected by app");
     }
   }
 
-  @Config(application = ApplicationInjectsFragment.class)
+  @Config(manifest = Config.NONE, application = ApplicationInjectsFragment.class)
   @Test
   public void fragmentInjectedByApplication() {
     Activity activity = Robolectric.setupActivity(Activity.class);
@@ -68,14 +67,14 @@
     assertThat(fragment.tag).isEqualTo("injected by app");
   }
 
-  public static class ActivityInjectsFragment extends Activity implements HasAndroidInjector {
+  public static class ActivityInjectsFragment extends Activity implements HasFragmentInjector {
     @Override
-    public AndroidInjector<Object> androidInjector() {
+    public AndroidInjector<Fragment> fragmentInjector() {
       return fakeFragmentInjector("injected by activity");
     }
   }
 
-  @Config(application = ApplicationInjectsFragment.class)
+  @Config(manifest = Config.NONE, application = ApplicationInjectsFragment.class)
   @Test
   public void fragmentInjectedByActivity() {
     ActivityInjectsFragment activity = Robolectric.setupActivity(ActivityInjectsFragment.class);
@@ -88,14 +87,14 @@
   }
 
   public static class ParentFragmentInjectsChildFragment extends Fragment
-      implements HasAndroidInjector {
+      implements HasFragmentInjector {
     @Override
-    public AndroidInjector<Object> androidInjector() {
+    public AndroidInjector<Fragment> fragmentInjector() {
       return fakeFragmentInjector("injected by parent fragment");
     }
   }
 
-  @Config(application = ApplicationInjectsFragment.class)
+  @Config(manifest = Config.NONE, application = ApplicationInjectsFragment.class)
   @Test
   public void fragmentInjectedByParentFragment() {
     ActivityInjectsFragment activity = Robolectric.setupActivity(ActivityInjectsFragment.class);
@@ -114,7 +113,7 @@
   }
 
   @Test
-  public void injectActivity_applicationDoesntImplementHasAndroidInjector() {
+  public void injectActivity_applicationDoesntImplementHasActivityInjector() {
     Activity activity = Robolectric.setupActivity(Activity.class);
 
     try {
@@ -140,15 +139,21 @@
     }
   }
 
-  private static class ApplicationReturnsNull extends Application implements HasAndroidInjector {
+  private static class ApplicationReturnsNull extends Application
+      implements HasActivityInjector, HasFragmentInjector {
     @Override
-    public AndroidInjector<Object> androidInjector() {
+    public AndroidInjector<Activity> activityInjector() {
+      return null;
+    }
+
+    @Override
+    public AndroidInjector<Fragment> fragmentInjector() {
       return null;
     }
   }
 
   @Test
-  @Config(application = ApplicationReturnsNull.class)
+  @Config(manifest = Config.NONE, application = ApplicationReturnsNull.class)
   public void activityInjector_returnsNull() {
     Activity activity = Robolectric.setupActivity(Activity.class);
 
@@ -156,12 +161,12 @@
       AndroidInjection.inject(activity);
       fail();
     } catch (Exception e) {
-      assertThat(e).hasMessageThat().contains("androidInjector() returned null");
+      assertThat(e).hasMessageThat().contains("activityInjector() returned null");
     }
   }
 
   @Test
-  @Config(application = ApplicationReturnsNull.class)
+  @Config(manifest = Config.NONE, application = ApplicationReturnsNull.class)
   public void fragmentInjector_returnsNull() {
     Fragment fragment = new Fragment();
     FragmentTestUtil.startFragment(fragment);
@@ -170,7 +175,7 @@
       AndroidInjection.inject(fragment);
       fail();
     } catch (Exception e) {
-      assertThat(e).hasMessageThat().contains("androidInjector() returned null");
+      assertThat(e).hasMessageThat().contains("fragmentInjector() returned null");
     }
   }
 
diff --git a/javatests/dagger/android/AndroidProguardTest.java b/javatests/dagger/android/AndroidProguardTest.java
deleted file mode 100644
index 0f51e49..0000000
--- a/javatests/dagger/android/AndroidProguardTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 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.android;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.android.internal.AndroidInjectionKeys;
-import java.net.URL;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class AndroidProguardTest {
-
-  @Test
-  public void checkLegacyProguardRules() {
-    URL resUrl =
-        AndroidInjectionKeys.class
-            .getClassLoader()
-            .getResource("META-INF/proguard/dagger-android.pro");
-    assertThat(resUrl).isNotNull();
-  }
-
-  // The com.android.tools files are only used outside Google, in Gradle projects.
-  @Test
-  public void checkProguardRules() {
-    URL resUrl =
-        AndroidInjectionKeys.class
-            .getClassLoader()
-            .getResource("META-INF/com.android.tools/proguard/dagger-android.pro");
-    assertThat(resUrl).isNotNull();
-  }
-
-  @Test
-  public void checkR8Rules() {
-    URL resUrl =
-        AndroidInjectionKeys.class
-            .getClassLoader()
-            .getResource("META-INF/com.android.tools/r8/dagger-android.pro");
-    assertThat(resUrl).isNotNull();
-  }
-}
diff --git a/javatests/dagger/android/BUILD b/javatests/dagger/android/BUILD
index 38efb3a..5bc3f45 100644
--- a/javatests/dagger/android/BUILD
+++ b/javatests/dagger/android/BUILD
@@ -15,11 +15,11 @@
 # Description:
 #   Tests for Dagger's Android integrations
 
+package(default_visibility = ["//:src"])
+
 load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
 load("//:test_defs.bzl", "GenRobolectricTests")
 
-package(default_visibility = ["//:src"])
-
 GenRobolectricTests(
     name = "android_tests",
     srcs = glob(["*.java"]),
@@ -29,7 +29,7 @@
     deps = [
         "//:dagger_with_compiler",
         "//java/dagger/android",
-        "//java/dagger/internal/guava:collect",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/junit",
         "@google_bazel_common//third_party/java/truth",
     ],
diff --git a/javatests/dagger/android/DispatchingAndroidInjectorTest.java b/javatests/dagger/android/DispatchingAndroidInjectorTest.java
index 37d3d61..d0306b8 100644
--- a/javatests/dagger/android/DispatchingAndroidInjectorTest.java
+++ b/javatests/dagger/android/DispatchingAndroidInjectorTest.java
@@ -29,7 +29,9 @@
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 
+@Config(manifest = Config.NONE)
 @RunWith(RobolectricTestRunner.class)
 public final class DispatchingAndroidInjectorTest {
   @Test
diff --git a/javatests/dagger/android/processor/AndroidProcessorTest.java b/javatests/dagger/android/processor/AndroidProcessorTest.java
new file mode 100644
index 0000000..1a45bdd
--- /dev/null
+++ b/javatests/dagger/android/processor/AndroidProcessorTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2017 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.android.processor;
+
+import static com.google.common.truth.Truth8.assertThat;
+import static com.google.testing.compile.CompilationSubject.assertThat;
+import static com.google.testing.compile.Compiler.javac;
+import static javax.tools.StandardLocation.CLASS_OUTPUT;
+
+import com.google.testing.compile.Compilation;
+import com.google.testing.compile.JavaFileObjects;
+import javax.tools.JavaFileObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class AndroidProcessorTest {
+  @Test
+  public void generatedProguardFile() {
+    JavaFileObject module =
+        JavaFileObjects.forSourceLines(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.android.AndroidInjectionKey;",
+            "import dagger.Module;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class TestModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @AndroidInjectionKey(\"test.TestActivity\")",
+            "  static int i() { ",
+            "    return 1;",
+            "  }",
+            "}");
+    Compilation enabled =
+        javac()
+            .withProcessors(new AndroidProcessor())
+            .withOptions("-Adagger.android.experimentalUseStringKeys=true")
+            .compile(module);
+    assertThat(enabled).succeeded();
+    assertThat(enabled)
+        .generatedFile(CLASS_OUTPUT, "META-INF/proguard/dagger.android.AndroidInjectionKeys");
+
+    Compilation disabled =
+        javac()
+            .withProcessors(new AndroidProcessor())
+            .withOptions("-Adagger.android.experimentalUseStringKeys=false")
+            .compile(module);
+    assertThat(disabled).succeeded();
+    assertThat(
+            disabled.generatedFile(
+                CLASS_OUTPUT, "META-INF/proguard/dagger.android.AndroidInjectionKeys"))
+        .isEmpty();
+
+    Compilation noFlag = javac().withProcessors(new AndroidProcessor()).compile(module);
+    assertThat(noFlag).succeeded();
+    assertThat(
+            noFlag.generatedFile(
+                CLASS_OUTPUT, "META-INF/proguard/dagger.android.AndroidInjectionKeys"))
+        .isEmpty();
+  }
+}
diff --git a/javatests/dagger/android/processor/BUILD b/javatests/dagger/android/processor/BUILD
index d7b210c..8a9c16e 100644
--- a/javatests/dagger/android/processor/BUILD
+++ b/javatests/dagger/android/processor/BUILD
@@ -15,27 +15,28 @@
 # Description:
 #   Tests for Dagger's Android integrations
 
+package(default_visibility = ["//:src"])
+
 load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "android_processor_tests",
     srcs = glob(["*.java"]),
     functional = False,
     javacopts = DOCLINT_HTML_AND_SYNTAX,
     deps = [
+        "@google_bazel_common//third_party/java/guava",
+        "@androidsdk//com.android.support:support-fragment-25.0.0",
+        # TODO(ronshapiro): create a common location to define the current Android version
+        "@androidsdk//:platforms/android-26/android.jar",
+        "@google_bazel_common//third_party/java/compile_testing",
         "//:dagger_with_compiler",
+        "@google_bazel_common//third_party/java/junit",
+        "@google_bazel_common//third_party/java/truth",
+        "@google_bazel_common//third_party/java/truth:truth8",
         "//java/dagger/android",
         "//java/dagger/android/processor",
         "//java/dagger/internal/codegen:processor",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@androidsdk//:platforms/android-30/android.jar",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-        "@maven//:androidx_fragment_fragment",
     ],
 )
diff --git a/javatests/dagger/android/support/AndroidSupportInjectionTest.java b/javatests/dagger/android/support/AndroidSupportInjectionTest.java
index 25c5e94..51e9992 100644
--- a/javatests/dagger/android/support/AndroidSupportInjectionTest.java
+++ b/javatests/dagger/android/support/AndroidSupportInjectionTest.java
@@ -20,15 +20,15 @@
 import static org.junit.Assert.fail;
 
 import android.app.Application;
-import androidx.fragment.app.Fragment;
+import android.support.v4.app.Fragment;
 import dagger.android.AndroidInjector;
-import dagger.android.HasAndroidInjector;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.support.v4.SupportFragmentTestUtil;
 
+@Config(manifest = Config.NONE)
 @RunWith(RobolectricTestRunner.class)
 public final class AndroidSupportInjectionTest {
   @Test
@@ -45,15 +45,15 @@
   }
 
   private static class ApplicationReturnsNull extends Application
-      implements HasAndroidInjector {
+      implements HasSupportFragmentInjector {
     @Override
-    public AndroidInjector<Object> androidInjector() {
+    public AndroidInjector<Fragment> supportFragmentInjector() {
       return null;
     }
   }
 
   @Test
-  @Config(application = ApplicationReturnsNull.class)
+  @Config(manifest = Config.NONE, application = ApplicationReturnsNull.class)
   public void fragmentInjector_returnsNull() {
     Fragment fragment = new Fragment();
     SupportFragmentTestUtil.startFragment(fragment);
@@ -62,7 +62,7 @@
       AndroidSupportInjection.inject(fragment);
       fail();
     } catch (Exception e) {
-      assertThat(e).hasMessageThat().contains("androidInjector() returned null");
+      assertThat(e).hasMessageThat().contains("supportFragmentInjector() returned null");
     }
   }
 
diff --git a/javatests/dagger/android/support/BUILD b/javatests/dagger/android/support/BUILD
index 6bbfaa1..6d8f43b 100644
--- a/javatests/dagger/android/support/BUILD
+++ b/javatests/dagger/android/support/BUILD
@@ -15,11 +15,11 @@
 # Description:
 #   Tests for Dagger's Android and Support library integrations
 
+package(default_visibility = ["//:src"])
+
 load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
 load("//:test_defs.bzl", "GenRobolectricTests")
 
-package(default_visibility = ["//:src"])
-
 GenRobolectricTests(
     name = "android-support-tests",
     srcs = glob(["*.java"]),
@@ -29,12 +29,10 @@
         "//:dagger_with_compiler",
         "//java/dagger/android",
         "//java/dagger/android/support",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
+        "@androidsdk//com.android.support:appcompat-v7-25.0.0",
+        "@androidsdk//com.android.support:support-fragment-25.0.0",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/junit",
         "@google_bazel_common//third_party/java/truth",
-        "@maven//:androidx_appcompat_appcompat",
-        "@maven//:androidx_fragment_fragment",
     ],
 )
diff --git a/javatests/dagger/android/support/functional/AndroidManifest.xml b/javatests/dagger/android/support/functional/AndroidManifest.xml
index 0b5f4cd..2e40a35 100644
--- a/javatests/dagger/android/support/functional/AndroidManifest.xml
+++ b/javatests/dagger/android/support/functional/AndroidManifest.xml
@@ -16,8 +16,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="dagger.android.support.functional">
 
-  <!-- Bump targetSdk to 29 when we update to Java 11 -->
-  <uses-sdk android:minSdkVersion="1" android:targetSdkVersion="28" />
+  <uses-sdk android:minSdkVersion="1" android:targetSdkVersion="26" />
 
   <application android:theme="@style/Theme.AppCompat"
       android:name=".UsesGeneratedModulesApplication">
diff --git a/javatests/dagger/android/support/functional/BUILD b/javatests/dagger/android/support/functional/BUILD
index 1ae1108..130b971 100644
--- a/javatests/dagger/android/support/functional/BUILD
+++ b/javatests/dagger/android/support/functional/BUILD
@@ -15,8 +15,6 @@
 # Description:
 #   Functional test code for Dagger-Android
 
-load("//:test_defs.bzl", "GenRobolectricTests")
-
 package(default_visibility = ["//:src"])
 
 android_library(
@@ -29,10 +27,9 @@
     manifest = "AndroidManifest.xml",
     resource_files = glob(["res/**"]),
     deps = [
-        "@maven//:androidx_fragment_fragment",
-        "@maven//:androidx_appcompat_appcompat",
-        "@maven//:androidx_annotation_annotation",
-        "//java/dagger/internal/guava:collect-android",
+        "@androidsdk//com.android.support:support-fragment-25.0.0",
+        "@androidsdk//com.android.support:appcompat-v7-25.0.0",
+        "@google_bazel_common//third_party/java/guava",
         "//:dagger_with_compiler",
         "//:android",
         "//:android-support",
@@ -41,6 +38,8 @@
     ],
 )
 
+load("//:test_defs.bzl", "GenRobolectricTests")
+
 GenRobolectricTests(
     name = "functional_tests",
     srcs = glob(["*Test.java"]),
@@ -49,9 +48,9 @@
         "//:android",
         "//:android-support",
         "//:dagger_with_compiler",
+        "@androidsdk//com.android.support:support-fragment-25.0.0",
+        "@google_bazel_common//third_party/java/junit",
+        "@google_bazel_common//third_party/java/robolectric",
         "@google_bazel_common//third_party/java/truth",
-        "@maven//:androidx_fragment_fragment",
-        "@maven//:junit_junit",
-        "@maven//:org_robolectric_robolectric",
     ],
 )
diff --git a/javatests/dagger/android/support/functional/InjectorsTest.java b/javatests/dagger/android/support/functional/InjectorsTest.java
index 73bb98a..c5cb150 100644
--- a/javatests/dagger/android/support/functional/InjectorsTest.java
+++ b/javatests/dagger/android/support/functional/InjectorsTest.java
@@ -20,12 +20,12 @@
 
 import android.content.Intent;
 import android.content.res.Configuration;
-import androidx.test.core.app.ApplicationProvider;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.android.controller.ActivityController;
 import org.robolectric.annotation.Config;
 
@@ -59,7 +59,7 @@
     intentService = Robolectric.buildIntentService(TestIntentService.class).create().get();
 
     broadcastReceiver = new TestBroadcastReceiver();
-    broadcastReceiver.onReceive(ApplicationProvider.getApplicationContext(), new Intent());
+    broadcastReceiver.onReceive(RuntimeEnvironment.application, new Intent());
 
     contentProvider = Robolectric.setupContentProvider(TestContentProvider.class);
   }
diff --git a/javatests/dagger/android/support/functional/TestContentProvider.java b/javatests/dagger/android/support/functional/TestContentProvider.java
index aff8961..1668ce6 100644
--- a/javatests/dagger/android/support/functional/TestContentProvider.java
+++ b/javatests/dagger/android/support/functional/TestContentProvider.java
@@ -19,7 +19,7 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
-import androidx.annotation.Nullable;
+import android.support.annotation.Nullable;
 import dagger.android.DaggerContentProvider;
 import java.util.Set;
 import javax.inject.Inject;
diff --git a/javatests/dagger/functional/BUILD b/javatests/dagger/functional/BUILD
index 8e6a555..f417bec 100644
--- a/javatests/dagger/functional/BUILD
+++ b/javatests/dagger/functional/BUILD
@@ -15,11 +15,15 @@
 # Description:
 #   Functional tests for Dagger
 
-load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "SOURCE_7_TARGET_7")
-load("//:test_defs.bzl", "GenJavaTests")
-
 package(default_visibility = ["//:src"])
 
+load(
+    "//:build_defs.bzl",
+    "DOCLINT_HTML_AND_SYNTAX",
+    "SOURCE_7_TARGET_7",
+)
+load("//:test_defs.bzl", "GenJavaTests")
+
 GenJavaTests(
     name = "functional_tests",
     srcs = glob(
@@ -27,16 +31,14 @@
     ),
     javacopts = DOCLINT_HTML_AND_SYNTAX,
     lib_javacopts = SOURCE_7_TARGET_7,
+    # NOTE: This should not depend on Guava or jsr305 to ensure that Dagger can be
+    # used without Guava and jsr305 deps.
     test_only_deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
         "@google_bazel_common//third_party/java/guava:testlib",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/truth",
         "@google_bazel_common//third_party/java/junit",
     ],
-    # NOTE: This should not depend on Guava or jsr305 to ensure that Dagger can be
-    # used without Guava and jsr305 deps.
     deps = [
         "//:dagger_with_compiler",
         "@google_bazel_common//third_party/java/auto:factory",
diff --git a/javatests/dagger/functional/BoundedGenerics.java b/javatests/dagger/functional/BoundedGenerics.java
index d514337..812cd04 100644
--- a/javatests/dagger/functional/BoundedGenerics.java
+++ b/javatests/dagger/functional/BoundedGenerics.java
@@ -19,7 +19,6 @@
 import java.util.List;
 import javax.inject.Inject;
 
-
 class BoundedGenerics<A extends Number & Comparable<? super A>, 
       B extends List<? extends CharSequence>,
       C extends List<? super String>,
diff --git a/javatests/dagger/functional/ComponentDependenciesTest.java b/javatests/dagger/functional/ComponentDependenciesTest.java
deleted file mode 100644
index 502c51d..0000000
--- a/javatests/dagger/functional/ComponentDependenciesTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/**
- * Tests component dependencies.
- */
-@RunWith(JUnit4.class)
-public final class ComponentDependenciesTest {
-  public interface One {
-    String getString();
-  }
-
-  public interface Two {
-    String getString();
-  }
-
-  public interface Merged extends One, Two {
-  }
-
-  @Component(dependencies = Merged.class)
-  interface TestComponent {
-    String getString();
-
-    @Component.Builder
-    interface Builder {
-      Builder dep(Merged dep);
-
-      TestComponent build();
-    }
-  }
-
-  @Test
-  public void testSameMethodTwice() throws Exception {
-    TestComponent component =
-        DaggerComponentDependenciesTest_TestComponent.builder().dep(() -> "test").build();
-    assertThat(component.getString()).isEqualTo("test");
-  }
-
-  public interface OneOverride {
-    Object getString();
-  }
-
-  public interface TwoOverride {
-    Object getString();
-  }
-
-  public interface MergedOverride extends OneOverride, TwoOverride {
-    @Override
-    String getString();
-  }
-
-  @Component(dependencies = MergedOverride.class)
-  interface TestOverrideComponent {
-    String getString();
-
-    @Component.Builder
-    interface Builder {
-      Builder dep(MergedOverride dep);
-
-      TestOverrideComponent build();
-    }
-  }
-
-  @Test
-  public void testPolymorphicOverridesStillCompiles() throws Exception {
-    TestOverrideComponent component =
-        DaggerComponentDependenciesTest_TestOverrideComponent.builder().dep(() -> "test").build();
-    assertThat(component.getString()).isEqualTo("test");
-  }
-}
diff --git a/javatests/dagger/functional/Generic2.java b/javatests/dagger/functional/Generic2.java
index 40ef546..f53c0f8 100644
--- a/javatests/dagger/functional/Generic2.java
+++ b/javatests/dagger/functional/Generic2.java
@@ -18,7 +18,6 @@
 
 import javax.inject.Inject;
 
-
 public class Generic2<T> {
   final T t;
 
diff --git a/javatests/dagger/functional/GenericNoDeps.java b/javatests/dagger/functional/GenericNoDeps.java
index 0e3d41b..c3f38b4 100644
--- a/javatests/dagger/functional/GenericNoDeps.java
+++ b/javatests/dagger/functional/GenericNoDeps.java
@@ -18,7 +18,6 @@
 
 import javax.inject.Inject;
 
-
 class GenericNoDeps<T> {
   
   @Inject GenericNoDeps() {}
diff --git a/javatests/dagger/functional/MultibindingTest.java b/javatests/dagger/functional/MultibindingTest.java
index 3da3901..d99e46d 100644
--- a/javatests/dagger/functional/MultibindingTest.java
+++ b/javatests/dagger/functional/MultibindingTest.java
@@ -80,7 +80,7 @@
 
   @Test
   public void wrappedAnnotationKeyMap() {
-    @SuppressWarnings({"unchecked", "rawtypes"})
+    @SuppressWarnings("unchecked")
     Class<? extends Number>[] classes = new Class[] {Long.class, Integer.class};
     assertThat(multibindingComponent.wrappedAnnotationKeyMap())
         .containsExactly(
diff --git a/javatests/dagger/functional/NeedsFactory.java b/javatests/dagger/functional/NeedsFactory.java
index 14ab134..2ea01ec 100644
--- a/javatests/dagger/functional/NeedsFactory.java
+++ b/javatests/dagger/functional/NeedsFactory.java
@@ -19,19 +19,11 @@
 import com.google.auto.factory.AutoFactory;
 import javax.inject.Inject;
 
-public class NeedsFactory {
+class NeedsFactory {
   @Inject
-  NeedsFactory(
-      @SuppressWarnings("unused") NeedsFactory_SomethingFactory somethingFactory,
-      @SuppressWarnings("unused") SomethingFactoryImpl somethingFactoryImpl) {}
+  NeedsFactory(@SuppressWarnings("unused") NeedsFactory_SomethingFactory somethingFactory) {}
 
-  public interface SomethingFactory {}
-
-  @AutoFactory(implementing = SomethingFactory.class, allowSubclasses = true)
+  @AutoFactory
   static class Something {}
-
-  public static final class SomethingFactoryImpl extends NeedsFactory_SomethingFactory {
-    @Inject SomethingFactoryImpl() {}
-  }
 }
 
diff --git a/javatests/dagger/functional/NeedsProviderOfFactory.java b/javatests/dagger/functional/NeedsProviderOfFactory.java
index 1ae797e..efbd73d 100644
--- a/javatests/dagger/functional/NeedsProviderOfFactory.java
+++ b/javatests/dagger/functional/NeedsProviderOfFactory.java
@@ -26,8 +26,7 @@
   static class InjectsProviderOfFactory {
     @Inject
     InjectsProviderOfFactory(
-        Provider<NeedsProviderOfFactory_SomethingFactory> somethingFactoryProvider,
-        Provider<SomethingFactoryImpl> somethingFactoryImplProvider) {}
+        Provider<NeedsProviderOfFactory_SomethingFactory> provider) {}
   }
 
   @Component
@@ -35,12 +34,6 @@
     InjectsProviderOfFactory injectsProviderOfFactory();
   }
 
-  interface SomethingFactory {}
-
-  @AutoFactory(implementing = SomethingFactory.class, allowSubclasses = true)
+  @AutoFactory
   static class Something {}
-
-  static final class SomethingFactoryImpl extends NeedsProviderOfFactory_SomethingFactory {
-    @Inject SomethingFactoryImpl() {}
-  }
 }
diff --git a/javatests/dagger/functional/aot/DependsOnMissingArrayKey.java b/javatests/dagger/functional/aot/DependsOnMissingArrayKey.java
new file mode 100644
index 0000000..20a89d4
--- /dev/null
+++ b/javatests/dagger/functional/aot/DependsOnMissingArrayKey.java
@@ -0,0 +1,40 @@
+/*
+ * 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.functional.aot;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.Subcomponent;
+
+/**
+ * Regression test for an ahead-of-time subcomponents bug where generating the name for a missing
+ * binding method for a key of an array type threw an exception.
+ */
+final class DependsOnMissingArrayKey {
+  @Module
+  abstract static class ModuleArrayDependencies {
+    @Provides
+    static int dependsOnMissingArrayType(int[] primitive, Object[] object, String[][] doubleArray) {
+      return 0;
+    }
+  }
+
+  @Subcomponent(modules = ModuleArrayDependencies.class)
+  interface HasMissingArrayBindings {
+    int dependsOnMissingArrayType();
+  }
+}
diff --git a/javatests/dagger/functional/aot/MapFrameworkInstanceWithContributionsInMultipleImplementationsTest.java b/javatests/dagger/functional/aot/MapFrameworkInstanceWithContributionsInMultipleImplementationsTest.java
new file mode 100644
index 0000000..ae6b3a4
--- /dev/null
+++ b/javatests/dagger/functional/aot/MapFrameworkInstanceWithContributionsInMultipleImplementationsTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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.functional.aot;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+import dagger.Subcomponent;
+import dagger.multibindings.IntoMap;
+import dagger.multibindings.StringKey;
+import java.util.Map;
+import javax.inject.Provider;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests that framework instances of map bindings are properly instantiated in ahead-of-time mode
+ * when contributions are made in 3 or more implementations.
+ */
+@RunWith(JUnit4.class)
+public final class MapFrameworkInstanceWithContributionsInMultipleImplementationsTest {
+  @Subcomponent(modules = LeafModule.class)
+  interface Leaf {
+    Provider<Map<String, String>> providerOfMapOfValues();
+    Provider<Map<String, Provider<String>>> providerOfMapOfProviders();
+  }
+
+  @Module
+  interface LeafModule {
+    @Provides
+    @IntoMap
+    @StringKey("a")
+    static String fromLeaf() {
+      return "a";
+    }
+  }
+
+  @Subcomponent(modules = AncestorModule.class)
+  interface Ancestor {
+    Leaf leaf();
+  }
+
+  @Module
+  interface AncestorModule {
+    @Provides
+    @IntoMap
+    @StringKey("b")
+    static String fromAncestor() {
+      return "b";
+    }
+  }
+
+  @Component(modules = RootModule.class)
+  interface Root {
+    Ancestor ancestor();
+  }
+
+  @Module
+  interface RootModule {
+    @Provides
+    @IntoMap
+    @StringKey("c")
+    static String fromRoot() {
+      return "c";
+    }
+  }
+
+  @Test
+  public void mapFactoryCanBeInstantiatedAcrossComponentImplementations() {
+    Leaf leaf =
+        DaggerMapFrameworkInstanceWithContributionsInMultipleImplementationsTest_Root.create()
+            .ancestor()
+            .leaf();
+    assertThat(leaf.providerOfMapOfValues().get()).hasSize(3);
+    assertThat(leaf.providerOfMapOfProviders().get()).hasSize(3);
+  }
+}
diff --git a/javatests/dagger/functional/aot/MissingBindingReplacedWithGeneratedInstance.java b/javatests/dagger/functional/aot/MissingBindingReplacedWithGeneratedInstance.java
new file mode 100644
index 0000000..1813ad2
--- /dev/null
+++ b/javatests/dagger/functional/aot/MissingBindingReplacedWithGeneratedInstance.java
@@ -0,0 +1,56 @@
+/*
+ * 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.functional.aot;
+
+import dagger.Subcomponent;
+import javax.inject.Inject;
+
+/**
+ * This class demonstrates a regression where a missing binding method was generated in a leaf
+ * component and then satisfied in an ancestor with a generated instance binding. If the ancestor's
+ * generated instance method had the same name as the formerly-missing binding method, Dagger would
+ * generate code without a proper {@code DaggerOuter.this} reference:
+ *
+ * <pre>{@code
+ * public class DaggerAncestor implements Ancestor {
+ *   protected abstract Ancestor getAncestor();
+ *
+ *   protected abstract class LeafImpl extends DaggerLeaf {
+ *     {@literal @Override}
+ *     protected final Ancestor getAncestor() {
+ *       return getAncestor();
+ *       //     ^ should be DaggerAncestor.this.getAncestor()
+ *     }
+ *   }
+ * }
+ * }</pre>
+ */
+final class MissingBindingReplacedWithGeneratedInstance {
+  @Subcomponent
+  interface Leaf {
+    DependsOnGeneratedInstance dependsOnGeneratedInstance();
+  }
+
+  static class DependsOnGeneratedInstance {
+    @Inject DependsOnGeneratedInstance(Ancestor generatedInstance) {}
+  }
+
+  @Subcomponent
+  interface Ancestor {
+    Leaf child();
+  }
+}
diff --git a/javatests/dagger/functional/aot/ModifiedFrameworkInstancesTest.java b/javatests/dagger/functional/aot/ModifiedFrameworkInstancesTest.java
new file mode 100644
index 0000000..7084f83
--- /dev/null
+++ b/javatests/dagger/functional/aot/ModifiedFrameworkInstancesTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.functional.aot;
+
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+import dagger.Subcomponent;
+import dagger.multibindings.IntoSet;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ModifiedFrameworkInstancesTest {
+  static class DependsOnModifiableBinding {
+    @Inject
+    DependsOnModifiableBinding(Set<Integer> modifiableDependency) {}
+  }
+
+  @Module
+  interface ChildModule {
+    @Provides
+    @IntoSet
+    static int contribution() {
+      return 1;
+    }
+  }
+
+  @Subcomponent(modules = ChildModule.class)
+  interface Child {
+    Provider<DependsOnModifiableBinding> frameworkInstanceWithModifiedDependency();
+  }
+
+  @Module
+  interface ParentModule {
+    @Provides
+    @IntoSet
+    static int contribution() {
+      return 2;
+    }
+  }
+
+  @Component(modules = ParentModule.class)
+  interface Parent {
+    Child child();
+  }
+
+  @Test
+  public void dependsOnModifiedFrameworkInstance() {
+    DaggerModifiedFrameworkInstancesTest_Parent.create()
+        .child()
+        .frameworkInstanceWithModifiedDependency()
+        // Ensure that modified framework instances that are dependencies to other framework 
+        // instances from superclass implementations are initialized correctly. This fixes a
+        // regression where a null instance would be passed to the superclass initialization, and
+        // then a NullPointerException would be thrown when the factory attempted to satisfy the
+        // dependency in get(). If get() succeeds, this test should pass.
+        .get();
+  }
+}
diff --git a/javatests/dagger/functional/aot/PrunedBindingDependedOnInSuperInitializationTest.java b/javatests/dagger/functional/aot/PrunedBindingDependedOnInSuperInitializationTest.java
new file mode 100644
index 0000000..853e22b
--- /dev/null
+++ b/javatests/dagger/functional/aot/PrunedBindingDependedOnInSuperInitializationTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.functional.aot;
+
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+import dagger.Subcomponent;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class PrunedBindingDependedOnInSuperInitializationTest {
+  interface PrunedDependency {}
+
+  static class WillHavePrunedDependency {
+    @Inject WillHavePrunedDependency(PrunedDependency pruned) {}
+  }
+
+  @Subcomponent
+  interface Child {
+    Provider<WillHavePrunedDependency> frameworkInstance();
+  }
+
+  @Module
+  static class ParentModule {
+    @Provides
+    static WillHavePrunedDependency pruneDependency() {
+      return new WillHavePrunedDependency(new PrunedDependency() {});
+    }
+  }
+
+  @Component(modules = ParentModule.class)
+  interface Parent {
+    Child child();
+  }
+
+  @Test
+  public void prunedFrameworkInstanceBindingUsedInInitializationDoesntThrow() {
+    Parent parent = DaggerPrunedBindingDependedOnInSuperInitializationTest_Parent.create();
+    // This test ensures that pruned bindings that are used during unpruned initialization
+    // statements do not throw exceptions. If the subcomponent initialization succeeds, the test
+    // should pass
+    parent.child();
+  }
+}
diff --git a/javatests/dagger/functional/aot/PrunedFrameworkInstanceWithModuleInstanceTest.java b/javatests/dagger/functional/aot/PrunedFrameworkInstanceWithModuleInstanceTest.java
new file mode 100644
index 0000000..f995789
--- /dev/null
+++ b/javatests/dagger/functional/aot/PrunedFrameworkInstanceWithModuleInstanceTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 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.functional.aot;
+
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+import dagger.Subcomponent;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class PrunedFrameworkInstanceWithModuleInstanceTest {
+  static class Pruned {}
+
+  static class InjectsPruned {
+    @Inject
+    InjectsPruned(Provider<Pruned> pruned) {}
+  }
+
+  @Module
+  static class InstanceStateModule {
+    @Provides
+    /* intentionally not static */ Pruned pruned() {
+      return new Pruned();
+    }
+  }
+
+  @Subcomponent(modules = InstanceStateModule.class)
+  interface LeafWithoutCreator {
+    InjectsPruned injectsPruned();
+  }
+
+  @Subcomponent(modules = InstanceStateModule.class)
+  interface LeafWithCreator {
+    InjectsPruned injectsPruned();
+
+    @Subcomponent.Builder
+    interface Builder {
+      Builder module(InstanceStateModule module);
+      LeafWithCreator build();
+    }
+  }
+
+  @Module
+  interface RootModule {
+    @Provides
+    static InjectsPruned pruneBindingWithInstanceState() {
+      return new InjectsPruned(null);
+    }
+  }
+
+  @Component(modules = RootModule.class)
+  interface Root {
+    LeafWithoutCreator leafWithoutCreator(InstanceStateModule pruned);
+    LeafWithCreator.Builder leafWithCreator();
+  }
+
+  @Test
+  public void prunedBindingWithModuleInstance_doesntThrowDuringInitialization() {
+    Root root = DaggerPrunedFrameworkInstanceWithModuleInstanceTest_Root.create();
+
+    Object unused = root.leafWithoutCreator(new InstanceStateModule()).injectsPruned();
+    unused = root.leafWithCreator().module(new InstanceStateModule()).build().injectsPruned();
+  }
+}
diff --git a/javatests/dagger/functional/aot/ScopedBindsWithMissingDependency.java b/javatests/dagger/functional/aot/ScopedBindsWithMissingDependency.java
new file mode 100644
index 0000000..2723ac0
--- /dev/null
+++ b/javatests/dagger/functional/aot/ScopedBindsWithMissingDependency.java
@@ -0,0 +1,55 @@
+/*
+ * 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.functional.aot;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Reusable;
+import dagger.Subcomponent;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.inject.Scope;
+
+/**
+ * A regression test for ahead-of-time subcomponents mode where a scoped {@link Binds} method whose
+ * dependency was missing in a partial subcomponent implementation threw an exception in the
+ * processor.
+ */
+final class ScopedBindsWithMissingDependency {
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @Scope
+  @interface CustomScope {}
+
+  @Module
+  interface ScopedBindsWithMissingDependencyModule {
+    @Binds
+    @CustomScope
+    Object bindsCustomScopeToMissingDep(String missingDependency);
+
+    @Binds
+    @Reusable
+    CharSequence bindsReusableScopeToMissingDep(String missingDependency);
+  }
+
+  @CustomScope
+  @Subcomponent(modules = ScopedBindsWithMissingDependencyModule.class)
+  interface HasScopedBindsWithMissingDependency {
+    Object customScopedBindsWithMissingDependency();
+    CharSequence reusableScopedBindsWithMissingDependency();
+  }
+}
diff --git a/javatests/dagger/functional/aot/SubcomponentWithInaccessibleMissingBindingMethod.java b/javatests/dagger/functional/aot/SubcomponentWithInaccessibleMissingBindingMethod.java
new file mode 100644
index 0000000..689689c
--- /dev/null
+++ b/javatests/dagger/functional/aot/SubcomponentWithInaccessibleMissingBindingMethod.java
@@ -0,0 +1,27 @@
+/*
+ * 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.functional.aot;
+
+import dagger.Subcomponent;
+import dagger.functional.aot.sub.PublicTypeWithPackagePrivateMissingDep;
+import javax.inject.Provider;
+
+@Subcomponent
+interface SubcomponentWithInaccessibleMissingBindingMethod {
+  PublicTypeWithPackagePrivateMissingDep instance();
+  Provider<PublicTypeWithPackagePrivateMissingDep> frameworkInstance();
+}
diff --git a/javatests/dagger/functional/aot/SubcomponentWithModifiedInaccessibleDependency.java b/javatests/dagger/functional/aot/SubcomponentWithModifiedInaccessibleDependency.java
new file mode 100644
index 0000000..06cebb9
--- /dev/null
+++ b/javatests/dagger/functional/aot/SubcomponentWithModifiedInaccessibleDependency.java
@@ -0,0 +1,32 @@
+/*
+ * 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.functional.aot;
+
+import dagger.Subcomponent;
+import dagger.functional.aot.sub.BindsPackagePrivateModule;
+import dagger.functional.aot.sub.SubcomponentWithInaccessibleOptionalBindingMethod;
+
+/**
+ * See {@link dagger.functional.aot.sub.SubcomponentWithInaccessibleOptionalBindingMethod}. This
+ * subcomponent will induce a modified binding method for its single child for the key {@code
+ * Optional<dagger.functional.aot.sub.PackagePrivate>}. When it tries to reimplement it, it must use
+ * the publicly accessible type.
+ */
+@Subcomponent(modules = BindsPackagePrivateModule.class)
+interface SubcomponentWithModifiedInaccessibleDependency {
+  SubcomponentWithInaccessibleOptionalBindingMethod child();
+}
diff --git a/javatests/dagger/functional/aot/sub/BindsPackagePrivateModule.java b/javatests/dagger/functional/aot/sub/BindsPackagePrivateModule.java
new file mode 100644
index 0000000..2eee3c9
--- /dev/null
+++ b/javatests/dagger/functional/aot/sub/BindsPackagePrivateModule.java
@@ -0,0 +1,28 @@
+/*
+ * 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.functional.aot.sub;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public final class BindsPackagePrivateModule {
+  @Provides
+  static PackagePrivate packagePrivate() {
+    return new PackagePrivate();
+  }
+}
diff --git a/javatests/dagger/functional/aot/sub/PackagePrivate.java b/javatests/dagger/functional/aot/sub/PackagePrivate.java
new file mode 100644
index 0000000..c629f6e
--- /dev/null
+++ b/javatests/dagger/functional/aot/sub/PackagePrivate.java
@@ -0,0 +1,19 @@
+/*
+ * 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.functional.aot.sub;
+
+final class PackagePrivate {}
diff --git a/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateMissingDep.java b/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateMissingDep.java
new file mode 100644
index 0000000..b5ced6f
--- /dev/null
+++ b/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateMissingDep.java
@@ -0,0 +1,24 @@
+/*
+ * 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.functional.aot.sub;
+
+import javax.inject.Inject;
+
+public class PublicTypeWithPackagePrivateMissingDep {
+  @Inject
+  PublicTypeWithPackagePrivateMissingDep(PackagePrivate packagePrivate) {}
+}
diff --git a/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateOptionalDep.java b/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateOptionalDep.java
new file mode 100644
index 0000000..1d69723
--- /dev/null
+++ b/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateOptionalDep.java
@@ -0,0 +1,25 @@
+/*
+ * 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.functional.aot.sub;
+
+import java.util.Optional;
+import javax.inject.Inject;
+
+public class PublicTypeWithPackagePrivateOptionalDep {
+  @Inject
+  PublicTypeWithPackagePrivateOptionalDep(Optional<PackagePrivate> packagePrivateOptional) {}
+}
diff --git a/javatests/dagger/functional/aot/sub/SubcomponentWithInaccessibleOptionalBindingMethod.java b/javatests/dagger/functional/aot/sub/SubcomponentWithInaccessibleOptionalBindingMethod.java
new file mode 100644
index 0000000..d908b1c
--- /dev/null
+++ b/javatests/dagger/functional/aot/sub/SubcomponentWithInaccessibleOptionalBindingMethod.java
@@ -0,0 +1,43 @@
+/*
+ * 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.functional.aot.sub;
+
+import dagger.BindsOptionalOf;
+import dagger.Module;
+import dagger.Subcomponent;
+import dagger.functional.aot.sub.SubcomponentWithInaccessibleOptionalBindingMethod.ExposesModifiablePackagePrivateBindingModule;
+import javax.inject.Provider;
+
+/**
+ * This component will generate a modifiable binding method for the key {@code
+ * Optional<PackagePrivate>} as a dependency of {@link PublicTypeWithPackagePrivateOptionalDep}.
+ * Even though this subcomponent implementation can refer to the parameterized type, a subclass
+ * implementation in another package will not be able to, and thus the return type must be reduced
+ * to the publicly accessible type. This is exhibited in {@link
+ * dagger.functional.aot.SubcomponentWithModifiedInaccessibleDependency}.
+ */
+@Subcomponent(modules = ExposesModifiablePackagePrivateBindingModule.class)
+public interface SubcomponentWithInaccessibleOptionalBindingMethod {
+  PublicTypeWithPackagePrivateOptionalDep instance();
+  Provider<PublicTypeWithPackagePrivateOptionalDep> frameworkInstance();
+
+  @Module
+  interface ExposesModifiablePackagePrivateBindingModule {
+    @BindsOptionalOf
+    PackagePrivate optional();
+  }
+}
diff --git a/javatests/dagger/functional/assisted/AssistedFactoryBindsTest.java b/javatests/dagger/functional/assisted/AssistedFactoryBindsTest.java
deleted file mode 100644
index 78495b7..0000000
--- a/javatests/dagger/functional/assisted/AssistedFactoryBindsTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Binds;
-import dagger.Component;
-import dagger.Module;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import javax.inject.Inject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class AssistedFactoryBindsTest {
-  @Component(modules = FooFactoryModule.class)
-  interface ParentComponent {
-    // Test using @Binds where Foo => FooImpl and FooFactory => FooFactoryImpl
-    FooFactory fooFactory();
-  }
-
-  @Module
-  interface FooFactoryModule {
-    @Binds
-    FooFactory bind(FooFactoryImpl impl);
-  }
-
-  interface Foo {}
-
-  static final class FooImpl implements Foo {
-    private final Dep dep;
-    private final AssistedDep assistedDep;
-
-    @AssistedInject
-    FooImpl(Dep dep, @Assisted AssistedDep assistedDep) {
-      this.dep = dep;
-      this.assistedDep = assistedDep;
-    }
-  }
-
-  interface FooFactory {
-    Foo create(AssistedDep assistedDep);
-  }
-
-  @AssistedFactory
-  interface FooFactoryImpl extends FooFactory {
-    @Override
-    FooImpl create(AssistedDep assistedDep);
-  }
-
-  static final class AssistedDep {}
-
-  static final class Dep {
-    @Inject
-    Dep() {}
-  }
-
-  @Test
-  public void testFooFactory() {
-    FooFactory fooFactory = DaggerAssistedFactoryBindsTest_ParentComponent.create().fooFactory();
-    assertThat(fooFactory).isInstanceOf(FooFactoryImpl.class);
-
-    AssistedDep assistedDep = new AssistedDep();
-    Foo foo = fooFactory.create(assistedDep);
-    assertThat(foo).isInstanceOf(FooImpl.class);
-
-    FooImpl fooImpl = (FooImpl) foo;
-    assertThat(fooImpl.dep).isNotNull();
-    assertThat(fooImpl.assistedDep).isEqualTo(assistedDep);
-  }
-}
diff --git a/javatests/dagger/functional/assisted/AssistedFactoryInaccessibleTest.java b/javatests/dagger/functional/assisted/AssistedFactoryInaccessibleTest.java
deleted file mode 100644
index d586c61..0000000
--- a/javatests/dagger/functional/assisted/AssistedFactoryInaccessibleTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import dagger.assisted.AssistedFactory;
-import dagger.functional.assisted.subpackage.AccessibleFoo;
-import dagger.functional.assisted.subpackage.AssistedDep;
-import dagger.functional.assisted.subpackage.InaccessibleFooFactory;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class AssistedFactoryInaccessibleTest {
-  @Component
-  interface ParentComponent {
-    // Factory for an accessible type from another package
-    AccessibleFooFactory accessibleFooFactory();
-
-    // Factory for an inaccessible type from another package
-    InaccessibleFooFactory inaccessibleFooFactory();
-  }
-
-  @AssistedFactory
-  public interface AccessibleFooFactory {
-    // Use different parameter names than Foo to make sure we're not assuming they're the same.
-    AccessibleFoo create(AssistedDep factoryAssistedDep);
-  }
-
-  @Test
-  public void testAccessibleFooFactory() {
-    AssistedDep assistedDep = new AssistedDep();
-    AccessibleFoo accessibleFoo =
-        DaggerAssistedFactoryInaccessibleTest_ParentComponent.create()
-            .accessibleFooFactory()
-            .create(assistedDep);
-    assertThat(accessibleFoo).isNotNull();
-    assertThat(accessibleFoo.dep).isNotNull();
-    assertThat(accessibleFoo.assistedDep).isEqualTo(assistedDep);
-  }
-
-  @Test
-  public void testInaccessibleFooFactory() {
-    AssistedDep assistedDep = new AssistedDep();
-    // We can't access InaccessibleFoo directly, so just use Object instead.
-    Object inaccessibleFoo =
-        DaggerAssistedFactoryInaccessibleTest_ParentComponent.create()
-            .inaccessibleFooFactory()
-            .create(assistedDep);
-    assertThat(inaccessibleFoo).isNotNull();
-  }
-}
diff --git a/javatests/dagger/functional/assisted/AssistedFactoryParameterizedTest.java b/javatests/dagger/functional/assisted/AssistedFactoryParameterizedTest.java
deleted file mode 100644
index d079430..0000000
--- a/javatests/dagger/functional/assisted/AssistedFactoryParameterizedTest.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import javax.inject.Singleton;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class AssistedFactoryParameterizedTest {
-  @Singleton
-  @Component
-  interface ParentComponent {
-    // Tests a parameterized Factory with unique @Assisted types
-    ParameterizedFooFactory<Dep2, AssistedDep2> uniqueParameterizedFooFactory();
-
-    // Tests a parameterized Factory with duplicate @Assisted types in its resolved request type.
-    // Note: this is fine since the @Assisted types are still unique on the @AssistedInject and
-    // @AssistedFactory types, so that the generated code can correctly matches types.
-    ParameterizedFooFactory<Dep1, AssistedDep1> dupeParameterizedFooFactory();
-
-    // Tests a parameterized Factory with same type as binding
-    ParameterizedFooFactory<Dep1, Dep1> bindingParameterizedFooFactory();
-
-    // Tests a parameterized Factory with fixed type parameters
-    FixedParameterizedFooFactory fixedParameterizedFooFactory();
-
-    // Tests a parameterized Factory that extends an interface with a parameterized return type
-    ExtendedFooFactory<Dep2, AssistedDep2> extendedParameterizedFooFactory();
-
-    // Tests a request of factories from another binding.
-    SomeEntryPoint someEntryPoint();
-  }
-
-  static final class Dep1 {
-    @Inject
-    Dep1(Dep2 dep2, Dep3 dep3) {}
-  }
-
-  static final class Dep2 {
-    @Inject
-    Dep2(Dep3 dep3) {}
-  }
-
-  static final class Dep3 {
-    @Inject
-    Dep3(Dep4 dep4) {}
-  }
-
-  static final class Dep4 {
-    @Inject
-    Dep4() {}
-  }
-
-  // A base interface to test that factories can reference subclasses of the assisted parameter.
-  interface AssistedDep {}
-
-  static final class AssistedDep1 implements AssistedDep {}
-
-  static final class AssistedDep2 implements AssistedDep {}
-
-  abstract static class BaseFoo {
-    @Inject Dep4 dep4;
-  }
-
-  static final class ParameterizedFoo<DepT, AssistedDepT> extends BaseFoo {
-    private final Dep1 dep1;
-    private final Provider<DepT> depTProvider;
-    private final AssistedDep1 assistedDep1;
-    private final AssistedDepT assistedDepT;
-    private final int assistedInt;
-    private final ParameterizedFooFactory<DepT, AssistedDepT> factory;
-
-    @Inject Dep3 dep3;
-
-    @AssistedInject
-    ParameterizedFoo(
-        Dep1 dep1,
-        @Assisted AssistedDep1 assistedDep1,
-        Provider<DepT> depTProvider,
-        @Assisted AssistedDepT assistedDepT,
-        @Assisted int assistedInt,
-        ParameterizedFooFactory<DepT, AssistedDepT> factory) {
-      this.dep1 = dep1;
-      this.depTProvider = depTProvider;
-      this.assistedDep1 = assistedDep1;
-      this.assistedDepT = assistedDepT;
-      this.assistedInt = assistedInt;
-      this.factory = factory;
-    }
-  }
-
-  @AssistedFactory
-  interface ParameterizedFooFactory<DepT, AssistedDepT> {
-    ParameterizedFoo<DepT, AssistedDepT> create(
-        AssistedDep1 assistedDep1, AssistedDepT assistedDepT, int assistedInt);
-  }
-
-  @Test
-  public void testUniqueParameterizedFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    AssistedDep2 assistedDep2 = new AssistedDep2();
-    int assistedInt = 7;
-    ParameterizedFoo<Dep2, AssistedDep2> parameterizedFoo =
-        DaggerAssistedFactoryParameterizedTest_ParentComponent.create()
-            .uniqueParameterizedFooFactory()
-            .create(assistedDep1, assistedDep2, assistedInt);
-    assertThat(parameterizedFoo.dep1).isNotNull();
-    assertThat(parameterizedFoo.depTProvider).isNotNull();
-    assertThat(parameterizedFoo.depTProvider.get()).isNotNull();
-    assertThat(parameterizedFoo.dep3).isNotNull();
-    assertThat(parameterizedFoo.dep4).isNotNull();
-    assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1);
-    assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep2);
-    assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt);
-    assertThat(parameterizedFoo.factory).isNotNull();
-  }
-
-  @Test
-  public void testDupeParameterizedFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    int assistedInt = 7;
-    ParameterizedFoo<Dep1, AssistedDep1> parameterizedFoo =
-        DaggerAssistedFactoryParameterizedTest_ParentComponent.create()
-            .dupeParameterizedFooFactory()
-            .create(assistedDep1, assistedDep1, assistedInt);
-    assertThat(parameterizedFoo.dep1).isNotNull();
-    assertThat(parameterizedFoo.depTProvider).isNotNull();
-    assertThat(parameterizedFoo.depTProvider.get()).isNotNull();
-    assertThat(parameterizedFoo.dep3).isNotNull();
-    assertThat(parameterizedFoo.dep4).isNotNull();
-    assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1);
-    assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep1);
-    assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt);
-    assertThat(parameterizedFoo.factory).isNotNull();
-  }
-
-  @Test
-  public void testBindingParameterizedFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    Dep1 dep1 = new Dep1(new Dep2(new Dep3(new Dep4())), new Dep3(new Dep4()));
-    int assistedInt = 7;
-    ParameterizedFoo<Dep1, Dep1> parameterizedFoo =
-        DaggerAssistedFactoryParameterizedTest_ParentComponent.create()
-            .bindingParameterizedFooFactory()
-            .create(assistedDep1, dep1, assistedInt);
-    assertThat(parameterizedFoo.dep1).isNotNull();
-    assertThat(parameterizedFoo.depTProvider).isNotNull();
-    assertThat(parameterizedFoo.depTProvider.get()).isNotNull();
-    assertThat(parameterizedFoo.dep3).isNotNull();
-    assertThat(parameterizedFoo.dep4).isNotNull();
-    assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1);
-    assertThat(parameterizedFoo.assistedDepT).isEqualTo(dep1);
-    assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt);
-    assertThat(parameterizedFoo.factory).isNotNull();
-  }
-
-  @AssistedFactory
-  interface FixedParameterizedFooFactory {
-    ParameterizedFoo<Dep2, AssistedDep2> create(
-        AssistedDep1 assistedDep1, AssistedDep2 assistedDep2, int assistedInt);
-  }
-
-  @Test
-  public void testFixedParameterizedFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    AssistedDep2 assistedDep2 = new AssistedDep2();
-    int assistedInt = 7;
-    ParameterizedFoo<Dep2, AssistedDep2> parameterizedFoo =
-        DaggerAssistedFactoryParameterizedTest_ParentComponent.create()
-            .fixedParameterizedFooFactory()
-            .create(assistedDep1, assistedDep2, assistedInt);
-    assertThat(parameterizedFoo.dep1).isNotNull();
-    assertThat(parameterizedFoo.depTProvider).isNotNull();
-    assertThat(parameterizedFoo.depTProvider.get()).isNotNull();
-    assertThat(parameterizedFoo.dep3).isNotNull();
-    assertThat(parameterizedFoo.dep4).isNotNull();
-    assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1);
-    assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep2);
-    assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt);
-    assertThat(parameterizedFoo.factory).isNotNull();
-  }
-
-  interface ParameterizedFactory<ReturnT, DepT, AssistedDepT> {
-    // Use different parameter names than Foo to make sure we're not assuming they're the same.
-    ReturnT create(
-        AssistedDep1 factoryAssistedDep1, AssistedDepT factoryAssistedDepT, int factoryAssistedInt);
-  }
-
-  @AssistedFactory
-  interface ExtendedFooFactory<DepT, AssistedDepT>
-      extends ParameterizedFactory<ParameterizedFoo<DepT, AssistedDepT>, DepT, AssistedDepT> {}
-
-  @Test
-  public void testExtendedFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    AssistedDep2 assistedDep2 = new AssistedDep2();
-    int assistedInt = 7;
-    ParameterizedFoo<Dep2, AssistedDep2> parameterizedFoo =
-        DaggerAssistedFactoryParameterizedTest_ParentComponent.create()
-            .extendedParameterizedFooFactory()
-            .create(assistedDep1, assistedDep2, assistedInt);
-    assertThat(parameterizedFoo.dep1).isNotNull();
-    assertThat(parameterizedFoo.depTProvider).isNotNull();
-    assertThat(parameterizedFoo.depTProvider.get()).isNotNull();
-    assertThat(parameterizedFoo.dep3).isNotNull();
-    assertThat(parameterizedFoo.dep4).isNotNull();
-    assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1);
-    assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep2);
-    assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt);
-    assertThat(parameterizedFoo.factory).isNotNull();
-  }
-
-  static class SomeEntryPoint {
-    private final ParameterizedFooFactory<Dep1, AssistedDep1> dupeParameterizedFooFactory;
-
-    @Inject
-    SomeEntryPoint(ParameterizedFooFactory<Dep1, AssistedDep1> dupeParameterizedFooFactory) {
-      this.dupeParameterizedFooFactory = dupeParameterizedFooFactory;
-    }
-  }
-
-  @Test
-  public void testParameterizedFooFactoryFromSomeEntryPoint() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    int assistedInt = 7;
-    ParameterizedFoo<Dep1, AssistedDep1> parameterizedFoo =
-        DaggerAssistedFactoryParameterizedTest_ParentComponent.create()
-            .someEntryPoint()
-            .dupeParameterizedFooFactory
-            .create(assistedDep1, assistedDep1, assistedInt);
-    assertThat(parameterizedFoo.dep1).isNotNull();
-    assertThat(parameterizedFoo.depTProvider).isNotNull();
-    assertThat(parameterizedFoo.depTProvider.get()).isNotNull();
-    assertThat(parameterizedFoo.dep3).isNotNull();
-    assertThat(parameterizedFoo.dep4).isNotNull();
-    assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1);
-    assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep1);
-    assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt);
-    assertThat(parameterizedFoo.factory).isNotNull();
-  }
-}
diff --git a/javatests/dagger/functional/assisted/AssistedFactoryTest.java b/javatests/dagger/functional/assisted/AssistedFactoryTest.java
deleted file mode 100644
index 3176add..0000000
--- a/javatests/dagger/functional/assisted/AssistedFactoryTest.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class AssistedFactoryTest {
-  @Component
-  interface ParentComponent {
-    // Simple factory using a nested factory.
-    SimpleFoo.Factory nestedSimpleFooFactory();
-
-    // Simple factory using a non-nested factory.
-    SimpleFooFactory nonNestedSimpleFooFactory();
-
-    // Simple factory using a factory that extends a supertype.
-    ExtendedSimpleFooFactory extendedSimpleFooFactory();
-
-    // Factory as interface
-    FooFactory fooFactory();
-
-    // Factory as abstract class
-    AbstractFooFactory abstractFooFactory();
-
-    // Factory without any assisted parameters
-    NoAssistedParametersFooFactory noAssistedParametersFooFactory();
-
-    // Test injecting the factories from another class
-    SomeEntryPoint someEntryPoint();
-  }
-
-  // This class tests the request of factories from another binding.
-  static class SomeEntryPoint {
-    private final SimpleFoo.Factory nestedSimpleFooFactory;
-    private final SimpleFooFactory nonNestedSimpleFooFactory;
-    private final ExtendedSimpleFooFactory extendedSimpleFooFactory;
-    private final FooFactory fooFactory;
-    private final AbstractFooFactory abstractFooFactory;
-    private final NoAssistedParametersFooFactory noAssistedParametersFooFactory;
-
-    @Inject
-    SomeEntryPoint(
-        SimpleFoo.Factory nestedSimpleFooFactory,
-        SimpleFooFactory nonNestedSimpleFooFactory,
-        ExtendedSimpleFooFactory extendedSimpleFooFactory,
-        FooFactory fooFactory,
-        AbstractFooFactory abstractFooFactory,
-        NoAssistedParametersFooFactory noAssistedParametersFooFactory) {
-      this.nestedSimpleFooFactory = nestedSimpleFooFactory;
-      this.nonNestedSimpleFooFactory = nonNestedSimpleFooFactory;
-      this.extendedSimpleFooFactory = extendedSimpleFooFactory;
-      this.fooFactory = fooFactory;
-      this.abstractFooFactory = abstractFooFactory;
-      this.noAssistedParametersFooFactory = noAssistedParametersFooFactory;
-    }
-  }
-
-  static final class Dep1 {
-    @Inject
-    Dep1(Dep2 dep2, Dep3 dep3) {}
-  }
-
-  static final class Dep2 {
-    @Inject
-    Dep2(Dep3 dep3) {}
-  }
-
-  static final class Dep3 {
-    @Inject
-    Dep3(Dep4 dep4) {}
-  }
-
-  static final class Dep4 {
-    @Inject
-    Dep4() {}
-  }
-
-  // A base interface to test that factories can reference subclasses of the assisted parameter.
-  interface AssistedDep {}
-
-  static final class AssistedDep1 implements AssistedDep {}
-
-  static final class AssistedDep2 implements AssistedDep {}
-
-  static final class SimpleFoo {
-    private final AssistedDep assistedDep;
-
-    @AssistedInject
-    SimpleFoo(@Assisted AssistedDep assistedDep) {
-      this.assistedDep = assistedDep;
-    }
-
-    @AssistedFactory
-    interface Factory {
-      // Use different parameter names than Foo to make sure we're not assuming they're the same.
-      SimpleFoo createSimpleFoo(AssistedDep factoryAssistedDep);
-
-      // A no-op method to test static methods in assisted factories
-      static void staticMethod() {
-        return;
-      }
-
-      // A no-op method to test default methods in assisted factories
-      default void defaultMethod() {
-        return;
-      }
-    }
-  }
-
-  @AssistedFactory
-  interface SimpleFooFactory {
-    // Use different parameter names than Foo to make sure we're not assuming they're the same.
-    SimpleFoo createSimpleFoo(AssistedDep factoryAssistedDep1);
-
-    // A no-op method to test static methods are allowed
-    static void staticMethod() {
-      return;
-    }
-
-    // A no-op method to test static methods that return assisted type are allowed
-    static SimpleFoo staticSimpleFooMethod() {
-      return null;
-    }
-
-    // A no-op method to test default methods are allowed
-    default void defaultMethod() {
-      return;
-    }
-
-    // A no-op method to test default methods that return assisted type are allowed
-    default SimpleFoo defaultSimpleFooMethod() {
-      return null;
-    }
-  }
-
-  @AssistedFactory
-  interface ExtendedSimpleFooFactory extends SimpleFooFactory {}
-
-  abstract static class BaseFoo {
-    @Inject Dep4 dep4;
-  }
-
-  static final class Foo extends BaseFoo {
-    private final Dep1 dep1;
-    private final Provider<Dep2> dep2Provider;
-    private final AssistedDep1 assistedDep1;
-    private final AssistedDep2 assistedDep2;
-    private final int assistedInt;
-    private final FooFactory factory;
-
-    @Inject Dep3 dep3;
-
-    @AssistedInject
-    Foo(
-        Dep1 dep1,
-        @Assisted AssistedDep1 assistedDep1,
-        Provider<Dep2> dep2Provider,
-        @Assisted AssistedDep2 assistedDep2,
-        @Assisted int assistedInt,
-        FooFactory factory) {
-      this.dep1 = dep1;
-      this.dep2Provider = dep2Provider;
-      this.assistedDep1 = assistedDep1;
-      this.assistedDep2 = assistedDep2;
-      this.assistedInt = assistedInt;
-      this.factory = factory;
-    }
-  }
-
-  @AssistedFactory
-  interface FooFactory {
-    // Use different parameter names than Foo to make sure we're not assuming they're the same.
-    Foo createFoo(
-        AssistedDep1 factoryAssistedDep1, AssistedDep2 factoryAssistedDep2, int factoryAssistedInt);
-  }
-
-  @AssistedFactory
-  abstract static class AbstractFooFactory {
-    // Use different parameter names than Foo to make sure we're not assuming they're the same.
-    abstract Foo createFoo(
-        AssistedDep1 factoryAssistedDep1, AssistedDep2 factoryAssistedDep2, int factoryAssistedInt);
-
-    // A no-op method to test static methods are allowed
-    static void staticMethod() {
-      return;
-    }
-
-    // A no-op method to test static methods that return assisted type are allowed
-    static Foo staticFooMethod() {
-      return null;
-    }
-
-    // A no-op method to test concrete methods are allowed
-    void concreteMethod() {
-      return;
-    }
-
-    // A no-op method to test concrete methods that return assisted type are allowed
-    Foo concreteFooMethod() {
-      return null;
-    }
-  }
-
-  static final class NoAssistedParametersFoo extends BaseFoo {
-    private final Dep1 dep1;
-    private final Provider<Dep2> dep2Provider;
-    private final NoAssistedParametersFooFactory factory;
-
-    @Inject Dep3 dep3;
-
-    @AssistedInject
-    NoAssistedParametersFoo(
-        Dep1 dep1, Provider<Dep2> dep2Provider, NoAssistedParametersFooFactory factory) {
-      this.dep1 = dep1;
-      this.dep2Provider = dep2Provider;
-      this.factory = factory;
-    }
-  }
-
-  @AssistedFactory
-  interface NoAssistedParametersFooFactory {
-    NoAssistedParametersFoo createNoAssistedParametersFoo();
-  }
-
-  @Test
-  public void testNestedSimpleFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    SimpleFoo simpleFoo1 =
-        DaggerAssistedFactoryTest_ParentComponent.create()
-            .nestedSimpleFooFactory()
-            .createSimpleFoo(assistedDep1);
-    assertThat(simpleFoo1.assistedDep).isEqualTo(assistedDep1);
-
-    AssistedDep2 assistedDep2 = new AssistedDep2();
-    SimpleFoo simpleFoo2 =
-        DaggerAssistedFactoryTest_ParentComponent.create()
-            .nestedSimpleFooFactory()
-            .createSimpleFoo(assistedDep2);
-    assertThat(simpleFoo2.assistedDep).isEqualTo(assistedDep2);
-  }
-
-  @Test
-  public void testNonNestedSimpleFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    SimpleFoo simpleFoo =
-        DaggerAssistedFactoryTest_ParentComponent.create()
-            .nonNestedSimpleFooFactory()
-            .createSimpleFoo(assistedDep1);
-    assertThat(simpleFoo.assistedDep).isEqualTo(assistedDep1);
-  }
-
-  @Test
-  public void testExtendedSimpleFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    SimpleFoo simpleFoo =
-        DaggerAssistedFactoryTest_ParentComponent.create()
-            .extendedSimpleFooFactory()
-            .createSimpleFoo(assistedDep1);
-    assertThat(simpleFoo.assistedDep).isEqualTo(assistedDep1);
-  }
-
-  @Test
-  public void testFooFactory() {
-    AssistedDep1 assistedDep1 = new AssistedDep1();
-    AssistedDep2 assistedDep2 = new AssistedDep2();
-    int assistedInt = 7;
-    Foo foo =
-        DaggerAssistedFactoryTest_ParentComponent.create()
-            .fooFactory()
-            .createFoo(assistedDep1, assistedDep2, assistedInt);
-    assertThat(foo.dep1).isNotNull();
-    assertThat(foo.dep2Provider).isNotNull();
-    assertThat(foo.dep2Provider.get()).isNotNull();
-    assertThat(foo.dep3).isNotNull();
-    assertThat(foo.dep4).isNotNull();
-    assertThat(foo.assistedDep1).isEqualTo(assistedDep1);
-    assertThat(foo.assistedDep2).isEqualTo(assistedDep2);
-    assertThat(foo.assistedInt).isEqualTo(assistedInt);
-    assertThat(foo.factory).isNotNull();
-  }
-
-  @Test
-  public void testNoAssistedParametersFooFactory() {
-    NoAssistedParametersFoo foo =
-        DaggerAssistedFactoryTest_ParentComponent.create()
-            .noAssistedParametersFooFactory()
-            .createNoAssistedParametersFoo();
-    assertThat(foo.dep1).isNotNull();
-    assertThat(foo.dep2Provider).isNotNull();
-    assertThat(foo.dep2Provider.get()).isNotNull();
-    assertThat(foo.dep3).isNotNull();
-    assertThat(foo.dep4).isNotNull();
-    assertThat(foo.factory).isNotNull();
-  }
-
-  @Test
-  public void testAssistedFactoryFromSomeEntryPoint() {
-    SomeEntryPoint someEntryPoint =
-        DaggerAssistedFactoryTest_ParentComponent.create().someEntryPoint();
-    assertThat(someEntryPoint.nestedSimpleFooFactory).isNotNull();
-    assertThat(someEntryPoint.nonNestedSimpleFooFactory).isNotNull();
-    assertThat(someEntryPoint.extendedSimpleFooFactory).isNotNull();
-    assertThat(someEntryPoint.fooFactory).isNotNull();
-    assertThat(someEntryPoint.abstractFooFactory).isNotNull();
-    assertThat(someEntryPoint.noAssistedParametersFooFactory).isNotNull();
-  }
-}
diff --git a/javatests/dagger/functional/assisted/AssistedFactoryWithArrayTypesTest.java b/javatests/dagger/functional/assisted/AssistedFactoryWithArrayTypesTest.java
deleted file mode 100644
index 91f7e42..0000000
--- a/javatests/dagger/functional/assisted/AssistedFactoryWithArrayTypesTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2021 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.functional.assisted;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class AssistedFactoryWithArrayTypesTest {
-  @Component
-  interface TestComponent {
-    FooFactory fooFactory();
-  }
-
-  @AssistedFactory
-  interface FooFactory {
-    Foo create(Dep[] depArray);
-  }
-
-  static class Dep {}
-
-  static class Foo {
-    private final Dep[] depArray;
-
-    @AssistedInject
-    Foo(@Assisted Dep[] depArray) {
-      this.depArray = depArray;
-    }
-  }
-
-  @Test
-  public void testFooFactory() {
-    Dep[] depArray = {new Dep(), new Dep()};
-    Foo foo =
-        DaggerAssistedFactoryWithArrayTypesTest_TestComponent.create()
-            .fooFactory()
-            .create(depArray);
-    assertThat(foo.depArray).isEqualTo(depArray);
-  }
-}
diff --git a/javatests/dagger/functional/assisted/AssistedFactoryWithAssistedInjectParamTest.java b/javatests/dagger/functional/assisted/AssistedFactoryWithAssistedInjectParamTest.java
deleted file mode 100644
index 9b794fd..0000000
--- a/javatests/dagger/functional/assisted/AssistedFactoryWithAssistedInjectParamTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2021 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.functional.assisted;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-// This is a regression test for https://github.com/google/dagger/issues/2278
-@RunWith(JUnit4.class)
-public final class AssistedFactoryWithAssistedInjectParamTest {
-  @Component
-  interface ParentComponent {
-    FooFactory fooFactory();
-
-    BarFactory barFactory();
-  }
-
-  static class Foo {
-    private final Bar bar;
-
-    @AssistedInject
-    Foo(@Assisted Bar bar) {
-      this.bar = bar;
-    }
-  }
-
-  static class Bar {
-    @AssistedInject
-    Bar() {}
-  }
-
-  @AssistedFactory
-  interface FooFactory {
-    Foo create(Bar bar);
-  }
-
-  @AssistedFactory
-  interface BarFactory {
-    Bar create();
-  }
-
-  @Test
-  public void testFooFactory() {
-    ParentComponent component =
-        DaggerAssistedFactoryWithAssistedInjectParamTest_ParentComponent.create();
-    FooFactory fooFactory = component.fooFactory();
-    BarFactory barFactory = component.barFactory();
-
-    Bar bar = barFactory.create();
-    Foo foo = fooFactory.create(bar);
-    assertThat(foo.bar).isEqualTo(bar);
-  }
-}
diff --git a/javatests/dagger/functional/assisted/AssistedFactoryWithQualifiedTypesTest.java b/javatests/dagger/functional/assisted/AssistedFactoryWithQualifiedTypesTest.java
deleted file mode 100644
index 952b94d..0000000
--- a/javatests/dagger/functional/assisted/AssistedFactoryWithQualifiedTypesTest.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2021 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.functional.assisted;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-// See https://github.com/google/dagger/issues/2281
-@RunWith(JUnit4.class)
-public final class AssistedFactoryWithQualifiedTypesTest {
-  @Component
-  interface TestComponent {
-    // Test a factory with duplicate types with unique qualifiers.
-    DupeTypeFactory dupeTypeFactory();
-
-    // Test a factory with duplicate qualifiers with unique types.
-    DupeQualifierFactory dupeQualifierFactory();
-
-    // Test a factory with unnecessary qualifiers on the factory.
-    UnnecessaryQualifierFactory unnecessaryQualifierFactory();
-
-    // Test a factory with different parameter order than the constructor.
-    SwappedDupeTypeFactory swappedDupeTypeFactory();
-  }
-
-  static class DupeType {
-    private final String str1;
-    private final String str2;
-
-    @AssistedInject
-    DupeType(@Assisted("1") String str1, @Assisted("2") String str2) {
-      this.str1 = str1;
-      this.str2 = str2;
-    }
-  }
-
-  @AssistedFactory
-  interface DupeTypeFactory {
-    DupeType create(@Assisted("1") String str1, @Assisted("2") String str2);
-  }
-
-  @Test
-  public void testDupeTypeFactory() {
-    String str1 = "str1";
-    String str2 = "str2";
-    DupeType dupeType =
-        DaggerAssistedFactoryWithQualifiedTypesTest_TestComponent.create()
-            .dupeTypeFactory()
-            .create(str1, str2);
-    assertThat(dupeType.str1).isEqualTo(str1);
-    assertThat(dupeType.str2).isEqualTo(str2);
-  }
-
-  @AssistedFactory
-  interface SwappedDupeTypeFactory {
-    DupeType create(@Assisted("2") String str2, @Assisted("1") String str1);
-  }
-
-  @Test
-  public void testSwappedDupeTypeFactory() {
-    String str1 = "str1";
-    String str2 = "str2";
-    DupeType dupeType =
-        DaggerAssistedFactoryWithQualifiedTypesTest_TestComponent.create()
-            .swappedDupeTypeFactory()
-            .create(str2, str1);
-    assertThat(dupeType.str1).isEqualTo(str1);
-    assertThat(dupeType.str2).isEqualTo(str2);
-  }
-
-  static class DupeQualifier {
-    private final String str;
-    private final int i;
-
-    @AssistedInject
-    DupeQualifier(@Assisted("1") String str, @Assisted("1") int i) {
-      this.str = str;
-      this.i = i;
-    }
-  }
-
-  @AssistedFactory
-  interface DupeQualifierFactory {
-    DupeQualifier create(@Assisted("1") String str, @Assisted("1") int i);
-  }
-
-  @Test
-  public void testDupeQualifierFactory() {
-    String str = "str";
-    int i = 11;
-    DupeQualifier dupeQualifier =
-        DaggerAssistedFactoryWithQualifiedTypesTest_TestComponent.create()
-            .dupeQualifierFactory()
-            .create(str, i);
-    assertThat(dupeQualifier.str).isEqualTo(str);
-    assertThat(dupeQualifier.i).isEqualTo(i);
-  }
-
-  static class UnnecessaryQualifier {
-    private final String str;
-    private final double d;
-    private final int i;
-
-    @AssistedInject
-    UnnecessaryQualifier(@Assisted String str, @Assisted double d, @Assisted("") int i) {
-      this.str = str;
-      this.d = d;
-      this.i = i;
-    }
-  }
-
-  @AssistedFactory
-  interface UnnecessaryQualifierFactory {
-    UnnecessaryQualifier create(@Assisted int i, @Assisted("") String str, double d);
-  }
-
-  @Test
-  public void testUnnecessaryQualifierFactory() {
-    String str = "str";
-    double d = 2.2;
-    int i = 11;
-    UnnecessaryQualifier unnecessaryQualifier =
-        DaggerAssistedFactoryWithQualifiedTypesTest_TestComponent.create()
-            .unnecessaryQualifierFactory()
-            .create(i, str, d);
-    assertThat(unnecessaryQualifier.str).isEqualTo(str);
-    assertThat(unnecessaryQualifier.d).isEqualTo(d);
-    assertThat(unnecessaryQualifier.i).isEqualTo(i);
-  }
-}
diff --git a/javatests/dagger/functional/assisted/BUILD b/javatests/dagger/functional/assisted/BUILD
deleted file mode 100644
index 5e663e7..0000000
--- a/javatests/dagger/functional/assisted/BUILD
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Functional tests for Dagger
-
-load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "SOURCE_7_TARGET_7")
-load("//:test_defs.bzl", "GenJavaTests")
-
-package(default_visibility = ["//:src"])
-
-GenJavaTests(
-    name = "assisted",
-    srcs = glob(["*.java"]),
-    javacopts = DOCLINT_HTML_AND_SYNTAX,
-    lib_javacopts = SOURCE_7_TARGET_7,
-    test_only_deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
-        "@google_bazel_common//third_party/java/guava:testlib",
-        "@google_bazel_common//third_party/java/truth",
-        "@google_bazel_common//third_party/java/junit",
-        "//javatests/dagger/functional/assisted/subpackage",
-    ],
-    # NOTE: This should not depend on Guava or jsr305 to ensure that Dagger can be
-    # used without Guava and jsr305 deps.
-    deps = [
-        "//:dagger_with_compiler",
-        "@google_bazel_common//third_party/java/auto:factory",
-        "@google_bazel_common//third_party/java/auto:value",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-    ],
-)
diff --git a/javatests/dagger/functional/assisted/kotlin/BUILD b/javatests/dagger/functional/assisted/kotlin/BUILD
deleted file mode 100644
index 3c3421d..0000000
--- a/javatests/dagger/functional/assisted/kotlin/BUILD
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2021 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.
-# Description:
-#   Tests for internal code for implementing Hilt processors.
-
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
-load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "SOURCE_7_TARGET_7")
-load("//:test_defs.bzl", "GenJavaTests")
-
-package(default_visibility = ["//:src"])
-
-kt_jvm_library(
-    name = "KotlinAssistedInjectionClasses",
-    srcs = ["KotlinAssistedInjectionClasses.kt"],
-    deps = [
-        "//:dagger_with_compiler",
-    ],
-)
-
-GenJavaTests(
-    name = "kotlin",
-    srcs = glob(
-        ["*.java"],
-        exclude = ["*.kt"],
-    ),
-    javacopts = DOCLINT_HTML_AND_SYNTAX,
-    lib_javacopts = SOURCE_7_TARGET_7,
-    test_only_deps = [
-        "//:dagger_with_compiler",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-    # NOTE: This should not depend on Guava or jsr305 to ensure that Dagger can be
-    # used without Guava and jsr305 deps.
-    deps = [
-        ":KotlinAssistedInjectionClasses",
-    ],
-)
diff --git a/javatests/dagger/functional/assisted/kotlin/KotlinAssistedInjectionClasses.kt b/javatests/dagger/functional/assisted/kotlin/KotlinAssistedInjectionClasses.kt
deleted file mode 100644
index e78873d..0000000
--- a/javatests/dagger/functional/assisted/kotlin/KotlinAssistedInjectionClasses.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2021 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.functional.assisted.kotlin
-
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import javax.inject.Inject
-
-class Dep @Inject constructor()
-
-class AssistedDep
-
-/** Assisted injection for a kotlin class. */
-class Foo @AssistedInject constructor(val dep: Dep, @Assisted val assistedDep: AssistedDep)
-
-/** Assisted injection for a kotlin data class. */
-data class FooData @AssistedInject constructor(val dep: Dep, @Assisted val assistedDep: AssistedDep)
-
-/** Assisted factory for a kotlin class */
-@AssistedFactory
-interface FooFactory {
-  fun create(assistedDep: AssistedDep): Foo
-}
-
-/** Assisted factory for a kotlin data class */
-@AssistedFactory
-interface FooDataFactory {
-  fun create(assistedDep: AssistedDep): FooData
-}
diff --git a/javatests/dagger/functional/assisted/kotlin/KotlinAssistedInjectionTest.java b/javatests/dagger/functional/assisted/kotlin/KotlinAssistedInjectionTest.java
deleted file mode 100644
index 7c597f8..0000000
--- a/javatests/dagger/functional/assisted/kotlin/KotlinAssistedInjectionTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2021 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.functional.assisted.kotlin;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-// This is a regression test for https://github.com/google/dagger/issues/2299
-@RunWith(JUnit4.class)
-public final class KotlinAssistedInjectionTest {
-  @Component
-  interface TestComponent {
-    FooFactory fooFactory();
-
-    FooDataFactory fooDataFactory();
-  }
-
-  @Test
-  public void testFooFactory() {
-    FooFactory fooFactory = DaggerKotlinAssistedInjectionTest_TestComponent.create().fooFactory();
-    AssistedDep assistedDep = new AssistedDep();
-    Foo foo = fooFactory.create(assistedDep);
-    assertThat(foo.getAssistedDep()).isEqualTo(assistedDep);
-  }
-
-  @Test
-  public void testFooDataFactory() {
-    FooDataFactory fooDataFactory =
-        DaggerKotlinAssistedInjectionTest_TestComponent.create().fooDataFactory();
-    AssistedDep assistedDep = new AssistedDep();
-    FooData fooData = fooDataFactory.create(assistedDep);
-    assertThat(fooData.getAssistedDep()).isEqualTo(assistedDep);
-  }
-}
diff --git a/javatests/dagger/functional/assisted/subpackage/AccessibleFoo.java b/javatests/dagger/functional/assisted/subpackage/AccessibleFoo.java
deleted file mode 100644
index 16d420a..0000000
--- a/javatests/dagger/functional/assisted/subpackage/AccessibleFoo.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted.subpackage;
-
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedInject;
-
-/** An accessible type using assisted inject from a separate package. */
-public final class AccessibleFoo {
-  // Accessible for testing
-  public final Dep dep;
-  public final AssistedDep assistedDep;
-
-  @AssistedInject
-  AccessibleFoo(Dep dep, @Assisted AssistedDep assistedDep) {
-    this.dep = dep;
-    this.assistedDep = assistedDep;
-  }
-}
diff --git a/javatests/dagger/functional/assisted/subpackage/AssistedDep.java b/javatests/dagger/functional/assisted/subpackage/AssistedDep.java
deleted file mode 100644
index b27b029..0000000
--- a/javatests/dagger/functional/assisted/subpackage/AssistedDep.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted.subpackage;
-
-/** An assisted dependency. */
-public final class AssistedDep {}
diff --git a/javatests/dagger/functional/assisted/subpackage/BUILD b/javatests/dagger/functional/assisted/subpackage/BUILD
deleted file mode 100644
index 644cf44..0000000
--- a/javatests/dagger/functional/assisted/subpackage/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Functional tests for Dagger
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "subpackage",
-    srcs = glob(["*.java"]),
-    deps = [
-        "//:dagger_with_compiler",
-        "@google_bazel_common//third_party/java/jsr330_inject",
-    ],
-)
diff --git a/javatests/dagger/functional/assisted/subpackage/Dep.java b/javatests/dagger/functional/assisted/subpackage/Dep.java
deleted file mode 100644
index a519b3f..0000000
--- a/javatests/dagger/functional/assisted/subpackage/Dep.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted.subpackage;
-
-import javax.inject.Inject;
-
-/** An {@link Inject} constructor dependency. */
-public final class Dep {
-  @Inject
-  Dep() {}
-}
diff --git a/javatests/dagger/functional/assisted/subpackage/InaccessibleFoo.java b/javatests/dagger/functional/assisted/subpackage/InaccessibleFoo.java
deleted file mode 100644
index e093365..0000000
--- a/javatests/dagger/functional/assisted/subpackage/InaccessibleFoo.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted.subpackage;
-
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedInject;
-
-/** An inaccessible type using assisted inject from a separate package. */
-// TODO(bcorso): Remove public once we allow inaccessible types in fastInit.
-public final class InaccessibleFoo {
-  private final Dep dep;
-  private final AssistedDep assistedDep;
-
-  @AssistedInject
-  InaccessibleFoo(Dep dep, @Assisted AssistedDep assistedDep) {
-    this.dep = dep;
-    this.assistedDep = assistedDep;
-  }
-}
diff --git a/javatests/dagger/functional/assisted/subpackage/InaccessibleFooFactory.java b/javatests/dagger/functional/assisted/subpackage/InaccessibleFooFactory.java
deleted file mode 100644
index a7efe57..0000000
--- a/javatests/dagger/functional/assisted/subpackage/InaccessibleFooFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.assisted.subpackage;
-
-import dagger.assisted.AssistedFactory;
-
-/** An accessible factory that creates an inaccessible type. */
-@AssistedFactory
-public interface InaccessibleFooFactory {
-  InaccessibleFoo create(AssistedDep assistedDep);
-}
diff --git a/javatests/dagger/functional/binds/SimpleBindingModule.java b/javatests/dagger/functional/binds/SimpleBindingModule.java
index e8c3ca6..e1d5227 100644
--- a/javatests/dagger/functional/binds/SimpleBindingModule.java
+++ b/javatests/dagger/functional/binds/SimpleBindingModule.java
@@ -20,7 +20,6 @@
 import dagger.Module;
 import dagger.Provides;
 import dagger.Reusable;
-import dagger.functional.NeedsFactory;
 import dagger.functional.SomeQualifier;
 import dagger.multibindings.ElementsIntoSet;
 import dagger.multibindings.IntKey;
@@ -36,12 +35,6 @@
 
 @Module(includes = InterfaceModule.class)
 abstract class SimpleBindingModule {
-
-  // Regression test for b/161853413 that binds an implementation that extends a generated class
-  // that is processed in the same build unit as the @Binds method.
-  @Binds
-  abstract NeedsFactory.SomethingFactory bindFooFactory(NeedsFactory.SomethingFactoryImpl impl);
-
   @Binds
   abstract Object bindObject(FooOfStrings impl);
 
@@ -154,7 +147,7 @@
   @IntKey(123)
   @SomeQualifier
   abstract Object bindFooOfStringsIntoQualifiedMap(FooOfStrings fooOfStrings);
-
+  
   @Provides
   @Named("For-123")
   static String provide123String() {
diff --git a/javatests/dagger/functional/builder/BuildMethodCovariantReturnInherited.java b/javatests/dagger/functional/builder/BuildMethodCovariantReturnInherited.java
index 9b1447c..07ebbc8 100644
--- a/javatests/dagger/functional/builder/BuildMethodCovariantReturnInherited.java
+++ b/javatests/dagger/functional/builder/BuildMethodCovariantReturnInherited.java
@@ -18,7 +18,6 @@
 
 import dagger.Component;
 
-
 interface BuildMethodCovariantReturnInherited {
   @Component
   interface Simple {
diff --git a/javatests/dagger/functional/builder/BuilderBindsInstanceParameterTest.java b/javatests/dagger/functional/builder/BuilderBindsInstanceParameterTest.java
index d47c892..33d3816 100644
--- a/javatests/dagger/functional/builder/BuilderBindsInstanceParameterTest.java
+++ b/javatests/dagger/functional/builder/BuilderBindsInstanceParameterTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-
 import dagger.BindsInstance;
 import dagger.Component;
 import org.junit.Test;
diff --git a/javatests/dagger/functional/builder/GenericParent.java b/javatests/dagger/functional/builder/GenericParent.java
index 949514e..9563103 100644
--- a/javatests/dagger/functional/builder/GenericParent.java
+++ b/javatests/dagger/functional/builder/GenericParent.java
@@ -16,7 +16,6 @@
 
 package dagger.functional.builder;
 
-
 interface GenericParent<B> {  
   B subcomponentBuilder();
 }
diff --git a/javatests/dagger/functional/cycle/Cycles.java b/javatests/dagger/functional/cycle/Cycles.java
index e17d619..f4faeab 100644
--- a/javatests/dagger/functional/cycle/Cycles.java
+++ b/javatests/dagger/functional/cycle/Cycles.java
@@ -97,7 +97,7 @@
       this.sProvider = sProvider;
     }
   }
-  
+
   static class X {
     public final Y y;
 
@@ -143,10 +143,10 @@
     A a();
 
     C c();
-    
+
     ChildCycleComponent child();
   }
-  
+
   @Module
   static class CycleModule {
     @Provides
@@ -160,12 +160,12 @@
   interface SelfCycleComponent {
     S s();
   }
-  
+
   @Subcomponent
   interface ChildCycleComponent {
     @SuppressWarnings("dependency-cycle")
     A a();
-    
+
     @SuppressWarnings("dependency-cycle")
     Object object();
   }
diff --git a/javatests/dagger/functional/cycle/DoubleCheckCycleTest.java b/javatests/dagger/functional/cycle/DoubleCheckCycleTest.java
index d77a713..b77ee3e 100644
--- a/javatests/dagger/functional/cycle/DoubleCheckCycleTest.java
+++ b/javatests/dagger/functional/cycle/DoubleCheckCycleTest.java
@@ -181,7 +181,6 @@
                 })
             .build();
 
-
     int numThreads = 10;
     CountDownLatch remainingTasks = new CountDownLatch(numThreads);
     List<Thread> tasks = new ArrayList<>(numThreads);
diff --git a/javatests/dagger/functional/guava/BUILD b/javatests/dagger/functional/guava/BUILD
index ed8efd3..66492eb 100644
--- a/javatests/dagger/functional/guava/BUILD
+++ b/javatests/dagger/functional/guava/BUILD
@@ -15,20 +15,19 @@
 # Description:
 #   Functional tests for Dagger that depend on Guava
 
+package(default_visibility = ["//:src"])
+
 load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "guava_tests",
     srcs = glob(["**/*.java"]),
     javacopts = DOCLINT_HTML_AND_SYNTAX,
     deps = [
         "//:dagger_with_compiler",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
         "@google_bazel_common//third_party/java/auto:value",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/jsr305_annotations",
         "@google_bazel_common//third_party/java/jsr330_inject",
         "@google_bazel_common//third_party/java/junit",
diff --git a/javatests/dagger/functional/jdk8/BUILD b/javatests/dagger/functional/jdk8/BUILD
index 5e35c75..6b76ba3 100644
--- a/javatests/dagger/functional/jdk8/BUILD
+++ b/javatests/dagger/functional/jdk8/BUILD
@@ -15,20 +15,19 @@
 # Description:
 #   Functional tests for Dagger that depend on Guava
 
+package(default_visibility = ["//:src"])
+
 load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "jdk8_tests",
     srcs = glob(["**/*.java"]),
     javacopts = DOCLINT_HTML_AND_SYNTAX,
     test_only_deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
+        "@google_bazel_common//third_party/java/truth:truth8",
     ],
     deps = [
         "//:dagger_with_compiler",
diff --git a/javatests/dagger/functional/kotlin/BUILD b/javatests/dagger/functional/kotlin/BUILD
deleted file mode 100644
index 529eb69..0000000
--- a/javatests/dagger/functional/kotlin/BUILD
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright (C) 2019 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.
-#
-# Description:
-#   Functional test code for Dagger-Android
-
-load("@rules_java//java:defs.bzl", "java_library")
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
-load("//:test_defs.bzl", "GenJavaTests")
-
-package(default_visibility = ["//:src"])
-
-kt_jvm_library(
-    name = "kotlin",
-    srcs = glob(
-        [
-            "*.java",
-            "*.kt",
-        ],
-        exclude = [
-            "*Test.java",
-            "JavaTestQualifier.java",
-            "FooWithInjectedQualifier.kt",
-        ],
-    ),
-    # TODO(danysantiago): Remove 'plugins' once kt_jvm_library supports 'exported_plugins'.
-    plugins = ["//javatests/dagger/functional/kotlin/processor:plugin"],
-    deps = [
-        ":foo_with_injected_qualifier",
-        ":java_qualifier",
-        "//:dagger_with_compiler",
-        "//javatests/dagger/functional/kotlin/processor:annotation",
-    ],
-)
-
-kt_jvm_library(
-    name = "foo_with_injected_qualifier",
-    srcs = ["FooWithInjectedQualifier.kt"],
-    deps = [
-        ":java_qualifier",
-        "//:dagger_with_compiler",
-    ],
-)
-
-java_library(
-    name = "java_qualifier",
-    srcs = ["JavaTestQualifier.java"],
-    deps = [
-        "//:dagger_with_compiler",
-    ],
-)
-
-GenJavaTests(
-    name = "kotlin_tests",
-    srcs = glob(["*Test.java"]),
-    functional = True,
-    test_only_deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-    deps = [
-        ":foo_with_injected_qualifier",
-        ":kotlin",
-        "//:dagger_with_compiler",
-    ],
-)
diff --git a/javatests/dagger/functional/kotlin/CompanionModuleTest.java b/javatests/dagger/functional/kotlin/CompanionModuleTest.java
deleted file mode 100644
index 591c5d6..0000000
--- a/javatests/dagger/functional/kotlin/CompanionModuleTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class CompanionModuleTest {
-
-  @Test
-  public void verifyCompanionModule() {
-    TestKotlinComponentWithCompanionModule component =
-        DaggerTestKotlinComponentWithCompanionModule.create();
-    assertThat(component.getDataA()).isNotNull();
-    assertThat(component.getDataB()).isNotNull();
-    assertThat(component.getBoolean()).isTrue();
-    assertThat(component.getStringType()).isNotNull();
-    assertThat(component.getCatNamedStringType()).isEqualTo("Cat");
-    assertThat(component.getDogNamedStringType()).isEqualTo("Dog");
-    assertThat(component.getInterface()).isNotNull();
-    assertThat(component.getLong()).isEqualTo(4L);
-    assertThat(component.getDouble()).isEqualTo(1.0);
-    assertThat(component.getInteger()).isEqualTo(2);
-  }
-}
diff --git a/javatests/dagger/functional/kotlin/FooWithInjectedQualifier.kt b/javatests/dagger/functional/kotlin/FooWithInjectedQualifier.kt
deleted file mode 100644
index 6602f10..0000000
--- a/javatests/dagger/functional/kotlin/FooWithInjectedQualifier.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin
-
-import javax.inject.Inject
-
-class FooWithInjectedQualifier {
-  @Inject
-  @JavaTestQualifier
-  lateinit var qualifiedString: String
-
-  @Inject
-  @field:JavaTestQualifier
-  @NotAQualifier
-  lateinit var qualifiedStringWithPropertyAnnotaion: String
-}
-
-@Target(AnnotationTarget.PROPERTY)
-annotation class NotAQualifier
diff --git a/javatests/dagger/functional/kotlin/JavaTestQualifier.java b/javatests/dagger/functional/kotlin/JavaTestQualifier.java
deleted file mode 100644
index 156f436..0000000
--- a/javatests/dagger/functional/kotlin/JavaTestQualifier.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import javax.inject.Qualifier;
-
-@Qualifier
-@Retention(RUNTIME)
-public @interface JavaTestQualifier {}
diff --git a/javatests/dagger/functional/kotlin/JavaTestQualifierWithTarget.java b/javatests/dagger/functional/kotlin/JavaTestQualifierWithTarget.java
deleted file mode 100644
index 3bc2e4e..0000000
--- a/javatests/dagger/functional/kotlin/JavaTestQualifierWithTarget.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import javax.inject.Qualifier;
-
-@Qualifier
-@Retention(RUNTIME)
-@Target({ElementType.FIELD, ElementType.METHOD})
-public @interface JavaTestQualifierWithTarget {}
diff --git a/javatests/dagger/functional/kotlin/ObjectModuleTest.java b/javatests/dagger/functional/kotlin/ObjectModuleTest.java
deleted file mode 100644
index a37be44..0000000
--- a/javatests/dagger/functional/kotlin/ObjectModuleTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class ObjectModuleTest {
-
-  @Test
-  public void verifyObjectModule() {
-    TestKotlinComponentWithObjectModule component =
-        DaggerTestKotlinComponentWithObjectModule.create();
-    assertThat(component.getDataA()).isNotNull();
-    assertThat(component.getDataAFromNestedModule()).isNotNull();
-    assertThat(component.getDataB()).isNotNull();
-    assertThat(component.getSetOfDataA()).isNotNull();
-    assertThat(component.getSetOfDataA()).hasSize(1);
-    assertThat(component.getPrimitiveType()).isTrue();
-  }
-}
diff --git a/javatests/dagger/functional/kotlin/PropertyQualifierTest.java b/javatests/dagger/functional/kotlin/PropertyQualifierTest.java
deleted file mode 100644
index e0ebf3c..0000000
--- a/javatests/dagger/functional/kotlin/PropertyQualifierTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class PropertyQualifierTest {
-
-  @Test
-  public void verifyQualifiedBinding() {
-    TestMemberInjectedClassWithQualifier injectedClass = new TestMemberInjectedClassWithQualifier();
-    DaggerTestKotlinComponentWithQualifier.create().inject(injectedClass);
-
-    assertThat(injectedClass.javaDataA).isNotNull();
-    assertThat(injectedClass.javaDataB).isNotNull();
-    assertThat(injectedClass.javaWithTargetDataA).isNotNull();
-    assertThat(injectedClass.kotlinDataA).isNotNull();
-    assertThat(injectedClass.dataWithConstructionInjection).isNotNull();
-    assertThat(injectedClass.dataWithConstructionInjection.getData()).isNotNull();
-  }
-
-  @Test
-  public void verifyQualifiedBinding_acrossCompilation() {
-    FooWithInjectedQualifier injectedClass = new FooWithInjectedQualifier();
-    DaggerTestKotlinComponentWithQualifier.create().inject(injectedClass);
-
-    assertThat(injectedClass.getQualifiedString()).isEqualTo("qualified string");
-    assertThat(injectedClass.getQualifiedStringWithPropertyAnnotaion())
-        .isEqualTo("qualified string");
-  }
-}
diff --git a/javatests/dagger/functional/kotlin/PublicModuleWithNonPublicInclude.java b/javatests/dagger/functional/kotlin/PublicModuleWithNonPublicInclude.java
deleted file mode 100644
index f927186..0000000
--- a/javatests/dagger/functional/kotlin/PublicModuleWithNonPublicInclude.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin;
-
-import dagger.Module;
-
-/** Verifies that a non-public included Kotlin object module does not fail compilation. */
-@Module(includes = {NonPublicObjectModule.class})
-public class PublicModuleWithNonPublicInclude {}
diff --git a/javatests/dagger/functional/kotlin/TestComponentWithCompanionModule.kt b/javatests/dagger/functional/kotlin/TestComponentWithCompanionModule.kt
deleted file mode 100644
index 1eaa3f5..0000000
--- a/javatests/dagger/functional/kotlin/TestComponentWithCompanionModule.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-package dagger.functional.kotlin
-
-import dagger.Binds
-import dagger.Component
-import dagger.Module
-import dagger.Provides
-import javax.inject.Named
-
-@Component(
-  modules = [
-    TestKotlinModuleWithCompanion::class,
-    TestKotlinModuleWithNamedCompanion::class,
-    TestKotlinAbstractModuleWithCompanion::class,
-    TestKotlinWorkaroundModuleWithCompanion::class,
-    TestKotlinModuleWithPrivateCompanion::class
-  ]
-)
-interface TestKotlinComponentWithCompanionModule {
-  fun getDataA(): TestDataA
-  fun getDataB(): TestDataB
-  fun getBoolean(): Boolean
-  fun getStringType(): String
-  @Named("Cat")
-  fun getCatNamedStringType(): String
-  @Named("Dog")
-  fun getDogNamedStringType(): String
-
-  fun getInterface(): TestInterface
-  fun getLong(): Long
-  fun getDouble(): Double
-  fun getInteger(): Int
-}
-
-@Module
-class TestKotlinModuleWithCompanion {
-  @Provides
-  fun provideDataA() = TestDataA("test")
-
-  companion object {
-    @Provides
-    fun provideDataB() = TestDataB("test")
-
-    @Provides
-    fun provideBoolean(): Boolean = true
-  }
-}
-
-@Module
-class TestKotlinModuleWithNamedCompanion {
-
-  @Provides
-  @Named("Cat")
-  fun provideNamedString() = "Cat"
-
-  companion object Foo {
-    @Provides
-    fun provideStringType(): String = ""
-  }
-}
-
-@Module
-abstract class TestKotlinAbstractModuleWithCompanion {
-
-  @Binds
-  abstract fun bindInterface(injectable: TestInjectable): TestInterface
-
-  companion object {
-    @Provides
-    fun provideLong() = 4L
-  }
-}
-
-@Module
-class TestKotlinWorkaroundModuleWithCompanion {
-
-  @Provides
-  fun provideDouble() = 1.0
-
-  @Module
-  companion object {
-    @Provides
-    @JvmStatic
-    fun provideInteger() = 2
-  }
-}
-
-@Module
-class TestKotlinModuleWithPrivateCompanion {
-
-  @Provides
-  @Named("Dog")
-  fun getNamedStringType() = "Dog"
-
-  private companion object {
-    fun randomFunction() = ""
-  }
-}
diff --git a/javatests/dagger/functional/kotlin/TestComponentWithObjectModule.kt b/javatests/dagger/functional/kotlin/TestComponentWithObjectModule.kt
deleted file mode 100644
index e390aba..0000000
--- a/javatests/dagger/functional/kotlin/TestComponentWithObjectModule.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin
-
-import dagger.Component
-import dagger.Module
-import dagger.Provides
-import dagger.multibindings.IntoSet
-import javax.inject.Named
-
-@Component(
-  modules = [
-    TestKotlinObjectModule::class,
-    TestModuleForNesting.TestNestedKotlinObjectModule::class
-  ]
-)
-interface TestKotlinComponentWithObjectModule {
-  fun getDataA(): TestDataA
-  @Named("nested-data-a")
-  fun getDataAFromNestedModule(): TestDataA
-  fun getDataB(): TestDataB
-  fun getSetOfDataA(): Set<TestDataA>
-  fun getPrimitiveType(): Boolean
-}
-
-@Module
-object TestKotlinObjectModule {
-  @Provides
-  fun provideDataA() = TestDataA("test")
-
-  @Provides
-  fun providePrimitiveType(): Boolean = true
-
-  @Provides
-  @JvmStatic
-  fun provideDataB() = TestDataB("test")
-
-  @Provides
-  @IntoSet
-  fun provideIntoMapDataA() = TestDataA("set-test")
-}
-
-class TestModuleForNesting {
-  @Module
-  object TestNestedKotlinObjectModule {
-    @Provides
-    @Named("nested-data-a")
-    fun provideDataA() = TestDataA("test")
-  }
-}
-
-@Module
-private object NonPublicObjectModule {
-  @Provides
-  fun provideInt() = 42
-}
diff --git a/javatests/dagger/functional/kotlin/TestComponentWithQualifier.kt b/javatests/dagger/functional/kotlin/TestComponentWithQualifier.kt
deleted file mode 100644
index 9aeb2d8..0000000
--- a/javatests/dagger/functional/kotlin/TestComponentWithQualifier.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin
-
-import dagger.Component
-import dagger.Module
-import dagger.Provides
-import dagger.functional.kotlin.processor.TriggerGeneratedTypeProcessor
-import javax.inject.Inject
-
-@Component(modules = [TestKotlinModuleWithQualifier::class])
-interface TestKotlinComponentWithQualifier {
-  fun inject(testInjectedClassWithQualifier: TestMemberInjectedClassWithQualifier)
-  fun inject(fooWithInjectedQualifier: FooWithInjectedQualifier)
-}
-
-@Module
-class TestKotlinModuleWithQualifier {
-  @Provides
-  @JavaTestQualifier
-  fun provideJavaDataA() = TestDataA("test")
-
-  @Provides
-  @JavaTestQualifier
-  fun provideJavaDataB() = TestDataB("test")
-
-  @Provides
-  @JavaTestQualifierWithTarget
-  fun provideJavaWithTargetDataA() = TestDataA("test")
-
-  @Provides
-  @KotlinTestQualifier
-  fun provideKotlinDataA() = TestDataA("test")
-
-  @Provides
-  @JavaTestQualifier
-  fun provideString() = "qualified string"
-}
-
-class TestConstructionInjectedClassWithQualifier @Inject constructor(
-  @JavaTestQualifier val data: TestDataA
-)
-
-@TriggerGeneratedTypeProcessor
-class TestMemberInjectedClassWithQualifier {
-  @Inject
-  @JavaTestQualifier
-  lateinit var javaDataA: TestDataA
-
-  @Inject
-  @field:JavaTestQualifier
-  lateinit var javaDataB: TestDataB
-
-  @Inject
-  @JavaTestQualifierWithTarget
-  lateinit var javaWithTargetDataA: TestDataA
-
-  @Inject
-  @JavaTestQualifier
-  lateinit var kotlinDataA: TestDataA
-
-  @Inject
-  lateinit var dataWithConstructionInjection: TestConstructionInjectedClassWithQualifier
-
-  val noBackingFieldProperty: Int
-    get() = 0
-
-  val delegatedProperty by lazy { "" }
-
-  val generatedTypeProperty = dagger.functional.kotlin.GeneratedType()
-
-  val generatedTypeDelegatedProperty by lazy { dagger.functional.kotlin.GeneratedType() }
-}
diff --git a/javatests/dagger/functional/kotlin/TestKotlinClasses.kt b/javatests/dagger/functional/kotlin/TestKotlinClasses.kt
deleted file mode 100644
index 5d151fc..0000000
--- a/javatests/dagger/functional/kotlin/TestKotlinClasses.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.functional.kotlin
-
-import javax.inject.Inject
-import javax.inject.Qualifier
-
-data class TestDataA(val data: String)
-data class TestDataB(val data: String)
-
-interface TestInterface
-class TestInjectable @Inject constructor() : TestInterface
-
-@Qualifier
-@Retention(AnnotationRetention.RUNTIME)
-annotation class KotlinTestQualifier
diff --git a/javatests/dagger/functional/kotlin/processor/BUILD b/javatests/dagger/functional/kotlin/processor/BUILD
deleted file mode 100644
index 31a45c7..0000000
--- a/javatests/dagger/functional/kotlin/processor/BUILD
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2019 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.
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
-
-package(default_visibility = ["//:src"])
-
-java_plugin(
-    name = "plugin",
-    generates_api = 1,
-    processor_class = "dagger.functional.kotlin.processor.TestGeneratedTypeProcessor",
-    deps = [":processor"],
-)
-
-kt_jvm_library(
-    name = "processor",
-    srcs = ["TestGeneratedTypeProcessor.kt"],
-    deps = [
-        "@google_bazel_common//third_party/java/auto:service",
-        "@google_bazel_common//third_party/java/javapoet",
-    ],
-)
-
-kt_jvm_library(
-    name = "annotation",
-    srcs = ["TriggerGeneratedTypeProcessor.kt"],
-)
diff --git a/javatests/dagger/functional/kotlin/processor/TestGeneratedTypeProcessor.kt b/javatests/dagger/functional/kotlin/processor/TestGeneratedTypeProcessor.kt
deleted file mode 100644
index 4a1d6e2..0000000
--- a/javatests/dagger/functional/kotlin/processor/TestGeneratedTypeProcessor.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package dagger.functional.kotlin.processor
-
-import com.google.auto.service.AutoService
-import com.squareup.javapoet.JavaFile
-import com.squareup.javapoet.TypeSpec
-import javax.annotation.processing.AbstractProcessor
-import javax.annotation.processing.Processor
-import javax.annotation.processing.RoundEnvironment
-import javax.lang.model.SourceVersion
-import javax.lang.model.element.Modifier
-import javax.lang.model.element.TypeElement
-
-/**
- * A processor to be used in functional tests that will generate a simple class with fqname
- * 'dagger.functional.kotlin.GeneratedType'. This processor is useful for testing situations
- * with KAPT where a type is not resolvable and for which KAPT will generate stubs containing
- * the 'error.NonExistentClass' type.
- */
-@AutoService(Processor::class)
-class TestGeneratedTypeProcessor : AbstractProcessor() {
-
-  private var isSourceGenerated = false
-
-  override fun getSupportedAnnotationTypes() =
-    mutableSetOf("dagger.functional.kotlin.processor.TriggerGeneratedTypeProcessor")
-
-  override fun getSupportedSourceVersion() = SourceVersion.latestSupported()
-
-  override fun process(
-    annotations: MutableSet<out TypeElement>,
-    roundEnv: RoundEnvironment
-  ): Boolean {
-    if (isSourceGenerated) {
-      return false
-    }
-
-    JavaFile.builder(
-      "dagger.functional.kotlin",
-      TypeSpec.classBuilder("GeneratedType")
-        .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-        .build()
-    ).build().writeTo(processingEnv.filer)
-
-    isSourceGenerated = true
-
-    return false
-  }
-}
diff --git a/javatests/dagger/functional/kotlin/processor/TriggerGeneratedTypeProcessor.kt b/javatests/dagger/functional/kotlin/processor/TriggerGeneratedTypeProcessor.kt
deleted file mode 100644
index c240fd3..0000000
--- a/javatests/dagger/functional/kotlin/processor/TriggerGeneratedTypeProcessor.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package dagger.functional.kotlin.processor
-
-@Retention(AnnotationRetention.BINARY)
-annotation class TriggerGeneratedTypeProcessor
diff --git a/javatests/dagger/functional/membersinject/MembersInjectGenericParent.java b/javatests/dagger/functional/membersinject/MembersInjectGenericParent.java
index 4a08455..3519348 100644
--- a/javatests/dagger/functional/membersinject/MembersInjectGenericParent.java
+++ b/javatests/dagger/functional/membersinject/MembersInjectGenericParent.java
@@ -18,7 +18,6 @@
 
 import javax.inject.Inject;
 
-
 class MembersInjectGenericParent<T> {
   
   @Inject T t; 
diff --git a/javatests/dagger/functional/membersinject/MembersInjectModule.java b/javatests/dagger/functional/membersinject/MembersInjectModule.java
index 6e182dd..d60a7d1 100644
--- a/javatests/dagger/functional/membersinject/MembersInjectModule.java
+++ b/javatests/dagger/functional/membersinject/MembersInjectModule.java
@@ -26,7 +26,7 @@
   
   @Provides int[] provideIntArray() { return new int[10]; }
   
-  @SuppressWarnings({"unchecked", "rawtypes"})
+  @SuppressWarnings("unchecked")
   @Provides MembersInjectGenericParent<String[]>[] provideFooArrayOfStringArray() { return new MembersInjectGenericParent[10]; }
 
 }
diff --git a/javatests/dagger/functional/membersinject/MembersInjectTest.java b/javatests/dagger/functional/membersinject/MembersInjectTest.java
index 31e4f45..0617fd5 100644
--- a/javatests/dagger/functional/membersinject/MembersInjectTest.java
+++ b/javatests/dagger/functional/membersinject/MembersInjectTest.java
@@ -18,15 +18,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import dagger.BindsInstance;
-import dagger.Component;
 import dagger.MembersInjector;
 import dagger.functional.multipackage.DaggerMembersInjectionVisibilityComponent;
 import dagger.functional.multipackage.MembersInjectionVisibilityComponent;
 import dagger.functional.multipackage.a.AGrandchild;
 import dagger.functional.multipackage.a.AParent;
 import dagger.functional.multipackage.b.BChild;
-import javax.inject.Inject;
 import javax.inject.Provider;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -96,35 +93,4 @@
     injector.injectMembers(child);
     assertThat(child.t).isEqualTo("field!");
   }
-
-  public static final class A extends B {
-    // No injected members
-  }
-
-  public static class B extends C {
-    // No injected members
-  }
-
-  public static class C {
-    @Inject String value;
-  }
-
-  @Component
-  interface NonLocalMembersComponent {
-    MembersInjector<A> getAMembersInjector();
-
-    @Component.Factory
-    interface Factory {
-      NonLocalMembersComponent create(@BindsInstance String value);
-    }
-  }
-
-  @Test
-  public void testNonLocalMembersInjection() {
-    MembersInjector<A> membersInjector = DaggerMembersInjectTest_NonLocalMembersComponent.factory()
-        .create("test").getAMembersInjector();
-    A testA = new A();
-    membersInjector.injectMembers(testA);
-    assertThat(testA.value).isEqualTo("test");
-  }
 }
diff --git a/javatests/dagger/functional/membersinject/MembersWithInstanceNameTest.java b/javatests/dagger/functional/membersinject/MembersWithInstanceNameTest.java
deleted file mode 100644
index 7cd97d9..0000000
--- a/javatests/dagger/functional/membersinject/MembersWithInstanceNameTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.membersinject;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
-import javax.inject.Inject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class MembersWithInstanceNameTest {
-
-  static final class Foo {
-    // Checks that member injection fields can use "instance" as a name (b/175818837).
-    @Inject String instance;
-
-    @Inject Foo() {}
-  }
-
-  @Module
-  interface TestModule {
-    @Provides
-    static String provideString() {
-      return "test";
-    }
-  }
-
-  @Component(modules = TestModule.class)
-  interface TestComponent {
-    Foo foo();
-  }
-
-  @Test
-  public void testMemberWithInstanceName() {
-    TestComponent component = DaggerMembersWithInstanceNameTest_TestComponent.create();
-    Foo foo = component.foo();
-    assertThat(foo).isNotNull();
-    assertThat(foo.instance).isEqualTo("test");
-  }
-}
diff --git a/javatests/dagger/functional/modules/ModuleIncludesTest.java b/javatests/dagger/functional/modules/ModuleIncludesTest.java
index 474cb80..38f7d97 100644
--- a/javatests/dagger/functional/modules/ModuleIncludesTest.java
+++ b/javatests/dagger/functional/modules/ModuleIncludesTest.java
@@ -19,7 +19,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import dagger.Component;
-import dagger.functional.modules.subpackage.FooForProvision;
 import dagger.functional.modules.subpackage.PublicModule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -31,8 +30,6 @@
   @Component(modules = PublicModule.class)
   interface TestComponent {
     Object object();
-
-    FooForProvision fooForProvision();
   }
 
   @Test
diff --git a/javatests/dagger/functional/modules/subpackage/FooForProvision.java b/javatests/dagger/functional/modules/subpackage/FooForProvision.java
deleted file mode 100644
index 60b4482..0000000
--- a/javatests/dagger/functional/modules/subpackage/FooForProvision.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.modules.subpackage;
-
-/** This object is provisioned by NonAbstractPackagePrivate module */
-public class FooForProvision {}
diff --git a/javatests/dagger/functional/modules/subpackage/NonAbstractPackagePrivateModule.java b/javatests/dagger/functional/modules/subpackage/NonAbstractPackagePrivateModule.java
deleted file mode 100644
index 47d2441..0000000
--- a/javatests/dagger/functional/modules/subpackage/NonAbstractPackagePrivateModule.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.modules.subpackage;
-
-import dagger.Module;
-import dagger.Provides;
-
-/**
- * We needed a separate test for non-abstract transitively included pkg-private modules. The reason
- * is that this caused a build failures when the component was generated in a separate package
- * because the generated no-op method references the inaccessible package-private type, so we
- * omitted those no-op methods to support such modules.
- */
-@Module
-class NonAbstractPackagePrivateModule {
-  @Provides
-  static FooForProvision provideFoo() {
-    return new FooForProvision();
-  }
-
-  private NonAbstractPackagePrivateModule() {}
-}
diff --git a/javatests/dagger/functional/modules/subpackage/PublicModule.java b/javatests/dagger/functional/modules/subpackage/PublicModule.java
index 9eade52..7c5fd29 100644
--- a/javatests/dagger/functional/modules/subpackage/PublicModule.java
+++ b/javatests/dagger/functional/modules/subpackage/PublicModule.java
@@ -19,7 +19,7 @@
 import dagger.Module;
 import dagger.Provides;
 
-@Module(includes = {PackagePrivateModule.class, NonAbstractPackagePrivateModule.class})
+@Module(includes = PackagePrivateModule.class)
 public abstract class PublicModule {
   @Provides
   static int provideInt() {
diff --git a/javatests/dagger/functional/multibindings/ComplexMapKeysInDifferentOrderTest.java b/javatests/dagger/functional/multibindings/ComplexMapKeysInDifferentOrderTest.java
index 801d120..f2b5598 100644
--- a/javatests/dagger/functional/multibindings/ComplexMapKeysInDifferentOrderTest.java
+++ b/javatests/dagger/functional/multibindings/ComplexMapKeysInDifferentOrderTest.java
@@ -17,7 +17,6 @@
 package dagger.functional.multibindings;
 
 import static com.google.common.truth.Truth.assertThat;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import com.google.auto.value.AutoAnnotation;
 import dagger.Component;
@@ -25,7 +24,6 @@
 import dagger.Module;
 import dagger.Provides;
 import dagger.multibindings.IntoMap;
-import java.lang.annotation.Retention;
 import java.util.Map;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,7 +31,6 @@
 
 @RunWith(JUnit4.class)
 public final class ComplexMapKeysInDifferentOrderTest {
-  @Retention(RUNTIME)
   @MapKey(unwrapValue = false)
   @interface ComplexMapKey {
     int i();
diff --git a/javatests/dagger/functional/multibindings/MapKeyWithDefaultTest.java b/javatests/dagger/functional/multibindings/MapKeyWithDefaultTest.java
index 70260e7..f188405 100644
--- a/javatests/dagger/functional/multibindings/MapKeyWithDefaultTest.java
+++ b/javatests/dagger/functional/multibindings/MapKeyWithDefaultTest.java
@@ -17,7 +17,6 @@
 package dagger.functional.multibindings;
 
 import static com.google.common.truth.Truth.assertThat;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import com.google.auto.value.AutoAnnotation;
 import dagger.Component;
@@ -25,7 +24,6 @@
 import dagger.Module;
 import dagger.Provides;
 import dagger.multibindings.IntoMap;
-import java.lang.annotation.Retention;
 import java.util.Map;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,7 +31,6 @@
 
 @RunWith(JUnit4.class)
 public final class MapKeyWithDefaultTest {
-  @Retention(RUNTIME)
   @MapKey(unwrapValue = false)
   @interface MapKeyWithDefault {
     boolean hasDefault() default true;
diff --git a/javatests/dagger/functional/producers/BUILD b/javatests/dagger/functional/producers/BUILD
index f69b3cb..36c9701 100644
--- a/javatests/dagger/functional/producers/BUILD
+++ b/javatests/dagger/functional/producers/BUILD
@@ -15,6 +15,8 @@
 # Description:
 #   Functional tests for Dagger Producers
 
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
@@ -23,24 +25,20 @@
 )
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "producers-functional-tests",
     srcs = glob(["**/*.java"]),
-    javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
-    lib_javacopts = SOURCE_7_TARGET_7,
+    javacopts = SOURCE_7_TARGET_7 + DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     deps = [
         "//:producers_with_compiler",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
         "@google_bazel_common//third_party/java/auto:value",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/jsr305_annotations",
         "@google_bazel_common//third_party/java/jsr330_inject",
         "@google_bazel_common//third_party/java/junit",
         "@google_bazel_common//third_party/java/mockito",
         "@google_bazel_common//third_party/java/truth",
+        "@google_bazel_common//third_party/java/truth:truth8",
     ],
 )
 
diff --git a/javatests/dagger/functional/producers/ComponentDependenciesTest.java b/javatests/dagger/functional/producers/ComponentDependenciesTest.java
deleted file mode 100644
index d4ad9f0..0000000
--- a/javatests/dagger/functional/producers/ComponentDependenciesTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2020 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.functional.producers;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import dagger.producers.ProductionComponent;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/**
- * Tests component dependencies.
- */
-@RunWith(JUnit4.class)
-public final class ComponentDependenciesTest {
-  public interface One {
-    ListenableFuture<String> getString();
-  }
-
-  public interface Two {
-    ListenableFuture<String> getString();
-  }
-
-  public interface Merged extends One, Two {
-  }
-
-  @ProductionComponent(dependencies = Merged.class)
-  interface TestProductionComponent {
-    ListenableFuture<String> getString();
-
-    @ProductionComponent.Builder
-    interface Builder {
-      Builder dep(Merged dep);
-
-      TestProductionComponent build();
-    }
-  }
-
-  @Test
-  public void testSameMethodTwiceProduction() throws Exception {
-    TestProductionComponent component =
-        DaggerComponentDependenciesTest_TestProductionComponent.builder().dep(
-            () -> Futures.immediateFuture("test")).build();
-    assertThat(component.getString().get()).isEqualTo("test");
-  }
-
-  public interface OneOverride {
-    ListenableFuture<?> getString();
-  }
-
-  public interface TwoOverride {
-    ListenableFuture<?> getString();
-  }
-
-  public interface MergedOverride extends OneOverride, TwoOverride {
-    @Override
-    ListenableFuture<String> getString();
-  }
-
-  @ProductionComponent(dependencies = MergedOverride.class)
-  interface TestOverrideComponent {
-    ListenableFuture<String> getString();
-
-    @ProductionComponent.Builder
-    interface Builder {
-      Builder dep(MergedOverride dep);
-
-      TestOverrideComponent build();
-    }
-  }
-
-  @Test
-  public void testPolymorphicOverridesStillCompiles() throws Exception {
-    TestOverrideComponent component =
-        DaggerComponentDependenciesTest_TestOverrideComponent.builder().dep(
-            () -> Futures.immediateFuture("test")).build();
-    assertThat(component.getString().get()).isEqualTo("test");
-  }
-}
diff --git a/javatests/dagger/functional/producers/ProducerFactoryTest.java b/javatests/dagger/functional/producers/ProducerFactoryTest.java
index 6df526e..c85e342 100644
--- a/javatests/dagger/functional/producers/ProducerFactoryTest.java
+++ b/javatests/dagger/functional/producers/ProducerFactoryTest.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.when;
 
diff --git a/javatests/dagger/functional/producers/monitoring/MonitoringTest.java b/javatests/dagger/functional/producers/monitoring/MonitoringTest.java
index 32007a9..543835f 100644
--- a/javatests/dagger/functional/producers/monitoring/MonitoringTest.java
+++ b/javatests/dagger/functional/producers/monitoring/MonitoringTest.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
diff --git a/javatests/dagger/functional/producers/multibindings/MultibindingComponent.java b/javatests/dagger/functional/producers/multibindings/MultibindingComponent.java
index a5eb8a3..fa5c6ee 100644
--- a/javatests/dagger/functional/producers/multibindings/MultibindingComponent.java
+++ b/javatests/dagger/functional/producers/multibindings/MultibindingComponent.java
@@ -30,7 +30,6 @@
 import java.util.Map;
 import java.util.Set;
 
-
 @ProductionComponent(
   modules = {ExecutorModule.class, MultibindingProducerModule.class, MultibindingModule.class}
 )
diff --git a/javatests/dagger/functional/spi/BUILD b/javatests/dagger/functional/spi/BUILD
index 8119bdd..fffaddb 100644
--- a/javatests/dagger/functional/spi/BUILD
+++ b/javatests/dagger/functional/spi/BUILD
@@ -15,19 +15,18 @@
 # Description:
 #   Functional tests for the experimental Dagger SPI
 
-load("@rules_java//java:defs.bzl", "java_library", "java_plugin")
-load("//:test_defs.bzl", "GenJavaTests")
-
 package(default_visibility = ["//:src"])
 
+load("//:test_defs.bzl", "GenJavaTests")
+
 java_plugin(
     name = "test_plugin",
     srcs = ["TestPlugin.java"],
     deps = [
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
+        "//java/dagger/model",
         "//java/dagger/spi",
         "@google_bazel_common//third_party/java/auto:service",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/javapoet",
     ],
 )
diff --git a/javatests/dagger/functional/subcomponent/GenericParentComponent.java b/javatests/dagger/functional/subcomponent/GenericParentComponent.java
index 10745d7..f49083b 100644
--- a/javatests/dagger/functional/subcomponent/GenericParentComponent.java
+++ b/javatests/dagger/functional/subcomponent/GenericParentComponent.java
@@ -16,7 +16,6 @@
 
 package dagger.functional.subcomponent;
 
-
 interface GenericParentComponent<B> {  
   B subcomponent();
 }
diff --git a/javatests/dagger/functional/subcomponent/SubcomponentTest.java b/javatests/dagger/functional/subcomponent/SubcomponentTest.java
index 380322b..c34de0a 100644
--- a/javatests/dagger/functional/subcomponent/SubcomponentTest.java
+++ b/javatests/dagger/functional/subcomponent/SubcomponentTest.java
@@ -50,7 +50,6 @@
     this.childComponent = childComponent;
   }
 
-
   @Test
   public void scopePropagatesUpward_class() {
     assertThat(childComponent.requiresSingleton().singletonType())
diff --git a/javatests/dagger/functional/subcomponent/hiding/ChildComponent.java b/javatests/dagger/functional/subcomponent/hiding/ChildComponent.java
index 846ceb0..7cb4fce 100644
--- a/javatests/dagger/functional/subcomponent/hiding/ChildComponent.java
+++ b/javatests/dagger/functional/subcomponent/hiding/ChildComponent.java
@@ -16,7 +16,6 @@
 
 package dagger.functional.subcomponent.hiding;
 
-
 import dagger.Subcomponent;
 
 @Subcomponent(modules = dagger.functional.subcomponent.hiding.b.CommonModuleName.class)
diff --git a/javatests/dagger/functional/tck/BUILD b/javatests/dagger/functional/tck/BUILD
index 9cad2a0..7526bf0 100644
--- a/javatests/dagger/functional/tck/BUILD
+++ b/javatests/dagger/functional/tck/BUILD
@@ -15,6 +15,8 @@
 # Description:
 #  TCK tests for Dagger
 
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
@@ -22,8 +24,6 @@
 )
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "tck_tests",
     srcs = glob(["*.java"]),
diff --git a/javatests/dagger/grpc/functional/server/BUILD b/javatests/dagger/grpc/functional/server/BUILD
index 0603801..1e8c2e6 100644
--- a/javatests/dagger/grpc/functional/server/BUILD
+++ b/javatests/dagger/grpc/functional/server/BUILD
@@ -1,9 +1,10 @@
 # Functional tests for Dagger-gRPC
 
-load("@rules_java//java:defs.bzl", "java_proto_library")
-
 package(default_visibility = ["//:src"])
 
+load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "DOCLINT_REFERENCES")
+load("//:test_defs.bzl", "GenJavaTests")
+
 # TODO(dpb): enable tests once java_grpc_library is ready in bazel:
 # https://github.com/grpc/grpc-java/issues/2756
 
diff --git a/javatests/dagger/hilt/android/processor/AndroidCompilers.java b/javatests/dagger/hilt/android/processor/AndroidCompilers.java
deleted file mode 100644
index 5ce0a2a..0000000
--- a/javatests/dagger/hilt/android/processor/AndroidCompilers.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor;
-
-import static java.util.stream.Collectors.toMap;
-
-import com.google.common.collect.ImmutableList;
-import com.google.testing.compile.Compiler;
-import dagger.hilt.android.processor.internal.androidentrypoint.AndroidEntryPointProcessor;
-import dagger.hilt.android.processor.internal.customtestapplication.CustomTestApplicationProcessor;
-import dagger.hilt.android.processor.internal.uninstallmodules.UninstallModulesProcessor;
-import dagger.hilt.processor.internal.aggregateddeps.AggregatedDepsProcessor;
-import dagger.hilt.processor.internal.definecomponent.DefineComponentProcessor;
-import dagger.hilt.processor.internal.generatesrootinput.GeneratesRootInputProcessor;
-import dagger.hilt.processor.internal.originatingelement.OriginatingElementProcessor;
-import dagger.hilt.processor.internal.root.RootProcessor;
-import dagger.internal.codegen.ComponentProcessor;
-import dagger.testing.compile.CompilerTests;
-import java.util.Arrays;
-import java.util.Map;
-import javax.annotation.processing.Processor;
-import com.tschuchort.compiletesting.KotlinCompilation;
-
-/** {@link Compiler} instances for testing Android Hilt. */
-public final class AndroidCompilers {
-
-  public static Compiler compiler(Processor... extraProcessors) {
-    Map<Class<?>, Processor> processors =
-        defaultProcessors().stream()
-            .collect(toMap((Processor e) -> e.getClass(), (Processor e) -> e));
-
-    // Adds extra processors, and allows overriding any processors of the same class.
-    Arrays.stream(extraProcessors)
-        .forEach(processor -> processors.put(processor.getClass(), processor));
-
-    return CompilerTests.compiler().withProcessors(processors.values());
-  }
-
-  public static KotlinCompilation kotlinCompiler() {
-    KotlinCompilation compilation = new KotlinCompilation();
-    compilation.setAnnotationProcessors(defaultProcessors());
-    compilation.setClasspaths(
-        ImmutableList.<java.io.File>builder()
-            .addAll(compilation.getClasspaths())
-            .add(CompilerTests.compilerDepsJar())
-            .build()
-    );
-    return compilation;
-  }
-
-  private static ImmutableList<Processor> defaultProcessors() {
-    return ImmutableList.of(
-        new AggregatedDepsProcessor(),
-        new AndroidEntryPointProcessor(),
-        new ComponentProcessor(),
-        new DefineComponentProcessor(),
-        new GeneratesRootInputProcessor(),
-        new OriginatingElementProcessor(),
-        new CustomTestApplicationProcessor(),
-        new UninstallModulesProcessor(),
-        new RootProcessor());
-  }
-
-  private AndroidCompilers() {}
-}
diff --git a/javatests/dagger/hilt/android/processor/BUILD b/javatests/dagger/hilt/android/processor/BUILD
deleted file mode 100644
index 7fb2320..0000000
--- a/javatests/dagger/hilt/android/processor/BUILD
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2020 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.
-# Description:
-#   Tests for internal code for implementing Hilt processors.
-
-package(default_visibility = ["//:src"])
-
-java_library(
-    name = "android_compilers",
-    srcs = ["AndroidCompilers.java"],
-    deps = [
-        "//java/dagger/hilt/android/processor/internal/androidentrypoint:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/customtestapplication:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/uninstallmodules:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
-        "//java/dagger/hilt/processor/internal/aggregateddeps:processor_lib",
-        "//java/dagger/hilt/processor/internal/definecomponent:processor_lib",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:processor_lib",
-        "//java/dagger/hilt/processor/internal/originatingelement:processor_lib",
-        "//java/dagger/hilt/processor/internal/root:processor_lib",
-        "//java/dagger/internal/codegen:processor",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/testing/compile",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@maven//:com_github_tschuchortdev_kotlin_compile_testing",
-    ],
-)
diff --git a/javatests/dagger/hilt/android/processor/internal/aggregateddeps/BUILD b/javatests/dagger/hilt/android/processor/internal/aggregateddeps/BUILD
deleted file mode 100644
index bf2ed4c..0000000
--- a/javatests/dagger/hilt/android/processor/internal/aggregateddeps/BUILD
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (C) 2020 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.
-# Description:
-#   Tests for internal code for implementing Hilt processors.
-
-load("//java/dagger/testing/compile:macros.bzl", "compiler_test")
-
-package(default_visibility = ["//:src"])
-
-compiler_test(
-    name = "TestInstallInTest",
-    srcs = ["TestInstallInTest.java"],
-    compiler_deps = [
-        ":InstallInModule",
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt:entry_point",
-        "//java/dagger/hilt/components",
-        "//java/dagger/hilt/android/internal/modules",
-        "//java/dagger/hilt/testing:test_install_in",
-        "//java/dagger/hilt/android/testing:hilt_android_test",
-        "@androidsdk//:platforms/android-30/android.jar",
-    ],
-    deps = [
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-        "//javatests/dagger/hilt/android/processor:android_compilers",
-    ],
-)
-
-java_library(
-    name = "InstallInModule",
-    srcs = ["InstallInModule.java"],
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/components",
-    ],
-)
diff --git a/javatests/dagger/hilt/android/processor/internal/aggregateddeps/InstallInModule.java b/javatests/dagger/hilt/android/processor/internal/aggregateddeps/InstallInModule.java
deleted file mode 100644
index af535f5..0000000
--- a/javatests/dagger/hilt/android/processor/internal/aggregateddeps/InstallInModule.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.aggregateddeps;
-
-import dagger.Module;
-import dagger.hilt.InstallIn;
-import dagger.hilt.components.SingletonComponent;
-
-/**
- * This is used in TestInstallInTest to test that the wrapper module, HiltWrapper_InstallInModule,
- * cannot be replaced. This needs to be compiled in a separate library because
- * AggregatedDepsProcesor does not defer modules that have not been generated yet.
- */
-@Module
-@InstallIn(SingletonComponent.class)
-interface InstallInModule {}
diff --git a/javatests/dagger/hilt/android/processor/internal/aggregateddeps/TestInstallInTest.java b/javatests/dagger/hilt/android/processor/internal/aggregateddeps/TestInstallInTest.java
deleted file mode 100644
index 3af5be6..0000000
--- a/javatests/dagger/hilt/android/processor/internal/aggregateddeps/TestInstallInTest.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.aggregateddeps;
-
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.hilt.android.processor.AndroidCompilers.compiler;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class TestInstallInTest {
-
-  @Test
-  public void testMissingValues() {
-    JavaFileObject testInstallInModule =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "",
-            "@Module",
-            "@TestInstallIn",
-            "interface TestInstallInModule {}");
-    Compilation compilation = compiler().compile(testInstallInModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@dagger.hilt.testing.TestInstallIn is missing default values for elements "
-                + "components,replaces")
-        .inFile(testInstallInModule)
-        .onLine(7);
-  }
-
-  @Test
-  public void testEmptyComponentValues() {
-    JavaFileObject installInModule =
-        JavaFileObjects.forSourceLines(
-            "test.InstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.InstallIn;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "",
-            "@Module",
-            "@InstallIn(SingletonComponent.class)",
-            "interface InstallInModule {}");
-    JavaFileObject testInstallInModule =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "",
-            "@Module",
-            "@TestInstallIn(components = {}, replaces = InstallInModule.class)",
-            "interface TestInstallInModule {}");
-    Compilation compilation = compiler().compile(installInModule, testInstallInModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    // TODO(bcorso): Add inFile().onLine() whenever we've fixed Processors.getAnnotationClassValues
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@TestInstallIn, 'components' class is invalid or missing: "
-                + "@dagger.hilt.testing.TestInstallIn("
-                + "components={}, replaces={test.InstallInModule.class})");
-  }
-
-  @Test
-  public void testEmptyReplacesValues() {
-    JavaFileObject testInstallInModule =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "",
-            "@Module",
-            "@TestInstallIn(components = SingletonComponent.class, replaces = {})",
-            "interface TestInstallInModule {}");
-    Compilation compilation = compiler().compile(testInstallInModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    // TODO(bcorso): Add inFile().onLine() whenever we've fixed Processors.getAnnotationClassValues
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@TestInstallIn, 'replaces' class is invalid or missing: "
-                + "@dagger.hilt.testing.TestInstallIn("
-                + "components={dagger.hilt.components.SingletonComponent.class}, replaces={})");
-  }
-
-  @Test
-  public void testMissingModuleAnnotation() {
-    JavaFileObject installInModule =
-        JavaFileObjects.forSourceLines(
-            "test.InstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.InstallIn;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "",
-            "@Module",
-            "@InstallIn(SingletonComponent.class)",
-            "interface InstallInModule {}");
-    JavaFileObject testInstallInModule =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "",
-            "@TestInstallIn(",
-            "    components = SingletonComponent.class,",
-            "    replaces = InstallInModule.class)",
-            "interface TestInstallInModule {}");
-    Compilation compilation = compiler().compile(installInModule, testInstallInModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@TestInstallIn-annotated classes must also be annotated with @Module or @EntryPoint: "
-                + "test.TestInstallInModule")
-        .inFile(testInstallInModule)
-        .onLine(10);
-  }
-
-  @Test
-  public void testInvalidUsageOnEntryPoint() {
-    JavaFileObject installInModule =
-        JavaFileObjects.forSourceLines(
-            "test.InstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.InstallIn;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "",
-            "@Module",
-            "@InstallIn(SingletonComponent.class)",
-            "interface InstallInModule {}");
-    JavaFileObject testInstallInEntryPoint =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInEntryPoint",
-            "package test;",
-            "",
-            "import dagger.hilt.EntryPoint;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "",
-            "@EntryPoint",
-            "@TestInstallIn(",
-            "    components = SingletonComponent.class,",
-            "    replaces = InstallInModule.class)",
-            "interface TestInstallInEntryPoint {}");
-    Compilation compilation = compiler().compile(installInModule, testInstallInEntryPoint);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("@TestInstallIn can only be used with modules")
-        .inFile(testInstallInEntryPoint)
-        .onLine(11);
-  }
-
-  @Test
-  public void testInvalidReplaceModules() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines("test.Foo", "package test;", "", "class Foo {}");
-    JavaFileObject testInstallInModule =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "",
-            "@Module",
-            "@TestInstallIn(",
-            "    components = SingletonComponent.class,",
-            "    replaces = Foo.class)",
-            "interface TestInstallInModule {}");
-    Compilation compilation = compiler().compile(foo, testInstallInModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@TestInstallIn#replaces() can only contain @InstallIn modules, but found: [test.Foo]")
-        .inFile(testInstallInModule)
-        .onLine(11);
-  }
-
-  @Test
-  public void testInternalDaggerReplaceModules() {
-    JavaFileObject testInstallInModule =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "",
-            "@Module",
-            "@TestInstallIn(",
-            "    components = SingletonComponent.class,",
-            "    replaces = dagger.hilt.android.internal.modules.ApplicationContextModule.class)",
-            "interface TestInstallInModule {}");
-    Compilation compilation = compiler().compile(testInstallInModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@TestInstallIn#replaces() cannot contain internal Hilt modules, but found: "
-                + "[dagger.hilt.android.internal.modules.ApplicationContextModule]")
-        .inFile(testInstallInModule)
-        .onLine(11);
-  }
-
-  @Test
-  public void testHiltWrapperDaggerReplaceModules() {
-    JavaFileObject testInstallInModule =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "import"
-                + " dagger.hilt.android.processor.internal.aggregateddeps.HiltWrapper_InstallInModule;",
-            "",
-            "@Module",
-            "@TestInstallIn(",
-            "    components = SingletonComponent.class,",
-            // Note: this module is built in a separate library since AggregatedDepsProcessor can't
-            // handle modules generated in the same round.
-            "    replaces = HiltWrapper_InstallInModule.class)",
-            "interface TestInstallInModule {}");
-    Compilation compilation = compiler().compile(testInstallInModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@TestInstallIn#replaces() cannot contain Hilt generated public wrapper modules, "
-                + "but found: [dagger.hilt.android.processor.internal.aggregateddeps."
-                + "HiltWrapper_InstallInModule]")
-        .inFile(testInstallInModule)
-        .onLine(12);
-  }
-
-  @Test
-  public void testCannotReplaceLocalInstallInModule() {
-    JavaFileObject test =
-        JavaFileObjects.forSourceLines(
-            "test.MyTest",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.InstallIn;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "import dagger.hilt.android.testing.HiltAndroidTest;",
-            "",
-            "@HiltAndroidTest",
-            "public class MyTest {",
-            "  @Module",
-            "  @InstallIn(SingletonComponent.class)",
-            "  interface LocalInstallInModule {}",
-            "}");
-    JavaFileObject testInstallIn =
-        JavaFileObjects.forSourceLines(
-            "test.TestInstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "",
-            "@Module",
-            "@TestInstallIn(",
-            "    components = SingletonComponent.class,",
-            "    replaces = MyTest.LocalInstallInModule.class)",
-            "interface TestInstallInModule {}");
-    Compilation compilation = compiler().compile(test, testInstallIn);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "TestInstallIn#replaces() cannot replace test specific @InstallIn modules, but found: "
-                + "[test.MyTest.LocalInstallInModule].")
-        .inFile(testInstallIn)
-        .onLine(11);
-  }
-
-  @Test
-  public void testThatTestInstallInCannotOriginateFromTest() {
-    JavaFileObject installInModule =
-        JavaFileObjects.forSourceLines(
-            "test.InstallInModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.InstallIn;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "",
-            "@Module",
-            "@InstallIn(SingletonComponent.class)",
-            "interface InstallInModule {}");
-    JavaFileObject test =
-        JavaFileObjects.forSourceLines(
-            "test.MyTest",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.testing.TestInstallIn;",
-            "import dagger.hilt.android.testing.HiltAndroidTest;",
-            "",
-            "@HiltAndroidTest",
-            "public class MyTest {",
-            "  @Module",
-            "  @TestInstallIn(",
-            "      components = SingletonComponent.class,",
-            "      replaces = InstallInModule.class)",
-            "  interface TestInstallInModule {}",
-            "}");
-    Compilation compilation = compiler().compile(test, installInModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@TestInstallIn modules cannot be nested in (or originate from) a "
-                + "@HiltAndroidTest-annotated class:  test.MyTest")
-        .inFile(test)
-        .onLine(14);
-  }
-}
diff --git a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGeneratorTest.java b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGeneratorTest.java
deleted file mode 100644
index 25a1abd..0000000
--- a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGeneratorTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.androidentrypoint;
-
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.hilt.android.processor.AndroidCompilers.compiler;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class ActivityGeneratorTest {
-
-  @Test
-  public void generate_componentActivity() {
-    JavaFileObject myActivity =
-        JavaFileObjects.forSourceLines(
-            "test.MyActivity",
-            "package test;",
-            "",
-            "import androidx.activity.ComponentActivity;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint(ComponentActivity.class)",
-            "public class MyActivity extends Hilt_MyActivity {",
-            "}");
-    Compilation compilation = compiler().compile(myActivity);
-    assertThat(compilation).succeeded();
-  }
-
-  @Test
-  public void generate_baseHiltComponentActivity() {
-    JavaFileObject baseActivity =
-        JavaFileObjects.forSourceLines(
-            "test.BaseActivity",
-            "package test;",
-            "",
-            "import androidx.activity.ComponentActivity;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint(ComponentActivity.class)",
-            "public class BaseActivity extends Hilt_BaseActivity {",
-            "}");
-    JavaFileObject myActivity =
-        JavaFileObjects.forSourceLines(
-            "test.MyActivity",
-            "package test;",
-            "",
-            "import androidx.activity.ComponentActivity;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint(BaseActivity.class)",
-            "public class MyActivity extends Hilt_MyActivity {",
-            "}");
-    Compilation compilation = compiler().compile(baseActivity, myActivity);
-    assertThat(compilation).succeeded();
-  }
-}
diff --git a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessorTest.java b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessorTest.java
deleted file mode 100644
index c024a9c..0000000
--- a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessorTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.androidentrypoint;
-
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.hilt.android.processor.AndroidCompilers.compiler;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class AndroidEntryPointProcessorTest {
-
-  @Test
-  public void missingBaseClass() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
-            "test.MyActivity",
-            "package test;",
-            "",
-            "import androidx.activity.ComponentActivity;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint",
-            "public class MyActivity extends ComponentActivity { }");
-    Compilation compilation = compiler().compile(testActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Expected @AndroidEntryPoint to have a value.")
-        ;
-  }
-
-  @Test
-  public void incorrectSuperclass() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
-            "test.MyActivity",
-            "package test;",
-            "",
-            "import androidx.activity.ComponentActivity;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint(ComponentActivity.class)",
-            "public class MyActivity extends ComponentActivity { }");
-    Compilation compilation = compiler().compile(testActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@AndroidEntryPoint class expected to extend Hilt_MyActivity. "
-                + "Found: ComponentActivity")
-        ;
-  }
-
-  @Test
-  public void disableSuperclassValidation_activity() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
-            "test.MyActivity",
-            "package test;",
-            "",
-            "import androidx.activity.ComponentActivity;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint",
-            "public class MyActivity extends ComponentActivity { }");
-    Compilation compilation =
-        compiler()
-            .withOptions("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
-            .compile(testActivity);
-    assertThat(compilation).succeeded();
-  }
-
-  @Test
-  public void disableSuperclassValidation_application() {
-    JavaFileObject testApplication =
-        JavaFileObjects.forSourceLines(
-            "test.MyApp",
-            "package test;",
-            "",
-            "import android.app.Application;",
-            "import dagger.hilt.android.HiltAndroidApp;",
-            "",
-            "@HiltAndroidApp",
-            "public class MyApp extends Application { }");
-    Compilation compilation =
-        compiler()
-            .withOptions("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
-            .compile(testApplication);
-    assertThat(compilation).succeeded();
-  }
-
-  @Test
-  public void checkBaseActivityExtendsComponentActivity() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
-            "test.MyActivity",
-            "package test;",
-            "",
-            "import android.app.Activity;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint(Activity.class)",
-            "public class MyActivity extends Hilt_MyActivity { }");
-    Compilation compilation = compiler().compile(testActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Activities annotated with @AndroidEntryPoint must be a subclass of "
-            + "androidx.activity.ComponentActivity. (e.g. FragmentActivity, AppCompatActivity, "
-            + "etc.)");
-  }
-
-  @Test
-  public void checkBaseActivityWithTypeParameters() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
-            "test.BaseActivity",
-            "package test;",
-            "",
-            "import androidx.activity.ComponentActivity;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint(ComponentActivity.class)",
-            "public class BaseActivity<T> extends Hilt_BaseActivity {}");
-    Compilation compilation = compiler().compile(testActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation).hadErrorContaining(
-        "cannot find symbol\n  symbol: class Hilt_BaseActivity");
-    assertThat(compilation).hadErrorContaining(
-        "@AndroidEntryPoint-annotated classes cannot have type parameters.");
-  }
-
-  @Test
-  public void checkAndroidEntryPointOnApplicationRecommendsHiltAndroidApp() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
-            "test.MyApplication",
-            "package test;",
-            "",
-            "import android.app.Application;",
-            "import dagger.hilt.android.AndroidEntryPoint;",
-            "",
-            "@AndroidEntryPoint(Application.class)",
-            "public class MyApplication extends Hilt_MyApplication { }");
-    Compilation compilation = compiler().compile(testActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("@AndroidEntryPoint cannot be used on an Application. "
-            + "Use @HiltAndroidApp instead.");
-  }
-}
diff --git a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/BUILD b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
deleted file mode 100644
index e53d9e2..0000000
--- a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright (C) 2020 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.
-# Description:
-#   Tests for internal code for implementing Hilt processors.
-
-load("//java/dagger/testing/compile:macros.bzl", "compiler_test")
-
-package(default_visibility = ["//:src"])
-
-compiler_test(
-    name = "ActivityGeneratorTest",
-    srcs = ["ActivityGeneratorTest.java"],
-    compiler_deps = [
-        "//java/dagger/hilt/android:android_entry_point",
-        "@androidsdk//:platforms/android-30/android.jar",
-    ],
-    deps = [
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-        "//javatests/dagger/hilt/android/processor:android_compilers",
-    ],
-)
-
-compiler_test(
-    name = "AndroidEntryPointProcessorTest",
-    srcs = ["AndroidEntryPointProcessorTest.java"],
-    compiler_deps = [
-        "//java/dagger/hilt/android:hilt_android_app",
-        "//java/dagger/hilt/android:android_entry_point",
-        "@androidsdk//:platforms/android-30/android.jar",
-    ],
-    deps = [
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-        "//javatests/dagger/hilt/android/processor:android_compilers",
-    ],
-)
-
-compiler_test(
-    name = "KotlinAndroidEntryPointProcessorTest",
-    srcs = ["KotlinAndroidEntryPointProcessorTest.java"],
-    compiler_deps = [
-        "//java/dagger/hilt/android:hilt_android_app",
-        "//java/dagger/hilt/android:android_entry_point",
-        "@androidsdk//:platforms/android-30/android.jar",
-    ],
-    deps = [
-        "//java/dagger/internal/guava:collect",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-        "//javatests/dagger/hilt/android/processor:android_compilers",
-        "@maven//:com_github_tschuchortdev_kotlin_compile_testing",
-    ],
-)
diff --git a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/KotlinAndroidEntryPointProcessorTest.java b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/KotlinAndroidEntryPointProcessorTest.java
deleted file mode 100644
index 739c87c..0000000
--- a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/KotlinAndroidEntryPointProcessorTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.androidentrypoint;
-
-import static dagger.hilt.android.processor.AndroidCompilers.kotlinCompiler;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.truth.Truth;
-import com.tschuchort.compiletesting.KotlinCompilation;
-import com.tschuchort.compiletesting.KotlinCompilation.ExitCode;
-import com.tschuchort.compiletesting.SourceFile;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class KotlinAndroidEntryPointProcessorTest {
-  @Test
-  public void checkBaseClassConstructorHasNotDefaultParameters() {
-    SourceFile fragmentSrc = SourceFile.Companion.kotlin("MyFragment.kt",
-        String.join("\n",
-            "package test",
-            "",
-            "import dagger.hilt.android.AndroidEntryPoint",
-            "",
-            "@AndroidEntryPoint",
-            "class MyFragment : BaseFragment()"
-        ),
-        false);
-    SourceFile baseFragmentSrc = SourceFile.Companion.kotlin("BaseFragment.kt",
-        String.join("\n",
-            "package test",
-            "",
-            "import androidx.fragment.app.Fragment",
-            "",
-            "abstract class BaseFragment(layoutId: Int = 0) : Fragment()"
-        ),
-        false);
-    KotlinCompilation compilation = kotlinCompiler();
-    compilation.setSources(ImmutableList.of(fragmentSrc, baseFragmentSrc));
-    compilation.setKaptArgs(ImmutableMap.of(
-        "dagger.hilt.android.internal.disableAndroidSuperclassValidation", "true"));
-    KotlinCompilation.Result result = compilation.compile();
-    Truth.assertThat(result.getExitCode()).isEqualTo(ExitCode.COMPILATION_ERROR);
-    Truth.assertThat(result.getMessages()).contains("The base class, 'test.BaseFragment', of the "
-        + "@AndroidEntryPoint, 'test.MyFragment', contains a constructor with default parameters. "
-        + "This is currently not supported by the Gradle plugin. Either specify the base class as "
-        + "described at https://dagger.dev/hilt/gradle-setup#why-use-the-plugin or remove the "
-        + "default value declaration.");
-  }
-}
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/BUILD b/javatests/dagger/hilt/android/processor/internal/viewmodel/BUILD
deleted file mode 100644
index 030efd9..0000000
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/BUILD
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Tests for internal code for implementing Hilt processors.
-
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
-load("//java/dagger/testing/compile:macros.bzl", "kt_compiler_test")
-
-package(default_visibility = ["//:src"])
-
-java_test(
-    name = "ViewModelProcessorTest",
-    runtime_deps = [
-        ":ViewModelProcessorTestLib",
-        "//java/dagger/hilt/android/lifecycle",
-        "@androidsdk//:platforms/android-30/android.jar",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/truth",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
-    ],
-)
-
-kt_jvm_library(
-    name = "ViewModelProcessorTestLib",
-    srcs = [
-        "ViewModelProcessorTest.kt",
-    ],
-    deps = [
-        ":test_utils",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-)
-
-java_test(
-    name = "ViewModelGeneratorTest",
-    runtime_deps = [
-        ":ViewModelGeneratorTestLib",
-        "//java/dagger/hilt/android/lifecycle",
-        "@androidsdk//:platforms/android-30/android.jar",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/truth",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
-    ],
-)
-
-kt_jvm_library(
-    name = "ViewModelGeneratorTestLib",
-    srcs = [
-        "ViewModelGeneratorTest.kt",
-    ],
-    deps = [
-        ":test_utils",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-)
-
-kt_compiler_test(
-    name = "ViewModelValidationPluginTest",
-    srcs = [
-        "ViewModelValidationPluginTest.kt",
-    ],
-    compiler_deps = [
-        "@androidsdk//:platforms/android-30/android.jar",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/truth",
-        "//java/dagger/hilt/android/lifecycle",
-        "//java/dagger/hilt/android:android_entry_point",
-        "//java/dagger/hilt/android:hilt_android_app",
-    ],
-    deps = [
-        ":test_utils",
-        "//:compiler_internals",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:validation_plugin_lib",
-        "//javatests/dagger/hilt/android/processor:android_compilers",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-)
-
-kt_jvm_library(
-    name = "test_utils",
-    srcs = [
-        "TestUtils.kt",
-    ],
-    deps = [
-        "@google_bazel_common//third_party/java/compile_testing",
-    ],
-)
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/TestUtils.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/TestUtils.kt
deleted file mode 100644
index 713cd22..0000000
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/TestUtils.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package dagger.hilt.android.processor.internal.viewmodel
-
-import com.google.testing.compile.JavaFileObjects
-
-val GENERATED_TYPE = try {
-  Class.forName("javax.annotation.processing.Generated")
-  "javax.annotation.processing.Generated"
-} catch (_: ClassNotFoundException) {
-  "javax.annotation.Generated"
-}
-
-const val GENERATED_ANNOTATION =
-  "@Generated(\"dagger.hilt.android.processor.internal.viewmodel.ViewModelProcessor\")"
-
-fun String.toJFO(qName: String) = JavaFileObjects.forSourceString(qName, this.trimIndent())
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelGeneratorTest.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelGeneratorTest.kt
deleted file mode 100644
index 7c3e45f..0000000
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelGeneratorTest.kt
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.viewmodel
-
-import com.google.testing.compile.CompilationSubject.assertThat
-import com.google.testing.compile.Compiler
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ViewModelGeneratorTest {
-
-  private fun compiler(): Compiler = Compiler.javac().withProcessors(ViewModelProcessor())
-
-  @Test
-  fun verifyModule_noArg() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel() { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-        
-        import androidx.lifecycle.ViewModel;
-        import dagger.Binds;
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityRetainedComponent;
-        import dagger.hilt.android.components.ViewModelComponent;
-        import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
-        import dagger.hilt.codegen.OriginatingElement;
-        import dagger.multibindings.IntoMap;
-        import dagger.multibindings.IntoSet;
-        import dagger.multibindings.StringKey;
-        import java.lang.String;
-        import $GENERATED_TYPE
-        
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-        
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-        
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-        
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
-
-    val compilation = compiler()
-      .compile(myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .hasSourceEquivalentTo(expected)
-    }
-  }
-
-  @Test
-  fun verifyModule_savedStateOnlyArg() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import androidx.lifecycle.SavedStateHandle;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel(SavedStateHandle savedState) { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-        
-        import androidx.lifecycle.ViewModel;
-        import dagger.Binds;
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityRetainedComponent;
-        import dagger.hilt.android.components.ViewModelComponent;
-        import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
-        import dagger.hilt.codegen.OriginatingElement;
-        import dagger.multibindings.IntoMap;
-        import dagger.multibindings.IntoSet;
-        import dagger.multibindings.StringKey;
-        import java.lang.String;
-        import $GENERATED_TYPE
-        
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-        
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-        
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-        
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
-
-    val compilation = compiler()
-      .compile(myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .hasSourceEquivalentTo(expected)
-    }
-  }
-
-  @Test
-  fun verifyModule_mixedArgs() {
-    val foo = """
-        package dagger.hilt.android.test;
-
-        public class Foo { }
-        """.toJFO("dagger.hilt.android.test.Foo")
-
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import androidx.lifecycle.SavedStateHandle;
-        import java.lang.String;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel(String s, Foo f, SavedStateHandle savedState, long l) { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-        
-        import androidx.lifecycle.ViewModel;
-        import dagger.Binds;
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityRetainedComponent;
-        import dagger.hilt.android.components.ViewModelComponent;
-        import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
-        import dagger.hilt.codegen.OriginatingElement;
-        import dagger.multibindings.IntoMap;
-        import dagger.multibindings.IntoSet;
-        import dagger.multibindings.StringKey;
-        import java.lang.String;
-        import $GENERATED_TYPE
-        
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-        
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-        
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-        
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
-
-    val compilation = compiler()
-      .compile(foo, myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .hasSourceEquivalentTo(expected)
-    }
-  }
-
-  @Test
-  fun verifyModule_mixedAndProviderArgs() {
-    val foo = """
-        package dagger.hilt.android.test;
-
-        public class Foo { }
-        """.toJFO("dagger.hilt.android.test.Foo")
-
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import androidx.lifecycle.SavedStateHandle;
-        import java.lang.String;
-        import javax.inject.Inject;
-        import javax.inject.Provider;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel(String s, Provider<Foo> f, SavedStateHandle savedState) { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-    
-        import androidx.lifecycle.ViewModel;
-        import dagger.Binds;
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityRetainedComponent;
-        import dagger.hilt.android.components.ViewModelComponent;
-        import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
-        import dagger.hilt.codegen.OriginatingElement;
-        import dagger.multibindings.IntoMap;
-        import dagger.multibindings.IntoSet;
-        import dagger.multibindings.StringKey;
-        import java.lang.String;
-        import $GENERATED_TYPE;
-        
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-        
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-        
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-        
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModules")
-
-    val compilation = compiler()
-      .compile(foo, myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .hasSourceEquivalentTo(expected)
-    }
-  }
-
-  @Test
-  fun verifyModule_qualifiedArgs() {
-    val myQualifier = """
-        package dagger.hilt.android.test;
-
-        import javax.inject.Qualifier;
-
-        @Qualifier
-        public @interface MyQualifier { }
-        """.toJFO("dagger.hilt.android.test.MyQualifier")
-
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import androidx.lifecycle.SavedStateHandle;
-        import java.lang.Long;
-        import java.lang.String;
-        import javax.inject.Inject;
-        import javax.inject.Named;
-        import javax.inject.Provider;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel(@Named("TheString") String s, @MyQualifier Provider<Long> l,
-                    SavedStateHandle savedState) {
-            }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-        
-        import androidx.lifecycle.ViewModel;
-        import dagger.Binds;
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityRetainedComponent;
-        import dagger.hilt.android.components.ViewModelComponent;
-        import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
-        import dagger.hilt.codegen.OriginatingElement;
-        import dagger.multibindings.IntoMap;
-        import dagger.multibindings.IntoSet;
-        import dagger.multibindings.StringKey;
-        import java.lang.String;
-        import $GENERATED_TYPE;
-        
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-        
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-        
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-        
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModules")
-
-    val compilation = compiler()
-      .compile(myQualifier, myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .hasSourceEquivalentTo(expected)
-    }
-  }
-
-  @Test
-  fun verifyInnerClass() {
-    val viewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import javax.inject.Inject;
-
-        class Outer {
-            @HiltViewModel
-            static class InnerViewModel extends ViewModel {
-                @Inject
-                InnerViewModel() { }
-            }
-        }
-        """.toJFO("dagger.hilt.android.test.Outer")
-
-    val expectedModule = """
-        package dagger.hilt.android.test;
-        
-        import androidx.lifecycle.ViewModel;
-        import dagger.Binds;
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityRetainedComponent;
-        import dagger.hilt.android.components.ViewModelComponent;
-        import dagger.hilt.android.internal.lifecycle.HiltViewModelMap;
-        import dagger.hilt.codegen.OriginatingElement;
-        import dagger.multibindings.IntoMap;
-        import dagger.multibindings.IntoSet;
-        import dagger.multibindings.StringKey;
-        import java.lang.String;
-        import $GENERATED_TYPE
-        
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = Outer.class
-        )
-        public final class Outer_InnerViewModel_HiltModules {
-          private Outer_InnerViewModel_HiltModules() {
-          }
-        
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.Outer${'$'}InnerViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(Outer.InnerViewModel vm);
-          }
-        
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-        
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.Outer${'$'}InnerViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.Outer_InnerViewModel_HiltModules")
-
-    val compilation = compiler()
-      .compile(viewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.Outer_InnerViewModel_HiltModules")
-        .hasSourceEquivalentTo(expectedModule)
-    }
-  }
-}
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessorTest.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessorTest.kt
deleted file mode 100644
index b3eaeab..0000000
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessorTest.kt
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.viewmodel
-
-import com.google.testing.compile.CompilationSubject.assertThat
-import com.google.testing.compile.Compiler
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ViewModelProcessorTest {
-
-  private fun compiler(): Compiler = Compiler.javac().withProcessors(ViewModelProcessor())
-
-  @Test
-  fun validViewModel() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject MyViewModel() { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val compilation = compiler().compile(myViewModel)
-    assertThat(compilation).succeeded()
-  }
-
-  @Test
-  fun verifyEnclosingElementExtendsViewModel() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel {
-            @Inject
-            MyViewModel() { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val compilation = compiler().compile(myViewModel)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "@HiltViewModel is only supported on types that subclass androidx.lifecycle.ViewModel."
-      )
-    }
-  }
-
-  @Test
-  fun verifySingleAnnotatedConstructor() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel() { }
-
-            @Inject
-            MyViewModel(String s) { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val compilation = compiler().compile(myViewModel)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "@HiltViewModel annotated class should contain exactly one @Inject annotated constructor."
-      )
-    }
-  }
-
-  @Test
-  fun verifyNonPrivateConstructor() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            private MyViewModel() { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val compilation = compiler().compile(myViewModel)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "@Inject annotated constructors must not be " +
-          "private."
-      )
-    }
-  }
-
-  @Test
-  fun verifyInnerClassIsStatic() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        class Outer {
-            @HiltViewModel
-            class MyViewModel extends ViewModel {
-                @Inject
-                MyViewModel() { }
-            }
-        }
-        """.toJFO("dagger.hilt.android.test.Outer")
-
-    val compilation = compiler().compile(myViewModel)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "@HiltViewModel may only be used on inner classes if they are static."
-      )
-    }
-  }
-
-  @Test
-  fun verifyNoScopeAnnotation() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-        import javax.inject.Singleton;
-
-        @Singleton
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject MyViewModel() { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val compilation = compiler().compile(myViewModel)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "@HiltViewModel classes should not be scoped. Found: @javax.inject.Singleton"
-      )
-    }
-  }
-}
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginTest.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginTest.kt
deleted file mode 100644
index b5c22c1..0000000
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginTest.kt
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.android.processor.internal.viewmodel
-
-import com.google.testing.compile.CompilationSubject.assertThat
-import com.google.testing.compile.Compiler
-import dagger.hilt.android.processor.AndroidCompilers.compiler
-import dagger.internal.codegen.ComponentProcessor
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ViewModelValidationPluginTest {
-
-  private fun testCompiler(): Compiler = compiler(
-    ComponentProcessor.forTesting(ViewModelValidationPlugin()),
-    ViewModelProcessor()
-  )
-
-  private val hiltAndroidApp = """
-      package test;
-
-      import android.app.Application;
-      import dagger.hilt.android.HiltAndroidApp;
-
-      @HiltAndroidApp(Application.class)
-      public class TestApplication extends Hilt_TestApplication {}
-      """.toJFO("test.TestApplication")
-
-  @Test
-  fun injectViewModelIsProhibited() {
-    val hiltActivity = """
-      package test;
-
-      import androidx.fragment.app.FragmentActivity;
-      import dagger.hilt.android.AndroidEntryPoint;
-      import javax.inject.Inject;
-
-      @AndroidEntryPoint(FragmentActivity.class)
-      public class TestActivity extends Hilt_TestActivity {
-        @Inject Foo foo;
-      }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
-        package test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject MyViewModel() { }
-        }
-        """.toJFO("test.MyViewModel")
-    val foo = """
-        package test;
-
-        import javax.inject.Inject;
-
-        final class Foo {
-            @Inject Foo(MyViewModel viewModel) {}
-        }
-    """.toJFO("test.Foo")
-
-    val compilation = testCompiler().compile(foo, hiltViewModel, hiltAndroidApp, hiltActivity)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "Injection of an @HiltViewModel class is prohibited"
-      )
-    }
-  }
-
-  @Test
-  fun fieldInjectedViewModelIsProhibited() {
-    val hiltActivity = """
-      package test;
-
-      import androidx.fragment.app.FragmentActivity;
-      import dagger.hilt.android.AndroidEntryPoint;
-      import javax.inject.Inject;
-
-      @AndroidEntryPoint(FragmentActivity.class)
-      public class TestActivity extends Hilt_TestActivity {
-        @Inject MyViewModel viewModel;
-      }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
-        package test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject MyViewModel() { }
-        }
-        """.toJFO("test.MyViewModel")
-
-    val compilation = testCompiler().compile(hiltViewModel, hiltAndroidApp, hiltActivity)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "Injection of an @HiltViewModel class is prohibited"
-      )
-    }
-  }
-
-  @Test
-  fun injectViewModelFromViewModelComponentIsProhibited() {
-    // Use an @HiltViewModel that injects a Foo to get the binding inside the ViewModelComponent
-    val hiltViewModel = """
-        package test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject MyViewModel(Foo foo) { }
-        }
-        """.toJFO("test.MyViewModel")
-
-    val foo = """
-        package test;
-
-        import javax.inject.Inject;
-        import javax.inject.Provider;
-
-        final class Foo {
-            @Inject Foo(Provider<MyViewModel> viewModelProvider) {}
-        }
-    """.toJFO("test.Foo")
-
-    val compilation = testCompiler().compile(foo, hiltViewModel, hiltAndroidApp)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "Injection of an @HiltViewModel class is prohibited"
-      )
-    }
-  }
-
-  @Test
-  fun injectOverriddenViewModelBindingIsAllowed() {
-    val hiltActivity = """
-      package test;
-
-      import androidx.fragment.app.FragmentActivity;
-      import dagger.hilt.android.AndroidEntryPoint;
-      import javax.inject.Inject;
-
-      @AndroidEntryPoint(FragmentActivity.class)
-      public class TestActivity extends Hilt_TestActivity {
-        @Inject Foo foo;
-      }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
-        package test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject MyViewModel() { }
-        }
-        """.toJFO("test.MyViewModel")
-    val foo = """
-        package test;
-
-        import javax.inject.Inject;
-
-        final class Foo {
-            @Inject Foo(MyViewModel viewModel) {}
-        }
-    """.toJFO("test.Foo")
-    val activityModule = """
-        package test;
-
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityComponent;
-
-        @InstallIn(ActivityComponent.class)
-        @Module
-        public final class ActivityModule {
-          @Provides static MyViewModel provideMyViewModel() {
-            // Normally you'd expect this to use a ViewModelProvider or something but
-            // since this test is just testing the binding graph, for simplicity just return
-            // null.
-            return null;
-          }
-        }
-    """.toJFO("test.ActivityModule")
-
-    val compilation = testCompiler().compile(
-      foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity
-    )
-    assertThat(compilation).succeeded()
-  }
-
-  @Test
-  fun injectQualifiedViewModelBindingIsAllowed() {
-    val hiltActivity = """
-      package test;
-
-      import androidx.fragment.app.FragmentActivity;
-      import dagger.hilt.android.AndroidEntryPoint;
-      import javax.inject.Inject;
-
-      @AndroidEntryPoint(FragmentActivity.class)
-      public class TestActivity extends Hilt_TestActivity {
-        @Inject Foo foo;
-      }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
-        package test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject MyViewModel() { }
-        }
-        """.toJFO("test.MyViewModel")
-    val foo = """
-        package test;
-
-        import javax.inject.Inject;
-
-        final class Foo {
-            @Inject Foo(@ActivityModule.MyQualifier MyViewModel viewModel) {}
-        }
-    """.toJFO("test.Foo")
-    val activityModule = """
-        package test;
-
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityComponent;
-        import javax.inject.Qualifier;
-
-        @InstallIn(ActivityComponent.class)
-        @Module
-        public final class ActivityModule {
-          @Qualifier
-          public @interface MyQualifier {}
-
-          @Provides
-          @MyQualifier
-          static MyViewModel provideMyViewModel() {
-            // Normally you'd expect this to use a ViewModelProvider or something but
-            // since this test is just testing the binding graph, for simplicity just return
-            // null.
-            return null;
-          }
-        }
-    """.toJFO("test.ActivityModule")
-
-    val compilation = testCompiler().compile(
-      foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity
-    )
-    assertThat(compilation).succeeded()
-  }
-
-  // Regression test for not handling array types properly
-  @Test
-  fun correctlyAllowsOtherBindings() {
-    val hiltActivity = """
-      package test;
-
-      import androidx.fragment.app.FragmentActivity;
-      import dagger.hilt.android.AndroidEntryPoint;
-      import javax.inject.Inject;
-
-      @AndroidEntryPoint(FragmentActivity.class)
-      public class TestActivity extends Hilt_TestActivity {
-        @Inject Foo foo;
-      }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
-        package test;
-
-        import androidx.lifecycle.ViewModel;
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject MyViewModel() { }
-        }
-        """.toJFO("test.MyViewModel")
-    val foo = """
-        package test;
-
-        import javax.inject.Inject;
-
-        final class Foo {
-            @Inject Foo(Long[] longArray) {}
-        }
-    """.toJFO("test.Foo")
-    val activityModule = """
-        package test;
-
-        import dagger.Module;
-        import dagger.Provides;
-        import dagger.hilt.InstallIn;
-        import dagger.hilt.android.components.ActivityComponent;
-
-        @InstallIn(ActivityComponent.class)
-        @Module
-        public final class ActivityModule {
-          @Provides
-          static Long[] provideLongArray() {
-            return null;
-          }
-        }
-    """.toJFO("test.ActivityModule")
-
-    val compilation = testCompiler().compile(
-      foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity
-    )
-    assertThat(compilation).succeeded()
-  }
-}
diff --git a/javatests/dagger/hilt/processor/internal/BUILD b/javatests/dagger/hilt/processor/internal/BUILD
deleted file mode 100644
index e6e1cfb..0000000
--- a/javatests/dagger/hilt/processor/internal/BUILD
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Description:
-#   Tests for internal code for implementing Hilt processors.
-
-package(default_visibility = ["//:src"])
-
-java_test(
-    name = "ProcessorsTest",
-    size = "small",
-    srcs = ["ProcessorsTest.java"],
-    deps = [
-        "//java/dagger/hilt/processor/internal:processors",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-)
-
-java_library(
-    name = "generated_import",
-    srcs = ["GeneratedImport.java"],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["**/*"]),
-)
diff --git a/javatests/dagger/hilt/processor/internal/GeneratedImport.java b/javatests/dagger/hilt/processor/internal/GeneratedImport.java
deleted file mode 100644
index 0feaa4e..0000000
--- a/javatests/dagger/hilt/processor/internal/GeneratedImport.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal;
-
-/** Utility class for @Generated usage in tests. */
-public final class GeneratedImport {
-  public static final String IMPORT_GENERATED_ANNOTATION =
-      isBeforeJava9()
-          ? "import javax.annotation.Generated;"
-          : "import javax.annotation.processing.Generated;";
-
-  private static boolean isBeforeJava9() {
-    try {
-      Class.forName("java.lang.Module");
-      return false;
-    } catch (ClassNotFoundException e) {
-      return true;
-    }
-  }
-
-  private GeneratedImport() {}
-}
diff --git a/javatests/dagger/hilt/processor/internal/ProcessorsTest.java b/javatests/dagger/hilt/processor/internal/ProcessorsTest.java
deleted file mode 100644
index cad41aa..0000000
--- a/javatests/dagger/hilt/processor/internal/ProcessorsTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeVariableName;
-import java.util.List;
-import javax.lang.model.element.Modifier;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class ProcessorsTest {
-
-  @Test
-  public void testCopyMethodSpecWithoutBodyForMethod() throws Exception {
-    TypeVariableName t = TypeVariableName.get("T", Number.class);
-    ClassName list = ClassName.get(List.class);
-    MethodSpec.Builder builder = MethodSpec.methodBuilder("myMethod")
-        .addJavadoc("This is a test line 1 in the java doc \n"
-            + "This is a test line 2 in the java doc \n"
-            + "<p>Test Use of links {@link $T} \n", list)
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC)
-        .addParameter(ParameterizedTypeName.get(list, t), "list", Modifier.FINAL)
-        .returns(ParameterizedTypeName.get(list, t))
-        .addException(IllegalArgumentException.class)
-        .addTypeVariable(t);
-
-    // Test that method copy is the same as original
-    MethodSpec method = builder.build();
-    MethodSpec methodCopy = Processors.copyMethodSpecWithoutBody(method).build();
-    assertThat(method.toString()).contains(methodCopy.toString());
-
-    // Test that method copy removes the body, compare with the old copy
-    MethodSpec methodWithBody = builder.addStatement("return list").build();
-    MethodSpec methodCopyWithBody = Processors.copyMethodSpecWithoutBody(methodWithBody).build();
-    assertThat(methodCopyWithBody.toString()).isEqualTo(methodCopy.toString());
-
-  }
-
-  @Test
-  public void testCopyMethodSpecWithoutBodyForConstructor() throws Exception {
-    TypeVariableName t = TypeVariableName.get("T", Number.class);
-    ClassName list = ClassName.get(List.class);
-    MethodSpec.Builder builder = MethodSpec.constructorBuilder()
-        .addJavadoc("This is a test line 1 in the java doc \n"
-            + "This is a test line 2 in the java doc \n"
-            + "<p>Test Use of links {@link $T} \n", list)
-        .addAnnotation(Override.class)
-        .addModifiers(Modifier.PUBLIC)
-        .addParameter(ParameterizedTypeName.get(list, t), "list", Modifier.FINAL)
-        .addException(IllegalArgumentException.class)
-        .addTypeVariable(t);
-
-    // Test that method copy is the same as original
-    MethodSpec method = builder.build();
-    MethodSpec methodCopy = Processors.copyMethodSpecWithoutBody(method).build();
-    assertThat(method.toString()).contains(methodCopy.toString());
-
-    // Test that method copy removes the body, compare with the old copy
-    MethodSpec methodWithBody = builder.addStatement("this.list = list").build();
-    MethodSpec methodCopyWithBody = Processors.copyMethodSpecWithoutBody(methodWithBody).build();
-    assertThat(methodCopyWithBody.toString()).isEqualTo(methodCopy.toString());
-  }
-}
diff --git a/javatests/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessorErrorsTest.java b/javatests/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessorErrorsTest.java
deleted file mode 100644
index b36a71d..0000000
--- a/javatests/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessorErrorsTest.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.aggregateddeps;
-
-import static com.google.testing.compile.CompilationSubject.assertThat;
-
-import com.google.common.base.Joiner;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import dagger.hilt.processor.internal.GeneratedImport;
-import dagger.testing.compile.CompilerTests;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Tests for errors generated by {@link AggregatedDepsProcessor} */
-@RunWith(JUnit4.class)
-public class AggregatedDepsProcessorErrorsTest {
-  private static final Joiner LINES = Joiner.on("\n");
-
-  @Test
-  public void reportMultipleAnnotationTypeKindErrors() {
-    JavaFileObject source =
-        JavaFileObjects.forSourceString(
-            "foo.bar.AnnotationsOnWrongTypeKind",
-            LINES.join(
-                "package foo.bar;",
-                "",
-                "import dagger.hilt.EntryPoint;",
-                "import dagger.hilt.InstallIn;",
-                "import dagger.Module;",
-                "import dagger.hilt.components.SingletonComponent;",
-                "import dagger.hilt.internal.ComponentEntryPoint;",
-                "import dagger.hilt.internal.GeneratedEntryPoint;",
-                "",
-                "@InstallIn(SingletonComponent.class)",
-                "@Module",
-                "enum FooModule { VALUE }",
-                "",
-                "@InstallIn(SingletonComponent.class)",
-                "@EntryPoint",
-                "final class BarEntryPoint {}",
-                "",
-                "@InstallIn(SingletonComponent.class)",
-                "@ComponentEntryPoint",
-                "final class BazComponentEntryPoint {}",
-                "",
-                "@EntryPoint",
-                "interface QuxEntryPoint {}",
-                "",
-                "@EntryPoint",
-                "@Module",
-                "interface DontMix{}",
-                ""));
-
-    Compilation compilation =
-        CompilerTests.compiler().withProcessors(new AggregatedDepsProcessor()).compile(source);
-
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Only classes and interfaces can be annotated with @Module")
-        .inFile(source)
-        .onLine(12);
-    assertThat(compilation)
-        .hadErrorContaining("Only interfaces can be annotated with @EntryPoint")
-        .inFile(source)
-        .onLine(16);
-    assertThat(compilation)
-        .hadErrorContaining("Only interfaces can be annotated with @ComponentEntryPoint")
-        .inFile(source)
-        .onLine(20);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@EntryPoint foo.bar.QuxEntryPoint must also be annotated with @InstallIn")
-        .inFile(source)
-        .onLine(23);
-    assertThat(compilation)
-        .hadErrorContaining("@Module and @EntryPoint cannot be used on the same interface")
-        .inFile(source)
-        .onLine(27);
-  }
-
-  @Test
-  public void testInvalidComponentInInstallInAnnotation() {
-    JavaFileObject module = JavaFileObjects.forSourceLines(
-        "test.FooModule",
-        "package test;",
-        "",
-        "import dagger.Module;",
-        "import dagger.hilt.InstallIn;",
-        "import dagger.hilt.android.qualifiers.ApplicationContext;",
-        "",
-        "@InstallIn(ApplicationContext.class)", // Error: Not a Hilt component
-        "@Module",
-        "final class FooModule {}");
-
-    Compilation compilation =
-        CompilerTests.compiler().withProcessors(new AggregatedDepsProcessor()).compile(module);
-
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@InstallIn, can only be used with @DefineComponent-annotated classes, but found: "
-                + "[dagger.hilt.android.qualifiers.ApplicationContext]")
-        .inFile(module)
-        .onLine(9);
-  }
-
-  @Test
-  public void testMissingInstallInAnnotation() {
-    JavaFileObject source = JavaFileObjects.forSourceString(
-        "foo.bar.AnnotationsOnWrongTypeKind",
-        LINES.join(
-            "package foo.bar;",
-            "",
-            "import dagger.Module;",
-            "",
-            "@Module",     // Error: Doesn't have InstallIn annotation
-            "final class FooModule {}"));
-
-    Compilation compilation =
-        CompilerTests.compiler().withProcessors(new AggregatedDepsProcessor()).compile(source);
-
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("foo.bar.FooModule is missing an @InstallIn annotation")
-        .inFile(source)
-        .onLine(6);
-  }
-
-  @Test
-  public void testNoErrorOnDaggerGeneratedModules() {
-    JavaFileObject source =
-        JavaFileObjects.forSourceString(
-            "foo.bar",
-            LINES.join(
-                "package foo.bar;",
-                "",
-                GeneratedImport.IMPORT_GENERATED_ANNOTATION,
-                "import dagger.Module;",
-                "",
-                "@Module",
-                "@Generated(value = \"something\")", // Error: Isn't Dagger-generated but missing
-                                                     // InstallIn
-                "final class FooModule {}",
-                "",
-                "@Module",
-                "@Generated(value = \"dagger\")", // No error because the module is dagger generated
-                "final class BarModule {}"));
-
-    Compilation compilation =
-        CompilerTests.compiler().withProcessors(new AggregatedDepsProcessor()).compile(source);
-
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("foo.bar.FooModule is missing an @InstallIn annotation")
-        .inFile(source)
-        .onLine(8);
-  }
-
-  @Test
-  public void testModuleWithOnlyParamConstructor_fails() {
-    JavaFileObject source = JavaFileObjects.forSourceString("foo.bar", LINES.join(
-        "package foo.bar;",
-        "",
-        "import dagger.Module;",
-        "import dagger.Provides;",
-        "import dagger.hilt.InstallIn;",
-        "import dagger.hilt.components.SingletonComponent;",
-        "",
-        "@Module",
-        "@InstallIn(SingletonComponent.class)",
-        "final class FooModule {",
-        "  FooModule(String arg) {}",
-        "",
-        "  @Provides",
-        "  String provideString() {",
-        "    return \"\";",
-        "  }",
-        "}"));
-
-    Compilation compilation =
-        CompilerTests.compiler().withProcessors(new AggregatedDepsProcessor()).compile(source);
-
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Modules that need to be instantiated by Hilt must have a visible, empty constructor.");
-  }
-
-  @Test
-  public void testInnerModule() {
-    JavaFileObject source = JavaFileObjects.forSourceString("foo.bar", LINES.join(
-        "package foo.bar;",
-        "",
-        "import dagger.Module;",
-        "import dagger.hilt.InstallIn;",
-        "import dagger.hilt.components.SingletonComponent;",
-        "",
-        "final class Outer {",
-        "  @Module",
-        "  @InstallIn(SingletonComponent.class)",
-        "  final class InnerModule {}",
-        "}"));
-
-    Compilation compilation =
-        CompilerTests.compiler().withProcessors(new AggregatedDepsProcessor()).compile(source);
-
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Nested @InstallIn modules must be static unless they are directly nested within a "
-                + "test. Found: foo.bar.Outer.InnerModule");
-  }
-
-  @Test
-  public void testInnerModuleInTest() {
-    JavaFileObject source = JavaFileObjects.forSourceString("foo.bar", LINES.join(
-        "package foo.bar;",
-        "",
-        "import dagger.Module;",
-        "import dagger.hilt.InstallIn;",
-        "import dagger.hilt.components.SingletonComponent;",
-        "import dagger.hilt.android.testing.HiltAndroidTest;",
-        "",
-        "@HiltAndroidTest",
-        "final class Outer {",
-        "  static class Nested {",
-        "    @Module",
-        "    @InstallIn(SingletonComponent.class)",
-        "    final class InnerModule {}",
-        "  }",
-        "}"));
-
-    Compilation compilation =
-        CompilerTests.compiler().withProcessors(new AggregatedDepsProcessor()).compile(source);
-
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Nested @InstallIn modules must be static unless they are directly nested within a "
-                + "test. Found: foo.bar.Outer.Nested.InnerModule");
-  }
-
-  @Test
-  public void testInnerModuleInTest_succeeds() {
-    JavaFileObject source = JavaFileObjects.forSourceString("foo.bar", LINES.join(
-        "package foo.bar;",
-        "",
-        "import dagger.Module;",
-        "import dagger.hilt.InstallIn;",
-        "import dagger.hilt.components.SingletonComponent;",
-        "import dagger.hilt.android.testing.HiltAndroidTest;",
-        "",
-        "@HiltAndroidTest",
-        "final class Outer {",
-        "  @Module",
-        "  @InstallIn(SingletonComponent.class)",
-        "  final class InnerModule {}",
-        "}"));
-
-    Compilation compilation =
-        CompilerTests.compiler().withProcessors(new AggregatedDepsProcessor()).compile(source);
-
-    assertThat(compilation).succeeded();
-  }
-}
diff --git a/javatests/dagger/hilt/processor/internal/aggregateddeps/BUILD b/javatests/dagger/hilt/processor/internal/aggregateddeps/BUILD
deleted file mode 100644
index f52b051..0000000
--- a/javatests/dagger/hilt/processor/internal/aggregateddeps/BUILD
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2020 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.
-#
-# Description:
-#  Builds and run tests related to AggregatedDepsProcessor.
-
-load("//java/dagger/testing/compile:macros.bzl", "compiler_test")
-
-package(default_visibility = ["//:src"])
-
-compiler_test(
-    name = "AggregatedDepsProcessorErrorsTest",
-    size = "small",
-    srcs = ["AggregatedDepsProcessorErrorsTest.java"],
-    compiler_deps = [
-        "//java/dagger/hilt/internal:component_entry_point",
-        "//java/dagger/hilt/internal:generated_entry_point",
-        "//:dagger_with_compiler",
-        "@google_bazel_common//third_party/java/jsr250_annotations",
-        "//java/dagger/hilt:entry_point",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android/testing:hilt_android_test",
-        "//java/dagger/hilt/android/components",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal/aggregateddeps:processor_lib",
-        "//java/dagger/internal/guava:base",
-        "//javatests/dagger/hilt/processor/internal:generated_import",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/javatests/dagger/hilt/processor/internal/definecomponent/BUILD b/javatests/dagger/hilt/processor/internal/definecomponent/BUILD
deleted file mode 100644
index ce5cc0a..0000000
--- a/javatests/dagger/hilt/processor/internal/definecomponent/BUILD
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (C) 2020 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.
-#
-# Description:
-#   Tests for Hilt's DefineComponentProcessor
-
-load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
-load("//:test_defs.bzl", "GenJavaTests")
-
-package(default_visibility = ["//:src"])
-
-GenJavaTests(
-    name = "hilt_processor_tests",
-    srcs = glob(["*.java"]),
-    functional = False,
-    javacopts = DOCLINT_HTML_AND_SYNTAX,
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:entry_point",
-        "//java/dagger/hilt:install_in",
-        "//java/dagger/hilt/android/components",
-        "//java/dagger/hilt/android/qualifiers",
-        "//java/dagger/hilt/processor/internal/definecomponent:define_components",
-        "//java/dagger/hilt/processor/internal/definecomponent:processor_lib",
-        "//javatests/dagger/hilt/processor/internal:generated_import",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/javatests/dagger/hilt/processor/internal/definecomponent/DefineComponentProcessorTest.java b/javatests/dagger/hilt/processor/internal/definecomponent/DefineComponentProcessorTest.java
deleted file mode 100644
index 901c7a3..0000000
--- a/javatests/dagger/hilt/processor/internal/definecomponent/DefineComponentProcessorTest.java
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.definecomponent;
-
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static com.google.testing.compile.Compiler.javac;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.Compiler;
-import com.google.testing.compile.JavaFileObjects;
-import dagger.hilt.processor.internal.GeneratedImport;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class DefineComponentProcessorTest {
-
-  @Test
-  public void testDefineComponentOutput() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent(parent = SingletonComponent.class)",
-            "interface FooComponent {",
-            "  static int staticField = 1;",
-            "  static int staticMethod() { return staticField; }",
-            "}");
-
-    JavaFileObject builder =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponentBuilder",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent.Builder",
-            "interface FooComponentBuilder {",
-            "  static int staticField = 1;",
-            "  static int staticMethod() { return staticField; }",
-            "",
-            "  FooComponent create();",
-            "}");
-
-    JavaFileObject componentOutput =
-        JavaFileObjects.forSourceLines(
-            "dagger.hilt.processor.internal.definecomponent.codegen.test_FooComponent",
-            "package dagger.hilt.processor.internal.definecomponent.codegen;",
-            "",
-            "import dagger.hilt.internal.definecomponent.DefineComponentClasses;",
-            GeneratedImport.IMPORT_GENERATED_ANNOTATION,
-            "",
-            "@DefineComponentClasses(component = \"test.FooComponent\")",
-            "@Generated(\"" + DefineComponentProcessor.class.getName() + "\")",
-            "interface test_FooComponent {}");
-
-    JavaFileObject builderOutput =
-        JavaFileObjects.forSourceLines(
-            "dagger.hilt.processor.internal.definecomponent.codegen.test_FooComponentBuilder",
-            "package dagger.hilt.processor.internal.definecomponent.codegen;",
-            "",
-            "import dagger.hilt.internal.definecomponent.DefineComponentClasses;",
-            GeneratedImport.IMPORT_GENERATED_ANNOTATION,
-            "",
-            "@DefineComponentClasses(builder = \"test.FooComponentBuilder\")",
-            "@Generated(\"" + DefineComponentProcessor.class.getName() + "\")",
-            "interface test_FooComponentBuilder {}");
-
-    Compilation compilation = compiler().compile(component, builder);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile(sourceName(componentOutput))
-        .hasSourceEquivalentTo(componentOutput);
-    assertThat(compilation)
-        .generatedSourceFile(sourceName(builderOutput))
-        .hasSourceEquivalentTo(builderOutput);
-  }
-
-  private static String sourceName(JavaFileObject fileObject) {
-    return fileObject.getName().replace(".java", "").replace('.', '/');
-  }
-
-  @Test
-  public void testDefineComponentClass_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent( parent = SingletonComponent.class )",
-            "abstract class FooComponent {}");
-
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent is only allowed on interfaces. Found: test.FooComponent");
-  }
-
-  @Test
-  public void testDefineComponentWithTypeParameters_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent( parent = SingletonComponent.class )",
-            "interface FooComponent<T> {}");
-
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("@DefineComponent test.FooComponent<T>, cannot have type parameters.");
-  }
-
-  @Test
-  public void testDefineComponentWithInvalidComponent_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "import dagger.hilt.android.qualifiers.ApplicationContext;",
-            "",
-            "@DefineComponent( parent = ApplicationContext.class )",
-            "interface FooComponent {}");
-
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent test.FooComponent, references a type not annotated with "
-                + "@DefineComponent: dagger.hilt.android.qualifiers.ApplicationContext")
-        .inFile(component);
-  }
-
-  @Test
-  public void testDefineComponentExtendsInterface_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "interface Foo {}",
-            "",
-            "@DefineComponent( parent = SingletonComponent.class )",
-            "interface FooComponent extends Foo {}");
-
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent test.FooComponent, cannot extend a super class or interface."
-                + " Found: test.Foo");
-  }
-
-  @Test
-  public void testDefineComponentNonStaticMethod_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.components.SingletonComponent;",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent( parent = SingletonComponent.class )",
-            "interface FooComponent {",
-            "  int nonStaticMethod();",
-            "}");
-
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent test.FooComponent, cannot have non-static methods. "
-                + "Found: [nonStaticMethod()]");
-  }
-
-  @Test
-  public void testDefineComponentDependencyCycle_fails() {
-    JavaFileObject component1 =
-        JavaFileObjects.forSourceLines(
-            "test.Component1",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent(parent = Component2.class)",
-            "interface Component1 {}");
-
-    JavaFileObject component2 =
-        JavaFileObjects.forSourceLines(
-            "test.Component2",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent(parent = Component1.class)",
-            "interface Component2 {}");
-
-    Compilation compilation = compiler().compile(component1, component2);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent cycle: test.Component1 -> test.Component2 -> test.Component1");
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent cycle: test.Component2 -> test.Component1 -> test.Component2");
-  }
-
-  @Test
-  public void testDefineComponentNoParent_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent",
-            "interface FooComponent {}");
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation)
-        .hadErrorContaining("@DefineComponent test.FooComponent is missing a parent declaration.");
-  }
-
-  @Test
-  public void testDefineComponentBuilderClass_fails() {
-    JavaFileObject builder =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponentBuilder",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent.Builder",
-            "abstract class FooComponentBuilder {}");
-
-    Compilation compilation = compiler().compile(builder);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent.Builder is only allowed on interfaces. "
-                + "Found: test.FooComponentBuilder");
-  }
-
-  @Test
-  public void testDefineComponentBuilderWithTypeParameters_fails() {
-    JavaFileObject builder =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponentBuilder",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent.Builder",
-            "interface FooComponentBuilder<T> {}");
-
-    Compilation compilation = compiler().compile(builder);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent.Builder test.FooComponentBuilder<T>, cannot have type "
-                + "parameters.");
-  }
-
-  @Test
-  public void testDefineComponentBuilderExtendsInterface_fails() {
-    JavaFileObject builder =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponentBuilder",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "interface Foo {}",
-            "",
-            "@DefineComponent.Builder",
-            "interface FooComponentBuilder extends Foo {}");
-
-    Compilation compilation = compiler().compile(builder);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent.Builder test.FooComponentBuilder, cannot extend a super class "
-                + "or interface. Found: test.Foo");
-  }
-
-  @Test
-  public void testDefineComponentBuilderNoBuilderMethod_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent.Builder",
-            "interface FooComponentBuilder {}");
-
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent.Builder test.FooComponentBuilder, must have exactly 1 build "
-                + "method that takes no parameters. Found: []");
-  }
-
-  @Test
-  public void testDefineComponentBuilderPrimitiveReturnType_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "@DefineComponent.Builder",
-            "interface FooComponentBuilder {",
-            "  int nonStaticMethod();",
-            "}");
-
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent.Builder method, test.FooComponentBuilder#nonStaticMethod(), "
-                + "must return a @DefineComponent type. Found: int");
-  }
-
-  @Test
-  public void testDefineComponentBuilderWrongReturnType_fails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.hilt.DefineComponent;",
-            "",
-            "interface Foo {}",
-            "",
-            "@DefineComponent.Builder",
-            "interface FooComponentBuilder {",
-            "  Foo build();",
-            "}");
-
-    Compilation compilation = compiler().compile(component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent.Builder method, test.FooComponentBuilder#build(), must return "
-                + "a @DefineComponent type. Found: test.Foo");
-  }
-
-  private static Compiler compiler() {
-    return javac().withProcessors(new DefineComponentProcessor());
-  }
-}
diff --git a/javatests/dagger/hilt/processor/internal/disableinstallincheck/BUILD b/javatests/dagger/hilt/processor/internal/disableinstallincheck/BUILD
deleted file mode 100644
index 90b0596..0000000
--- a/javatests/dagger/hilt/processor/internal/disableinstallincheck/BUILD
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2020 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.
-#
-# Description:
-#  Builds and run tests related to DisableInstallInCheckProcessor.
-
-load("//java/dagger/testing/compile:macros.bzl", "compiler_test")
-
-package(default_visibility = ["//:src"])
-
-compiler_test(
-    name = "DisableInstallInCheckProcessorErrorsTest",
-    size = "small",
-    srcs = ["DisableInstallInCheckProcessorErrorsTest.java"],
-    compiler_deps = [
-        "//java/dagger/hilt/migration:disable_install_in_check",
-        "//:dagger_with_compiler",
-        "@google_bazel_common//third_party/java/jsr250_annotations",
-        "//java/dagger/hilt:entry_point",
-    ],
-    deps = [
-        "//java/dagger/hilt/processor/internal/disableinstallincheck:processor_lib",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["*"]),
-)
diff --git a/javatests/dagger/hilt/processor/internal/disableinstallincheck/DisableInstallInCheckProcessorErrorsTest.java b/javatests/dagger/hilt/processor/internal/disableinstallincheck/DisableInstallInCheckProcessorErrorsTest.java
deleted file mode 100644
index 8ea715d..0000000
--- a/javatests/dagger/hilt/processor/internal/disableinstallincheck/DisableInstallInCheckProcessorErrorsTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal.disableinstallincheck;
-
-import static com.google.testing.compile.CompilationSubject.assertThat;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import dagger.testing.compile.CompilerTests;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Tests for errors generated by {@link DisableInstallInCheckProcessor} */
-@RunWith(JUnit4.class)
-public class DisableInstallInCheckProcessorErrorsTest {
-
-  @Test
-  public void testIllegalCombinationInstallIn() {
-    JavaFileObject source =
-        JavaFileObjects.forSourceLines(
-            "foo.bar",
-            "package foo.bar;",
-            "",
-            "import dagger.hilt.migration.DisableInstallInCheck;",
-            "import dagger.hilt.EntryPoint;",
-            "",
-            "@DisableInstallInCheck",
-            "final class NotModule {}",
-            "",
-            "@DisableInstallInCheck",
-            "@EntryPoint",
-            "interface FooEntryPoint {}");
-
-    Compilation compilation =
-        CompilerTests.compiler()
-            .withProcessors(new DisableInstallInCheckProcessor())
-            .compile(source);
-
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DisableInstallInCheck should only be used on modules. However, it was found"
-                + " annotating foo.bar.NotModule")
-        .inFile(source)
-        .onLine(7);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DisableInstallInCheck should only be used on modules. However, it was found"
-                + " annotating foo.bar.FooEntryPoint")
-        .inFile(source)
-        .onLine(11);
-  }
-}
diff --git a/javatests/dagger/hilt/processor/internal/generatesrootinput/BUILD b/javatests/dagger/hilt/processor/internal/generatesrootinput/BUILD
deleted file mode 100644
index c5dacd9..0000000
--- a/javatests/dagger/hilt/processor/internal/generatesrootinput/BUILD
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2017 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.
-#
-# Description:
-# Tests the functionality of GeneratesRootInputProcessor.
-
-load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
-load("//:test_defs.bzl", "GenJavaTests")
-
-package(default_visibility = ["//:src"])
-
-GenJavaTests(
-    name = "GeneratesRootInputProcessorTest",
-    srcs = glob(["*.java"]),
-    functional = False,
-    javacopts = DOCLINT_HTML_AND_SYNTAX,
-    deps = [
-        "//:dagger_with_compiler",
-        "//java/dagger/hilt:generates_root_input",
-        "//java/dagger/hilt/processor/internal:base_processor",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:generates_root_inputs",
-        "//java/dagger/hilt/processor/internal/generatesrootinput:processor_lib",
-        "@google_bazel_common//third_party/java/compile_testing",
-        "@google_bazel_common//third_party/java/javapoet",
-        "@google_bazel_common//third_party/java/junit",
-        "@google_bazel_common//third_party/java/truth",
-        "@maven//:com_google_auto_auto_common",
-    ],
-)
-
-filegroup(
-    name = "srcs_filegroup",
-    srcs = glob(["**/*"]),
-)
diff --git a/javatests/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputProcessorTest.java b/javatests/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputProcessorTest.java
deleted file mode 100644
index fb62c3d..0000000
--- a/javatests/dagger/hilt/processor/internal/generatesrootinput/GeneratesRootInputProcessorTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2019 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.hilt.processor.internal.generatesrootinput;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static com.google.testing.compile.Compiler.javac;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.truth.Correspondence;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.TypeSpec;
-import dagger.hilt.processor.internal.BaseProcessor;
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.lang.model.element.Element;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Tests that {@link GeneratesRootInputs} returns the elements to wait for. */
-@RunWith(JUnit4.class)
-public final class GeneratesRootInputProcessorTest {
-  private static final int GENERATED_CLASSES = 5;
-  private static final ClassName TEST_ANNOTATION = ClassName.get("test", "TestAnnotation");
-
-  private final List<Element> elementsToWaitFor = new ArrayList<>();
-  private int generatedClasses = 0;
-
-  @SupportedAnnotationTypes("*")
-  public final class TestAnnotationProcessor extends BaseProcessor {
-    private GeneratesRootInputs generatesRootInputs;
-
-    @Override
-    public synchronized void init(ProcessingEnvironment processingEnv) {
-      super.init(processingEnv);
-      generatesRootInputs = new GeneratesRootInputs(processingEnv);
-    }
-
-    @Override
-    protected void postRoundProcess(RoundEnvironment roundEnv) throws Exception {
-      if (generatedClasses > 0) {
-        elementsToWaitFor.addAll(generatesRootInputs.getElementsToWaitFor(roundEnv));
-      }
-      if (generatedClasses < GENERATED_CLASSES) {
-        TypeSpec typeSpec =
-            TypeSpec.classBuilder("Foo" + generatedClasses++)
-                .addAnnotation(TEST_ANNOTATION)
-                .build();
-        JavaFile.builder("foo", typeSpec).build().writeTo(processingEnv.getFiler());
-      }
-    }
-  }
-
-  @Test
-  public void succeeds_ComponentProcessorWaitsForAnnotationsWithgeneratesstinginput() {
-    JavaFileObject testAnnotation =
-        JavaFileObjects.forSourceLines(
-            "test.TestAnnotation",
-            "package test;",
-            "@dagger.hilt.GeneratesRootInput",
-            "public @interface TestAnnotation {}");
-
-    Compilation compilation =
-        javac()
-            .withProcessors(new TestAnnotationProcessor(), new GeneratesRootInputProcessor())
-            .compile(testAnnotation);
-
-    assertThat(compilation).succeeded();
-    assertThat(elementsToWaitFor)
-        .comparingElementsUsing(
-            Correspondence.<Element, String>transforming(
-                element -> MoreElements.asType(element).getQualifiedName().toString(),
-                "has qualified name of"))
-        .containsExactly("foo.Foo0", "foo.Foo1", "foo.Foo2", "foo.Foo3", "foo.Foo4")
-        .inOrder();
-  }
-}
diff --git a/javatests/dagger/internal/MapProviderFactoryTest.java b/javatests/dagger/internal/MapProviderFactoryTest.java
index c55bee3..5598ff2 100644
--- a/javatests/dagger/internal/MapProviderFactoryTest.java
+++ b/javatests/dagger/internal/MapProviderFactoryTest.java
@@ -46,7 +46,6 @@
     MapProviderFactory.<String, Integer>builder(1).put("Hello", null);
   }
 
-
   @Test
   public void iterationOrder() {
     Provider<Integer> p1 = incrementingIntegerProvider(10);
@@ -75,7 +74,6 @@
         .inOrder();
   }
 
-
   private static Provider<Integer> incrementingIntegerProvider(int seed) {
     return new AtomicInteger(seed)::getAndIncrement;
   }
diff --git a/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsMultibindingsTest.java b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsMultibindingsTest.java
new file mode 100644
index 0000000..bb967b1
--- /dev/null
+++ b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsMultibindingsTest.java
@@ -0,0 +1,2838 @@
+/*
+ * 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.testing.compile.CompilationSubject.assertThat;
+import static dagger.internal.codegen.CompilerMode.AHEAD_OF_TIME_SUBCOMPONENTS_MODE;
+import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
+import static dagger.internal.codegen.Compilers.CLASS_PATH_WITHOUT_GUAVA_OPTION;
+import static dagger.internal.codegen.Compilers.compilerWithOptions;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
+import static dagger.internal.codegen.GeneratedLines.GENERATION_OPTIONS_ANNOTATION;
+import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
+
+import com.google.common.collect.ImmutableList;
+import com.google.testing.compile.Compilation;
+import com.google.testing.compile.JavaFileObjects;
+import javax.tools.JavaFileObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class AheadOfTimeSubcomponentsMultibindingsTest {
+  @Test
+  public void setMultibindings_contributionsInLeaf() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Set<InLeaf> contributionsInLeaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InLeaf provideInLeaf() {",
+            "    return new InLeaf();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Set<InLeaf> contributionsInLeaf() {",
+            "    return ImmutableSet.<InLeaf>of(",
+            "        LeafModule_ProvideInLeafFactory.provideInLeaf());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+  }
+
+  @Test
+  public void setMultibindings_contributionsInAncestorOnly() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InAncestor");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  Set<InAncestor> contributionsInAncestor();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract Set<InAncestor> contributionsInAncestor();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.ElementsIntoSet;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @ElementsIntoSet",
+            "  static Set<InAncestor> provideInAncestors() {",
+            "    return ImmutableSet.of(new InAncestor(), new InAncestor());",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Set<InAncestor> contributionsInAncestor() {",
+            "      return ImmutableSet.<InAncestor>copyOf(",
+            "          AncestorModule_ProvideInAncestorsFactory.provideInAncestors());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void setMultibindings_contributionsInLeafAndAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Set<InEachSubcomponent> contributionsInEachSubcomponent();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InEachSubcomponent provideInLeaf() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InEachSubcomponent provideAnotherInLeaf() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Set<InEachSubcomponent> contributionsInEachSubcomponent() {",
+            "    return ImmutableSet.<InEachSubcomponent>of(",
+            "        LeafModule_ProvideInLeafFactory.provideInLeaf(),",
+            "        LeafModule_ProvideAnotherInLeafFactory.provideAnotherInLeaf());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.ElementsIntoSet;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @ElementsIntoSet",
+            "  static Set<InEachSubcomponent> provideInAncestor() {",
+            "    return ImmutableSet.of(new InEachSubcomponent(), new InEachSubcomponent());",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Set<InEachSubcomponent> contributionsInEachSubcomponent() {",
+            "      return ImmutableSet.<InEachSubcomponent>builderWithExpectedSize(3)",
+            "          .addAll(AncestorModule_ProvideInAncestorFactory.provideInAncestor())",
+            "          .addAll(super.contributionsInEachSubcomponent())",
+            "          .build();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void setMultibindings_contributionsInLeafAndGrandAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InLeafAndGrandAncestor");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InLeafAndGrandAncestor provideInLeaf() {",
+            "    return new InLeafAndGrandAncestor();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InLeafAndGrandAncestor provideAnotherInLeaf() {",
+            "    return new InLeafAndGrandAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
+            "    return ImmutableSet.<InLeafAndGrandAncestor>of(",
+            "        LeafModule_ProvideInLeafFactory.provideInLeaf(),",
+            "        LeafModule_ProvideAnotherInLeafFactory.provideAnotherInLeaf());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.GrandAncestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = GrandAncestorModule.class)",
+            "interface GrandAncestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.GrandAncestorModule",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.ElementsIntoSet;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "class GrandAncestorModule {",
+            "  @Provides",
+            "  @ElementsIntoSet",
+            "  static Set<InLeafAndGrandAncestor> provideInGrandAncestor() {",
+            "    return ImmutableSet.of(new InLeafAndGrandAncestor(),",
+            "        new InLeafAndGrandAncestor());",
+            "  }",
+            "}"));
+    JavaFileObject generatedGrandAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerGrandAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerGrandAncestor implements GrandAncestor {",
+            "  protected DaggerGrandAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Set<InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
+            "      return ImmutableSet.<InLeafAndGrandAncestor>builderWithExpectedSize(3)",
+            "          .addAll(GrandAncestorModule_ProvideInGrandAncestorFactory",
+            "              .provideInGrandAncestor())",
+            "          .addAll(super.contributionsInLeafAndGrandAncestor())",
+            "          .build();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerGrandAncestor")
+        .hasSourceEquivalentTo(generatedGrandAncestor);
+  }
+
+  @Test
+  public void setMultibindings_nonComponentMethodDependency() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(
+        filesToCompile, "InAllSubcomponents", "RequresInAllSubcomponentsSet");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  RequresInAllSubcomponentsSet requiresNonComponentMethod();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InAllSubcomponents provideInAllSubcomponents() {",
+            "    return new InAllSubcomponents();",
+            "  }",
+            "",
+            "  @Provides",
+            "  static RequresInAllSubcomponentsSet providesRequresInAllSubcomponentsSet(",
+            "      Set<InAllSubcomponents> inAllSubcomponents) {",
+            "    return new RequresInAllSubcomponentsSet();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public RequresInAllSubcomponentsSet requiresNonComponentMethod() {",
+            "    return LeafModule_ProvidesRequresInAllSubcomponentsSetFactory",
+            "        .providesRequresInAllSubcomponentsSet(getSetOfInAllSubcomponents());",
+            "  }",
+            "",
+            "  protected Set getSetOfInAllSubcomponents() {",
+            "    return ImmutableSet.<InAllSubcomponents>of(",
+            "        LeafModule_ProvideInAllSubcomponentsFactory",
+            "            .provideInAllSubcomponents());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InAllSubcomponents provideInAllSubcomponents() {",
+            "      return new InAllSubcomponents();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected Set getSetOfInAllSubcomponents() {",
+            "      return ImmutableSet.<InAllSubcomponents>builderWithExpectedSize(2)",
+            "          .add(AncestorModule_ProvideInAllSubcomponentsFactory",
+            "              .provideInAllSubcomponents())",
+            "          .addAll(super.getSetOfInAllSubcomponents())",
+            "          .build();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void setMultibindings_newSubclass() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InAncestor", "RequiresInAncestorSet");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  RequiresInAncestorSet missingWithSetDependency();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract RequiresInAncestorSet missingWithSetDependency();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "",
+            "  @Provides",
+            "  static RequiresInAncestorSet provideRequiresInAncestorSet(",
+            "      Set<InAncestor> inAncestors) {",
+            "    return new RequiresInAncestorSet();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InAncestor provideInAncestor() {",
+            "    return new InAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  private RequiresInAncestorSet getRequiresInAncestorSet() {",
+            "    return AncestorModule_ProvideRequiresInAncestorSetFactory",
+            "        .provideRequiresInAncestorSet(getSetOfInAncestor());",
+            "  }",
+            "",
+            "  protected Set getSetOfInAncestor() {",
+            "    return ImmutableSet.<InAncestor>of(",
+            "        AncestorModule_ProvideInAncestorFactory.provideInAncestor());",
+            "  }",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public final RequiresInAncestorSet missingWithSetDependency() {",
+            "      return DaggerAncestor.this.getRequiresInAncestorSet();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void setMultibinding_requestedAsInstanceInLeaf_requestedAsFrameworkInstanceFromAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(
+        filesToCompile, "Multibound", "MissingInLeaf_WillDependOnFrameworkInstance");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Set<Multibound> instance();",
+            "  MissingInLeaf_WillDependOnFrameworkInstance willDependOnFrameworkInstance();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static Multibound contribution() {",
+            "    return new Multibound();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Set<Multibound> instance() {",
+            "    return ImmutableSet.<Multibound>of(",
+            "        LeafModule_ContributionFactory.contribution());",
+            "  }",
+            "",
+            "  @Override",
+            "  public abstract MissingInLeaf_WillDependOnFrameworkInstance",
+            "      willDependOnFrameworkInstance();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.Multibinds;",
+            "import java.util.Set;",
+            "import javax.inject.Provider;",
+            "",
+            "@Module",
+            "interface AncestorModule {",
+            "  @Provides",
+            "  static MissingInLeaf_WillDependOnFrameworkInstance providedInAncestor(",
+            "      Provider<Set<Multibound>> frameworkInstance) {",
+            "    return null;",
+            "  }",
+            "",
+            "  @Multibinds Set<Multibound> multibinds();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.SetFactory;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    private Provider<Set<Multibound>> setOfMultiboundProvider;",
+            "",
+            "    protected LeafImpl() {}",
+            "",
+            "    protected void configureInitialization() { ",
+            "      initialize();",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() { ",
+            "      this.setOfMultiboundProvider =",
+            "          SetFactory.<Multibound>builder(1, 0)",
+            "              .addProvider(LeafModule_ContributionFactory.create())",
+            "              .build();",
+            "    }",
+            "",
+            "    protected Provider getSetOfMultiboundProvider() {",
+            "      return setOfMultiboundProvider;",
+            "    }",
+            "",
+            "    @Override",
+            "    public final MissingInLeaf_WillDependOnFrameworkInstance ",
+            "        willDependOnFrameworkInstance() {",
+            "      return AncestorModule_ProvidedInAncestorFactory.providedInAncestor(",
+            "          getSetOfMultiboundProvider());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void missingMultibindingInLeaf_onlyContributionsInAncestor_notReModifiedInRoot() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  Set<Object> set();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract Set<Object> set();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static Object onlyContribution() {",
+            "    return new Object();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Set<Object> set() {",
+            "      return ImmutableSet.<Object>of(",
+            "          AncestorModule_OnlyContributionFactory.onlyContribution());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface Root {",
+            "  Ancestor ancestor();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Ancestor ancestor() {",
+            "    return new AncestorImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class AncestorImpl extends DaggerAncestor {",
+            "    private AncestorImpl() {}",
+            "",
+            "    @Override",
+            "    public Leaf leaf() {",
+            "      return new LeafImpl();",
+            "    }",
+            "",
+            "    protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      private LeafImpl() {}",
+            // This tests a regression case where Dagger used to reimplement Leaf.set(), even though
+            // there were no new contributions, because the state change from missing -> 
+            // multibinding wasn't properly recorded
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void setMultibindings_contributionsInLeafAndAncestor_frameworkInstances() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InEachSubcomponent provideInLeaf() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @IntoSet",
+            "  static InEachSubcomponent provideAnotherInLeaf() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.SetFactory;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  private Provider<Set<InEachSubcomponent>> setOfInEachSubcomponentProvider;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization() {",
+            "    initialize();",
+            "  }",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.setOfInEachSubcomponentProvider =",
+            "        SetFactory.<InEachSubcomponent>builder(2, 0)",
+            "            .addProvider(LeafModule_ProvideInLeafFactory.create())",
+            "            .addProvider(LeafModule_ProvideAnotherInLeafFactory.create())",
+            "            .build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent() {",
+            "    return setOfInEachSubcomponentProvider;",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.ElementsIntoSet;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @ElementsIntoSet",
+            "  static Set<InEachSubcomponent> provideInAncestor() {",
+            "    return ImmutableSet.of(new InEachSubcomponent(), new InEachSubcomponent());",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.DelegateFactory;",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.SetFactory;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    private Provider<Set<InEachSubcomponent>> setOfInEachSubcomponentProvider = ",
+            "        new DelegateFactory<>();",
+            "",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected void configureInitialization() {",
+            "      super.configureInitialization();",
+            "      initialize();",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() {",
+            "      DelegateFactory.setDelegate(",
+            "          setOfInEachSubcomponentProvider,",
+            "          SetFactory.<InEachSubcomponent>builder(0, 2)",
+            "              .addCollectionProvider(super.contributionsInEachSubcomponent())",
+            "              .addCollectionProvider(",
+            "                  AncestorModule_ProvideInAncestorFactory.create())",
+            "              .build());",
+            "    }",
+            "",
+            "    @Override",
+            "    public Provider<Set<InEachSubcomponent>> contributionsInEachSubcomponent() {",
+            "      return setOfInEachSubcomponentProvider;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void mapMultibindings_contributionsInLeaf() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Map<String, InLeaf> contributionsInLeaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"leafmodule\")",
+            "  static InLeaf provideInLeaf() {",
+            "    return new InLeaf();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Map<String, InLeaf> contributionsInLeaf() {",
+            "    return ImmutableMap.<String, InLeaf>of(",
+            "        \"leafmodule\",",
+            "        LeafModule_ProvideInLeafFactory.provideInLeaf());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+  }
+
+  @Test
+  public void mapMultibindings_contributionsInAncestorOnly() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InAncestor");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  Map<String, InAncestor> contributionsInAncestor();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract Map<String, InAncestor> contributionsInAncestor();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"ancestormodule\")",
+            "  static InAncestor provideInAncestor() {",
+            "    return new InAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Map<String, InAncestor> contributionsInAncestor() {",
+            "      return ImmutableMap.<String, InAncestor>of(\"ancestormodule\",",
+            "          AncestorModule_ProvideInAncestorFactory.provideInAncestor());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void mapMultibindings_contributionsInLeafAndAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Map<String, InEachSubcomponent> contributionsInEachSubcomponent();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"leafmodule\")",
+            "  static InEachSubcomponent provideInLeaf() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
+            "    return ImmutableMap.<String, InEachSubcomponent>of(",
+            "        \"leafmodule\", LeafModule_ProvideInLeafFactory.provideInLeaf());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"ancestormodule\")",
+            "  static InEachSubcomponent provideInAncestor() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
+            "      return ImmutableMap.<String, InEachSubcomponent>builderWithExpectedSize(2)",
+            "          .put(\"ancestormodule\",",
+            "              AncestorModule_ProvideInAncestorFactory.provideInAncestor())",
+            "          .putAll(super.contributionsInEachSubcomponent())",
+            "          .build();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void mapMultibindings_contributionsInLeafAndAncestor_frameworkInstance() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Provider<Map<String, InEachSubcomponent>> contributionsInEachSubcomponent();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"leafmodule\")",
+            "  static InEachSubcomponent provideInLeaf() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.MapFactory;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  private Provider<Map<String, InEachSubcomponent>> ",
+            "    mapOfStringAndInEachSubcomponentProvider;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization() {",
+            "    initialize();",
+            "  }",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.mapOfStringAndInEachSubcomponentProvider =",
+            "        MapFactory.<String, InEachSubcomponent>builder(1)",
+            "            .put(\"leafmodule\", LeafModule_ProvideInLeafFactory.create())",
+            "            .build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Provider<Map<String, InEachSubcomponent>> ",
+            "      contributionsInEachSubcomponent() {",
+            "    return mapOfStringAndInEachSubcomponentProvider;",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"ancestormodule\")",
+            "  static InEachSubcomponent provideInAncestor() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.DelegateFactory;",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.MapFactory;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    private Provider<Map<String, InEachSubcomponent>> ",
+            "      mapOfStringAndInEachSubcomponentProvider = new DelegateFactory<>();",
+            "",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected void configureInitialization() { ",
+            "      super.configureInitialization();",
+            "      initialize();",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() { ",
+            "      DelegateFactory.setDelegate(",
+            "          mapOfStringAndInEachSubcomponentProvider,",
+            "          MapFactory.<String, InEachSubcomponent>builder(2)",
+            "              .putAll(super.contributionsInEachSubcomponent())",
+            "              .put(",
+            "                  \"ancestormodule\",",
+            "                  AncestorModule_ProvideInAncestorFactory.create())",
+            "              .build());",
+            "    }",
+            "",
+            "    @Override",
+            "    public Provider<Map<String, InEachSubcomponent>> ",
+            "        contributionsInEachSubcomponent() {",
+            "      return mapOfStringAndInEachSubcomponentProvider;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void mapMultibindings_contributionsInLeafAndGrandAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InLeafAndGrandAncestor");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Map<String, InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"leafmodule\")",
+            "  static InLeafAndGrandAncestor provideInLeaf() {",
+            "    return new InLeafAndGrandAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Map<String, InLeafAndGrandAncestor> contributionsInLeafAndGrandAncestor() {",
+            "    return ImmutableMap.<String, InLeafAndGrandAncestor>of(",
+            "        \"leafmodule\", LeafModule_ProvideInLeafFactory.provideInLeaf());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.GrandAncestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = GrandAncestorModule.class)",
+            "interface GrandAncestor {",
+            "  Ancestor ancestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.GrandAncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class GrandAncestorModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"grandancestormodule\")",
+            "  static InLeafAndGrandAncestor provideInGrandAncestor() {",
+            "    return new InLeafAndGrandAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedGrandAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerGrandAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerGrandAncestor implements GrandAncestor {",
+            "  protected DaggerGrandAncestor() {}",
+            "",
+            "  protected abstract class AncestorImpl extends DaggerAncestor {",
+            "    protected AncestorImpl() {}",
+            "",
+            "    protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      protected LeafImpl() {}",
+            "",
+            "      @Override",
+            "      public Map<String, InLeafAndGrandAncestor>",
+            "          contributionsInLeafAndGrandAncestor() {",
+            "        return",
+            "            ImmutableMap.<String, InLeafAndGrandAncestor>builderWithExpectedSize(2)",
+            "                .put(\"grandancestormodule\",",
+            "                    GrandAncestorModule_ProvideInGrandAncestorFactory",
+            "                        .provideInGrandAncestor())",
+            "                .putAll(super.contributionsInLeafAndGrandAncestor())",
+            "                .build();",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerGrandAncestor")
+        .hasSourceEquivalentTo(generatedGrandAncestor);
+  }
+
+  @Test
+  public void mapMultibindings_contributionsInLeafAndAncestorWithoutGuava() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InEachSubcomponent");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Map<String, InEachSubcomponent> contributionsInEachSubcomponent();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"leafmodule\")",
+            "  static InEachSubcomponent provideInLeaf() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Collections;",
+            "import java.util.Map",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
+            "    return Collections.<String, InEachSubcomponent>singletonMap(",
+            "        \"leafmodule\", LeafModule_ProvideInLeafFactory.provideInLeaf());",
+            "  }",
+            "}");
+    Compilation compilation = compileWithoutGuava(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.StringKey;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @StringKey(\"ancestormodule\")",
+            "  static InEachSubcomponent provideInAncestor() {",
+            "    return new InEachSubcomponent();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.MapBuilder;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Map<String, InEachSubcomponent> contributionsInEachSubcomponent() {",
+            "      return MapBuilder.<String, InEachSubcomponent>newMapBuilder(2)",
+            "          .put(\"ancestormodule\",",
+            "              AncestorModule_ProvideInAncestorFactory.provideInAncestor())",
+            "          .putAll(super.contributionsInEachSubcomponent())",
+            "          .build();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compileWithoutGuava(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void mapMultibinding_requestedAsInstanceInLeaf_requestedAsFrameworkInstanceFromAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(
+        filesToCompile, "Multibound", "MissingInLeaf_WillDependOnFrameworkInstance");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Map<Integer, Multibound> instance();",
+            "  MissingInLeaf_WillDependOnFrameworkInstance willDependOnFrameworkInstance();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntKey;",
+            "import dagger.multibindings.IntoMap;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @IntKey(111)",
+            "  static Multibound contribution() {",
+            "    return new Multibound();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Map<Integer, Multibound> instance() {",
+            "    return ImmutableMap.<Integer, Multibound>of(",
+            "        111, LeafModule_ContributionFactory.contribution());",
+            "  }",
+            "",
+            "  @Override",
+            "  public abstract MissingInLeaf_WillDependOnFrameworkInstance",
+            "      willDependOnFrameworkInstance();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.Multibinds;",
+            "import java.util.Map;",
+            "import javax.inject.Provider;",
+            "",
+            "@Module",
+            "interface AncestorModule {",
+            "  @Provides",
+            "  static MissingInLeaf_WillDependOnFrameworkInstance providedInAncestor(",
+            "      Provider<Map<Integer, Multibound>> frameworkInstance) {",
+            "    return null;",
+            "  }",
+            "",
+            "  @Multibinds Map<Integer, Multibound> multibinds();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.MapFactory;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    private Provider<Map<Integer, Multibound>> mapOfIntegerAndMultiboundProvider;",
+            "",
+            "    protected LeafImpl() {}",
+            "",
+            "    protected void configureInitialization() { ",
+            "      initialize();",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() { ",
+            "      this.mapOfIntegerAndMultiboundProvider =",
+            "          MapFactory.<Integer, Multibound>builder(1)",
+            "              .put(111, LeafModule_ContributionFactory.create())",
+            "              .build();",
+            "    }",
+            "",
+            "    protected Provider getMapOfIntegerAndMultiboundProvider() {",
+            "      return mapOfIntegerAndMultiboundProvider;",
+            "    }",
+            "",
+            "    @Override",
+            "    public final MissingInLeaf_WillDependOnFrameworkInstance ",
+            "        willDependOnFrameworkInstance() {",
+            "      return AncestorModule_ProvidedInAncestorFactory.providedInAncestor(",
+            "          getMapOfIntegerAndMultiboundProvider());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void emptyMultibinds_set() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Multibound");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.multibindings.Multibinds;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Multibinds",
+            "  Set<Multibound> set();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Set<Multibound> set();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Set<Multibound> set() {",
+            "    return ImmutableSet.<Multibound>of();",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static Multibound fromAncestor() {",
+            "    return new Multibound();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Set<Multibound> set() {",
+            "      return ImmutableSet.<Multibound>of(",
+            "          AncestorModule_FromAncestorFactory.fromAncestor());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void emptyMultibinds_set_frameworkInstance() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Multibound");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.multibindings.Multibinds;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Multibinds",
+            "  Set<Multibound> set();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Provider<Set<Multibound>> set();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.SetFactory;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Provider<Set<Multibound>> set() {",
+            "    return SetFactory.<Multibound>empty();",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static Multibound fromAncestor() {",
+            "    return new Multibound();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.DelegateFactory;",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.SetFactory;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    private Provider<Set<Multibound>> setOfMultiboundProvider =",
+            "        new DelegateFactory<>();",
+            "",
+            "    protected LeafImpl() {}",
+            "",
+            "    protected void configureInitialization() {",
+            "      initialize();",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() {",
+            "      DelegateFactory.setDelegate(",
+            "          setOfMultiboundProvider,",
+            "          SetFactory.<Multibound>builder(1, 0)",
+            "              .addProvider(AncestorModule_FromAncestorFactory.create())",
+            "              .build());",
+            "    }",
+            "",
+            "    @Override",
+            "    public Provider<Set<Multibound>> set() {",
+            "      return setOfMultiboundProvider;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void emptyMultibinds_map() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Multibound");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.multibindings.Multibinds;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Multibinds",
+            "  Map<Integer, Multibound> map();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Map<Integer, Multibound> map();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Map<Integer, Multibound> map() {",
+            "    return ImmutableMap.<Integer, Multibound>of();",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntKey;",
+            "import dagger.multibindings.IntoMap;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @IntKey(111)",
+            "  static Multibound fromAncestor() {",
+            "    return new Multibound();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableMap;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Map<Integer, Multibound> map() {",
+            "      return ImmutableMap.<Integer, Multibound>of(",
+            "          111, AncestorModule_FromAncestorFactory.fromAncestor());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void emptyMultibinds_map_frameworkInstance() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Multibound");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.multibindings.Multibinds;",
+            "import java.util.Map;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Multibinds",
+            "  Map<Integer, Multibound> map();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Provider<Map<Integer, Multibound>> map();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.MapFactory;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Provider<Map<Integer, Multibound>> map() {",
+            "    return MapFactory.<Integer, Multibound>emptyMapProvider();",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntKey;",
+            "import dagger.multibindings.IntoMap;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  @IntoMap",
+            "  @IntKey(111)",
+            "  static Multibound fromAncestor() {",
+            "    return new Multibound();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.DelegateFactory;",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.MapFactory;",
+            "import java.util.Map;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    private Provider<Map<Integer, Multibound>> mapOfIntegerAndMultiboundProvider =",
+            "        new DelegateFactory<>()",
+            "",
+            "    protected LeafImpl() {}",
+            "",
+            "    protected void configureInitialization() {",
+            "      initialize();",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() {",
+            "      DelegateFactory.setDelegate(",
+            "          mapOfIntegerAndMultiboundProvider,",
+            "          MapFactory.<Integer, Multibound>builder(1)",
+            "              .put(111, AncestorModule_FromAncestorFactory.create())",
+            "              .build());",
+            "    }",
+            "",
+            "    @Override",
+            "    public Provider<Map<Integer, Multibound>> map() {",
+            "      return mapOfIntegerAndMultiboundProvider;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void bindsMissingDep_Multibindings() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Binds;",
+            "import dagger.Module;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Binds",
+            "  @IntoSet",
+            "  CharSequence bindsMultibindingWithMissingDep(String string);",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Set;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Set<CharSequence> set();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Set<CharSequence> set() {",
+            "    return ImmutableSet.<CharSequence>of(getBindsMultibindingWithMissingDep());",
+            "  }",
+            "",
+            // The expected output here is subtle: the Key of
+            // LeafModule.bindsMultibindingWithMissingDep() is Set<CharSequence>, but the binding
+            // method should only be returning an individual CharSequence. Otherwise the
+            // ImmutableSet factory method above will fail.
+            "  protected abstract CharSequence getBindsMultibindingWithMissingDep();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+  }
+
+  @Test
+  public void multibindingsAndFastInit() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "PackagePrivate");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.MultibindingModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntKey;",
+            "import dagger.multibindings.IntoMap;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "interface MultibindingModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  @LeafScope",
+            "  static PackagePrivate setContribution() {",
+            "    return new PackagePrivate();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @IntoMap",
+            "  @IntKey(1)",
+            "  @LeafScope",
+            "  static PackagePrivate mapContribution() {",
+            "    return new PackagePrivate();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafScope",
+            "package test;",
+            "",
+            "import javax.inject.Scope;",
+            "",
+            "@Scope",
+            "@interface LeafScope {}"),
+        JavaFileObjects.forSourceLines(
+            "test.UsesMultibindings",
+            "package test;",
+            "",
+            "import java.util.Map;",
+            "import java.util.Set;",
+            "import javax.inject.Inject;",
+            "",
+            "class UsesMultibindings {",
+            "  @Inject",
+            "  UsesMultibindings(Set<PackagePrivate> set, Map<Integer, PackagePrivate> map) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Map;",
+            "import java.util.Set;",
+            "",
+            "@LeafScope",
+            "@Subcomponent(modules = MultibindingModule.class)",
+            "interface Leaf {",
+            "  UsesMultibindings entryPoint();",
+            "}"));
+
+    Compilation compilation =
+        compilerWithOptions(AHEAD_OF_TIME_SUBCOMPONENTS_MODE, FAST_INIT_MODE)
+            .compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "@GenerationOptions(fastInit = true)",
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  private PackagePrivate getSetContribution() {",
+            "    Object local = setContribution;",
+            "    if (local instanceof MemoizedSentinel) {",
+            "      synchronized (local) {",
+            "        local = setContribution;",
+            "        if (local instanceof MemoizedSentinel) {",
+            "          local = MultibindingModule_SetContributionFactory.setContribution();",
+            "          setContribution = DoubleCheck.reentrantCheck(setContribution, local);",
+            "        }",
+            "      }",
+            "    }",
+            "    return (PackagePrivate) local;",
+            "  }",
+            "",
+            "  private PackagePrivate getMapContribution() {",
+            "    Object local = mapContribution;",
+            "    if (local instanceof MemoizedSentinel) {",
+            "      synchronized (local) {",
+            "        local = mapContribution;",
+            "        if (local instanceof MemoizedSentinel) {",
+            "          local = MultibindingModule_MapContributionFactory.mapContribution();",
+            "          mapContribution = DoubleCheck.reentrantCheck(mapContribution, local);",
+            "        }",
+            "      }",
+            "    }",
+            "    return (PackagePrivate) local;",
+            "  }",
+            "",
+            "  @Override",
+            "  public UsesMultibindings entryPoint() {",
+            "    return new UsesMultibindings(",
+            "        getSetOfPackagePrivate(), getMapOfIntegerAndPackagePrivate());",
+            "  }",
+            "",
+            "  protected Set getSetOfPackagePrivate() {",
+            "    return ImmutableSet.<PackagePrivate>of(getSetContribution());",
+            "  }",
+            "",
+            "  protected Map getMapOfIntegerAndPackagePrivate() {",
+            "    return ImmutableMap.<Integer, PackagePrivate>of(1, getMapContribution());",
+            "  }",
+            "}");
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .containsElementsIn(generatedLeaf);
+  }
+
+  // TODO(ronshapiro): remove copies from AheadOfTimeSubcomponents*Test classes
+  private void createSimplePackagePrivateClasses(
+      ImmutableList.Builder<JavaFileObject> filesBuilder, String... ancillaryClasses) {
+    for (String className : ancillaryClasses) {
+      filesBuilder.add(
+          JavaFileObjects.forSourceLines(
+              String.format("test.%s", className),
+              "package test;",
+              "",
+              String.format("class %s { }", className)));
+    }
+  }
+
+  private static Compilation compile(Iterable<JavaFileObject> files) {
+    return compilerWithOptions(AHEAD_OF_TIME_SUBCOMPONENTS_MODE).compile(files);
+  }
+
+  private static Compilation compileWithoutGuava(Iterable<JavaFileObject> files) {
+    return daggerCompiler()
+        .withOptions(
+            AHEAD_OF_TIME_SUBCOMPONENTS_MODE.javacopts().append(CLASS_PATH_WITHOUT_GUAVA_OPTION))
+        .compile(files);
+  }
+}
diff --git a/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java
new file mode 100644
index 0000000..1bd221a
--- /dev/null
+++ b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java
@@ -0,0 +1,5677 @@
+/*
+ * 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.testing.compile.CompilationSubject.assertThat;
+import static dagger.internal.codegen.CompilerMode.AHEAD_OF_TIME_SUBCOMPONENTS_MODE;
+import static dagger.internal.codegen.Compilers.compilerWithOptions;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
+import static dagger.internal.codegen.GeneratedLines.GENERATION_OPTIONS_ANNOTATION;
+import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ObjectArrays;
+import com.google.testing.compile.Compilation;
+import com.google.testing.compile.JavaFileObjects;
+import javax.tools.JavaFileObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class AheadOfTimeSubcomponentsTest {
+  private static final String PRUNED_METHOD_BODY =
+      "throw new UnsupportedOperationException(\"This binding is not part of the final binding "
+          + "graph. The key was requested by a binding that was believed to possibly be part of "
+          + "the graph, but is no longer requested. If this exception is thrown, it is the result "
+          + "of a Dagger bug.\");";
+
+  @Test
+  public void missingBindings_fromComponentMethod() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "MissingInLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  MissingInLeaf missingFromComponentMethod();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract MissingInLeaf missingFromComponentMethod();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  static MissingInLeaf satisfiedInAncestor() { return new MissingInLeaf(); }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public final MissingInLeaf missingFromComponentMethod() {",
+            "      return AncestorModule_SatisfiedInAncestorFactory.satisfiedInAncestor();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void missingBindings_dependsOnBindingWithMatchingComponentMethod() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "MissingInLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  MissingInLeaf missingComponentMethod();",
+            "  DependsOnComponentMethod dependsOnComponentMethod();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.DependsOnComponentMethod",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class DependsOnComponentMethod {",
+            "  @Inject DependsOnComponentMethod(MissingInLeaf missingInLeaf) {}",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract MissingInLeaf missingComponentMethod();",
+            "",
+            "  @Override",
+            "  public DependsOnComponentMethod dependsOnComponentMethod() {",
+            "    return new DependsOnComponentMethod(missingComponentMethod());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+  }
+
+  @Test
+  public void missingBindings_dependsOnMissingBinding() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "MissingInLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  DependsOnMissingBinding dependsOnMissingBinding();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.DependsOnMissingBinding",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class DependsOnMissingBinding {",
+            "  @Inject DependsOnMissingBinding(MissingInLeaf missing) {}",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public DependsOnMissingBinding dependsOnMissingBinding() {",
+            "    return new DependsOnMissingBinding((MissingInLeaf) getMissingInLeaf());",
+            "  }",
+            "",
+            "  protected abstract Object getMissingInLeaf();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  static MissingInLeaf satisfiedInAncestor() { return new MissingInLeaf(); }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected final Object getMissingInLeaf() {",
+            "      return AncestorModule_SatisfiedInAncestorFactory.satisfiedInAncestor();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void missingBindings_satisfiedInGreatAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "MissingInLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  DependsOnMissingBinding dependsOnMissingBinding();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.DependsOnMissingBinding",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class DependsOnMissingBinding {",
+            "  @Inject DependsOnMissingBinding(MissingInLeaf missing) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.GreatAncestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = SatisfiesMissingBindingModule.class)",
+            "interface GreatAncestor {",
+            "  Ancestor ancestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.SatisfiesMissingBindingModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class SatisfiesMissingBindingModule {",
+            "  @Provides",
+            "  static MissingInLeaf satisfy() { return new MissingInLeaf(); }",
+            "}"));
+    // DaggerLeaf+DaggerAncestor generated types are ignored - they're not the focus of this test
+    // and are tested elsewhere
+    JavaFileObject generatedGreatAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerGreatAncestor implements GreatAncestor {",
+            "  protected DaggerGreatAncestor() {}",
+            "",
+            "  protected abstract class AncestorImpl extends DaggerAncestor {",
+            "    protected AncestorImpl() {}",
+            "",
+            "    protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      protected LeafImpl() {}",
+            "",
+            "      @Override",
+            "      protected final Object getMissingInLeaf() {",
+            "        return SatisfiesMissingBindingModule_SatisfyFactory.satisfy();",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerGreatAncestor")
+        .hasSourceEquivalentTo(generatedGreatAncestor);
+  }
+
+  @Test
+  public void moduleInstanceDependency() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = TestModule.class)",
+            "interface Leaf {",
+            "  String string();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class TestModule {",
+            "  @Provides String provideString() { return \"florp\"; }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public String string() {",
+            "    return TestModule_ProvideStringFactory.provideString(testModule());",
+            "  }",
+            "",
+            "  protected abstract TestModule testModule();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface Root {",
+            "  Ancestor ancestor();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Ancestor ancestor() {",
+            "    return new AncestorImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class AncestorImpl extends DaggerAncestor {",
+            "    private AncestorImpl() {}",
+            "",
+            "    @Override",
+            "    public Leaf leaf() {",
+            "      return new LeafImpl();",
+            "    }",
+            "",
+            "    protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      private final TestModule testModule;",
+            "",
+            "      private LeafImpl() {",
+            "        this.testModule = new TestModule();",
+            "      }",
+            "",
+            "      @Override",
+            "      protected TestModule testModule() {",
+            "        return testModule;",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void moduleInstanceDependency_withModuleParams() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = TestModule.class)",
+            "interface Leaf {",
+            "  int getInt();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "final class TestModule {",
+            "  private int i;",
+            "",
+            "  TestModule(int i) {}",
+            "",
+            "  @Provides int provideInt() {",
+            "    return i++;",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public int getInt() {",
+            "    return testModule().provideInt();",
+            "  }",
+            "",
+            "  protected abstract TestModule testModule();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  Leaf leaf(TestModule module);",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface Root {",
+            "  Ancestor ancestor();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Ancestor ancestor() {",
+            "    return new AncestorImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class AncestorImpl extends DaggerAncestor {",
+            "    private AncestorImpl() {}",
+            "",
+            "    @Override",
+            "    public Leaf leaf(TestModule module) {",
+            "      Preconditions.checkNotNull(module);",
+            "      return new LeafImpl(module);",
+            "    }",
+            "",
+            "    protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      private final TestModule testModule;",
+            "",
+            "      private LeafImpl(TestModule module) {",
+            "        this.testModule = module;",
+            "      }",
+            "",
+            "      @Override",
+            "      protected TestModule testModule() {",
+            "        return testModule;",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void generatedInstanceBinding() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  @Subcomponent.Builder",
+            "  interface Builder {",
+            "    Leaf build();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  Leaf.Builder leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  @Override",
+            "  public abstract Leaf.Builder leaf();",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface Root {",
+            "  Ancestor ancestor();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Ancestor ancestor() {",
+            "    return new AncestorImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class AncestorImpl extends DaggerAncestor {",
+            "    private AncestorImpl() {}",
+            "",
+            "    @Override",
+            "    public Leaf.Builder leaf() {",
+            "      return new LeafBuilder();",
+            "    }",
+            "",
+            "    private final class LeafBuilder implements Leaf.Builder {",
+            "      @Override",
+            "      public Leaf build() {",
+            "        return new LeafImpl();",
+            "      }",
+            "    }",
+            "",
+            "    protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      private LeafImpl() {}",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void prunedGeneratedInstanceBinding() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.PrunedSubcomponent",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface PrunedSubcomponent {",
+            "  @Subcomponent.Builder",
+            "  interface Builder {",
+            "    PrunedSubcomponent build();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.InstallsPrunedSubcomponentModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "",
+            "@Module(subcomponents = PrunedSubcomponent.class)",
+            "interface InstallsPrunedSubcomponentModule {}"),
+        JavaFileObjects.forSourceLines(
+            "test.DependsOnPrunedSubcomponentBuilder",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class DependsOnPrunedSubcomponentBuilder {",
+            "  @Inject DependsOnPrunedSubcomponentBuilder(PrunedSubcomponent.Builder builder) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.MaybeLeaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = InstallsPrunedSubcomponentModule.class)",
+            "interface MaybeLeaf {",
+            "  DependsOnPrunedSubcomponentBuilder dependsOnPrunedSubcomponentBuilder();",
+            "}"));
+    JavaFileObject generatedMaybeLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerMaybeLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerMaybeLeaf implements MaybeLeaf {",
+            "  protected DaggerMaybeLeaf() {}",
+            "",
+            "  @Override",
+            "  public DependsOnPrunedSubcomponentBuilder dependsOnPrunedSubcomponentBuilder() {",
+            "    return new DependsOnPrunedSubcomponentBuilder(",
+            "        (PrunedSubcomponent.Builder) getPrunedSubcomponentBuilder());",
+            "  }",
+            "",
+            "  protected abstract Object getPrunedSubcomponentBuilder();",
+            "",
+            "  protected abstract class PrunedSubcomponentImpl extends DaggerPrunedSubcomponent {",
+            "    protected PrunedSubcomponentImpl() {}",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerMaybeLeaf")
+        .hasSourceEquivalentTo(generatedMaybeLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.PrunesGeneratedInstanceModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "interface PrunesGeneratedInstanceModule {",
+            "  @Provides",
+            "  static DependsOnPrunedSubcomponentBuilder pruneGeneratedInstance() {",
+            "    return new DependsOnPrunedSubcomponentBuilder(null);",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = PrunesGeneratedInstanceModule.class)",
+            "interface Root {",
+            "  MaybeLeaf actuallyLeaf();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public MaybeLeaf actuallyLeaf() {",
+            "    return new MaybeLeafImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class MaybeLeafImpl extends DaggerMaybeLeaf {",
+            "    private MaybeLeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected Object getPrunedSubcomponentBuilder() {",
+            "      " + PRUNED_METHOD_BODY,
+            "    }",
+            "",
+            "    @Override",
+            "    public DependsOnPrunedSubcomponentBuilder dependsOnPrunedSubcomponentBuilder() {",
+            "      return PrunesGeneratedInstanceModule_PruneGeneratedInstanceFactory",
+            "          .pruneGeneratedInstance();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void optionalBindings_boundAndSatisfiedInSameSubcomponent() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "SatisfiedInSub");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Sub",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Optional;",
+            "",
+            "@Subcomponent(modules = {SubModule.class, BindsSatisfiedInSubModule.class})",
+            "interface Sub {",
+            "  Optional<SatisfiedInSub> satisfiedInSub();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.SubModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Module;",
+            "",
+            "@Module",
+            "abstract class SubModule {",
+            "  @BindsOptionalOf abstract SatisfiedInSub optionalSatisfiedInSub();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.BindsSatisfiedInSubModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "abstract class BindsSatisfiedInSubModule {",
+            "  @Provides static SatisfiedInSub provideSatisfiedInSub() {",
+            "      return new SatisfiedInSub();",
+            "  }",
+            "}"));
+    JavaFileObject generatedSubcomponent =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerSub",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerSub implements Sub {",
+            "  protected DaggerSub() {}",
+            "",
+            "  @Override",
+            "  public Optional<SatisfiedInSub> satisfiedInSub() {",
+            "    return Optional.of(",
+            "        BindsSatisfiedInSubModule_ProvideSatisfiedInSubFactory",
+            "            .provideSatisfiedInSub());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerSub")
+        .hasSourceEquivalentTo(generatedSubcomponent);
+  }
+
+  @Test
+  public void optionalBindings_satisfiedInAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "SatisfiedInAncestor");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Optional;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Optional<SatisfiedInAncestor> satisfiedInAncestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Module;",
+            "",
+            "@Module",
+            "abstract class LeafModule {",
+            "  @BindsOptionalOf abstract SatisfiedInAncestor optionalSatisfiedInAncestor();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Optional<SatisfiedInAncestor> satisfiedInAncestor() {",
+            "    return Optional.<SatisfiedInAncestor>empty();",
+            "  }",
+            "}");
+    Compilation compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "abstract class AncestorModule {",
+            "  @Provides",
+            "  static SatisfiedInAncestor satisfiedInAncestor(){",
+            "    return new SatisfiedInAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public final Optional<SatisfiedInAncestor> satisfiedInAncestor() {",
+            "      return Optional.of(AncestorModule_SatisfiedInAncestorFactory",
+            "          .satisfiedInAncestor());",
+            "    }",
+            "",
+            "  }",
+            "}");
+    compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void optionalBindings_satisfiedInGrandAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "SatisfiedInGrandAncestor");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Optional;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Optional<SatisfiedInGrandAncestor> satisfiedInGrandAncestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Module;",
+            "",
+            "@Module",
+            "abstract class LeafModule {",
+            "  @BindsOptionalOf",
+            "  abstract SatisfiedInGrandAncestor optionalSatisfiedInGrandAncestor();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Optional<SatisfiedInGrandAncestor> satisfiedInGrandAncestor() {",
+            "    return Optional.<SatisfiedInGrandAncestor>empty();",
+            "  }",
+            "}");
+    Compilation compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "  }",
+            "}");
+    compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.GreatAncestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = GreatAncestorModule.class)",
+            "interface GreatAncestor {",
+            "  Ancestor ancestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.GreatAncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "abstract class GreatAncestorModule {",
+            "  @Provides",
+            "  static SatisfiedInGrandAncestor satisfiedInGrandAncestor(){",
+            "    return new SatisfiedInGrandAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedGreatAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerGreatAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerGreatAncestor implements GreatAncestor {",
+            "  protected DaggerGreatAncestor() {}",
+            "",
+            "  protected abstract class AncestorImpl extends DaggerAncestor {",
+            "    protected AncestorImpl() {}",
+            "",
+            "    protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      protected LeafImpl() {}",
+            "",
+            "      @Override",
+            "      public final Optional<SatisfiedInGrandAncestor> satisfiedInGrandAncestor() {",
+            "        return Optional.of(",
+            "            GreatAncestorModule_SatisfiedInGrandAncestorFactory",
+            "                .satisfiedInGrandAncestor());",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerGreatAncestor")
+        .hasSourceEquivalentTo(generatedGreatAncestor);
+  }
+
+  @Test
+  public void optionalBindings_nonComponentMethodDependencySatisfiedInAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(
+        filesToCompile, "SatisfiedInAncestor", "RequiresOptionalSatisfiedInAncestor");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Optional;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  RequiresOptionalSatisfiedInAncestor requiresOptionalSatisfiedInAncestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import java.util.Optional;",
+            "",
+            "@Module",
+            "abstract class LeafModule {",
+            "  @Provides static RequiresOptionalSatisfiedInAncestor",
+            "      provideRequiresOptionalSatisfiedInAncestor(",
+            "          Optional<SatisfiedInAncestor> satisfiedInAncestor) {",
+            "    return new RequiresOptionalSatisfiedInAncestor();",
+            "  }",
+            "",
+            "  @BindsOptionalOf abstract SatisfiedInAncestor optionalSatisfiedInAncestor();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public RequiresOptionalSatisfiedInAncestor",
+            "      requiresOptionalSatisfiedInAncestor() {",
+            "    return LeafModule_ProvideRequiresOptionalSatisfiedInAncestorFactory",
+            "        .provideRequiresOptionalSatisfiedInAncestor(",
+            "            getOptionalOfSatisfiedInAncestor());",
+            "  }",
+            "",
+            "  protected Optional getOptionalOfSatisfiedInAncestor() {",
+            "    return Optional.<SatisfiedInAncestor>empty();",
+            "  }",
+            "}");
+    Compilation compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "abstract class AncestorModule {",
+            "  @Provides",
+            "  static SatisfiedInAncestor satisfiedInAncestor(){",
+            "    return new SatisfiedInAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected final Optional getOptionalOfSatisfiedInAncestor() {",
+            "      return Optional.of(",
+            "          AncestorModule_SatisfiedInAncestorFactory.satisfiedInAncestor());",
+            "    }",
+            "  }",
+            "}");
+    compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void optionalBindings_boundInAncestorAndSatisfiedInGrandAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "SatisfiedInGrandAncestor");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import java.util.Optional;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  Optional<SatisfiedInGrandAncestor> boundInAncestorSatisfiedInGrandAncestor();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract Optional<SatisfiedInGrandAncestor>",
+            "      boundInAncestorSatisfiedInGrandAncestor();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Module;",
+            "",
+            "@Module",
+            "abstract class AncestorModule {",
+            "  @BindsOptionalOf",
+            "  abstract SatisfiedInGrandAncestor optionalSatisfiedInGrandAncestor();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Optional<SatisfiedInGrandAncestor>",
+            "        boundInAncestorSatisfiedInGrandAncestor() {",
+            "      return Optional.<SatisfiedInGrandAncestor>empty();",
+            "    }",
+            "  }",
+            "}");
+    compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.GrandAncestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = GrandAncestorModule.class)",
+            "interface GrandAncestor {",
+            "  Ancestor ancestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.GrandAncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class GrandAncestorModule {",
+            "  @Provides static SatisfiedInGrandAncestor provideSatisfiedInGrandAncestor() {",
+            "    return new SatisfiedInGrandAncestor();",
+            "  }",
+            "}"));
+    JavaFileObject generatedGrandAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerGrandAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Optional;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerGrandAncestor implements GrandAncestor {",
+            "  protected DaggerGrandAncestor() {}",
+            "",
+            "  protected abstract class AncestorImpl extends DaggerAncestor {",
+            "    protected AncestorImpl() {}",
+            "",
+            "    protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      protected LeafImpl() {}",
+            "",
+            "      @Override",
+            "      public final Optional<SatisfiedInGrandAncestor>",
+            "          boundInAncestorSatisfiedInGrandAncestor() {",
+            "        return Optional.of(",
+            "            GrandAncestorModule_ProvideSatisfiedInGrandAncestorFactory",
+            "                .provideSatisfiedInGrandAncestor());",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    compilation =
+        compile(
+            filesToCompile.build()
+            , CompilerMode.JAVA7
+            );
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerGrandAncestor")
+        .hasSourceEquivalentTo(generatedGrandAncestor);
+  }
+
+  @Test
+  public void provisionOverInjection_providedInAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.ProvidedInAncestor",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class ProvidedInAncestor {",
+            "  @Inject",
+            "  ProvidedInAncestor(String string) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  ProvidedInAncestor injectedInLeaf();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public ProvidedInAncestor injectedInLeaf() {",
+            "    return new ProvidedInAncestor(getString());",
+            "  }",
+            "",
+            "  protected abstract String getString();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  static ProvidedInAncestor provideProvidedInAncestor() {",
+            "    return new ProvidedInAncestor(\"static\");",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public final ProvidedInAncestor injectedInLeaf() {",
+            "      return AncestorModule_ProvideProvidedInAncestorFactory",
+            "          .provideProvidedInAncestor();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void provisionOverInjection_providedInGrandAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.ProvidedInGrandAncestor",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class ProvidedInGrandAncestor {",
+            "  @Inject",
+            "  ProvidedInGrandAncestor(String string) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  ProvidedInGrandAncestor injectedInLeaf();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public ProvidedInGrandAncestor injectedInLeaf() {",
+            "    return new ProvidedInGrandAncestor(getString());",
+            "  }",
+            "",
+            "  protected abstract String getString();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.GrandAncestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = GrandAncestorModule.class)",
+            "interface GrandAncestor {",
+            "  Ancestor ancestor();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.GrandAncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class GrandAncestorModule {",
+            "  @Provides",
+            "  static ProvidedInGrandAncestor provideProvidedInGrandAncestor() {",
+            "    return new ProvidedInGrandAncestor(\"static\");",
+            "  }",
+            "}"));
+    JavaFileObject generatedGrandAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerGrandAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerGrandAncestor implements GrandAncestor {",
+            "  protected DaggerGrandAncestor() {}",
+            "",
+            "  protected abstract class AncestorImpl extends DaggerAncestor {",
+            "    protected AncestorImpl() {}",
+            "",
+            "    protected abstract class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      protected LeafImpl() {}",
+            "",
+            "      @Override",
+            "      public final ProvidedInGrandAncestor injectedInLeaf() {",
+            "        return GrandAncestorModule_ProvideProvidedInGrandAncestorFactory",
+            "            .provideProvidedInGrandAncestor();",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerGrandAncestor")
+        .hasSourceEquivalentTo(generatedGrandAncestor);
+  }
+
+  @Test
+  public void provisionOverInjection_indirectDependency() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.ProvidedInAncestor",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class ProvidedInAncestor {",
+            "  @Inject",
+            "  ProvidedInAncestor(String string) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.InjectedInLeaf",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class InjectedInLeaf {",
+            "  @Inject",
+            "  InjectedInLeaf(ProvidedInAncestor providedInAncestor) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  InjectedInLeaf injectedInLeaf();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public InjectedInLeaf injectedInLeaf() {",
+            "    return new InjectedInLeaf((ProvidedInAncestor) getProvidedInAncestor());",
+            "  }",
+            "",
+            "  protected abstract String getString();",
+            "",
+            "  protected Object getProvidedInAncestor() {",
+            "    return new ProvidedInAncestor(getString());",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  static ProvidedInAncestor provideProvidedInAncestor() {",
+            "    return new ProvidedInAncestor(\"static\");",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected final Object getProvidedInAncestor() {",
+            "      return AncestorModule_ProvideProvidedInAncestorFactory",
+            "          .provideProvidedInAncestor();",
+            "    }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void provisionOverInjection_prunedIndirectDependency() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "PrunedDependency");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.InjectsPrunedDependency",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class InjectsPrunedDependency {",
+            "  @Inject",
+            "  InjectsPrunedDependency(PrunedDependency prunedDependency) {}",
+            "",
+            "  private InjectsPrunedDependency() { }",
+            "",
+            "  static InjectsPrunedDependency create() { return new InjectsPrunedDependency(); }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  InjectsPrunedDependency injectsPrunedDependency();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public InjectsPrunedDependency injectsPrunedDependency() {",
+            "    return new InjectsPrunedDependency((PrunedDependency) getPrunedDependency());",
+            "  }",
+            "",
+            "  protected abstract Object getPrunedDependency();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = RootModule.class)",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.RootModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class RootModule {",
+            "  @Provides",
+            "  static InjectsPrunedDependency injectsPrunedDependency() {",
+            "    return InjectsPrunedDependency.create();",
+            "  }",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Leaf leaf() {",
+            "    return new LeafImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    @Deprecated",
+            "    public Builder rootModule(RootModule rootModule) {",
+            "      Preconditions.checkNotNull(rootModule);",
+            "      return this;",
+            "    }",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    private LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected Object getPrunedDependency() {",
+            "      " + PRUNED_METHOD_BODY,
+            "    }",
+            "",
+            "    @Override",
+            "    public InjectsPrunedDependency injectsPrunedDependency() {",
+            "      return RootModule_InjectsPrunedDependencyFactory",
+            "          .injectsPrunedDependency();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void provisionOverInjection_prunedDirectDependency_prunedInConcreteImplementation() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        // The binding for PrunedDependency will always exist, but will change from
+        // ModifiableBindingType.INJECTION to ModifiableBindingType.MISSING. We should correctly
+        // ignore this change leave the modifiable binding method alone
+        JavaFileObjects.forSourceLines(
+            "test.PrunedDependency",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class PrunedDependency {",
+            "  @Inject PrunedDependency() {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.InjectsPrunedDependency",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class InjectsPrunedDependency {",
+            "  @Inject",
+            "  InjectsPrunedDependency(PrunedDependency prunedDependency) {}",
+            "",
+            "  private InjectsPrunedDependency() { }",
+            "",
+            "  static InjectsPrunedDependency create() { return new InjectsPrunedDependency(); }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  InjectsPrunedDependency injectsPrunedDependency();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public InjectsPrunedDependency injectsPrunedDependency() {",
+            "    return new InjectsPrunedDependency((PrunedDependency) getPrunedDependency());",
+            "  }",
+            "",
+            "  protected Object getPrunedDependency() {",
+            "    return new PrunedDependency();",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = RootModule.class)",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.RootModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class RootModule {",
+            "  @Provides",
+            "  static InjectsPrunedDependency injectsPrunedDependency() {",
+            "    return InjectsPrunedDependency.create();",
+            "  }",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Leaf leaf() {",
+            "    return new LeafImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    @Deprecated",
+            "    public Builder rootModule(RootModule rootModule) {",
+            "      Preconditions.checkNotNull(rootModule);",
+            "      return this;",
+            "    }",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    private LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public InjectsPrunedDependency injectsPrunedDependency() {",
+            "      return RootModule_InjectsPrunedDependencyFactory",
+            "          .injectsPrunedDependency();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void provisionOverInjection_prunedDirectDependency_prunedInAbstractImplementation() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        // The binding for PrunedDependency will always exist, but will change from
+        // ModifiableBindingType.INJECTION to ModifiableBindingType.MISSING. We should correctly
+        // ignore this change leave the modifiable binding method alone
+        JavaFileObjects.forSourceLines(
+            "test.PrunedDependency",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class PrunedDependency {",
+            "  @Inject PrunedDependency() {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.InjectsPrunedDependency",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class InjectsPrunedDependency {",
+            "  @Inject",
+            "  InjectsPrunedDependency(PrunedDependency prunedDependency) {}",
+            "",
+            "  private InjectsPrunedDependency() { }",
+            "",
+            "  static InjectsPrunedDependency create() { return new InjectsPrunedDependency(); }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  InjectsPrunedDependency injectsPrunedDependency();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public InjectsPrunedDependency injectsPrunedDependency() {",
+            "    return new InjectsPrunedDependency((PrunedDependency) getPrunedDependency());",
+            "  }",
+            "",
+            "  protected Object getPrunedDependency() {",
+            "    return new PrunedDependency();",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  static InjectsPrunedDependency injectsPrunedDependency() {",
+            "    return InjectsPrunedDependency.create();",
+            "  }",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public final InjectsPrunedDependency injectsPrunedDependency() {",
+            "      return AncestorModule_InjectsPrunedDependencyFactory",
+            "          .injectsPrunedDependency();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface Root {",
+            "  Ancestor ancestor();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Ancestor ancestor() {",
+            "    return new AncestorImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class AncestorImpl extends DaggerAncestor {",
+            "    private AncestorImpl() {}",
+            "",
+            "    @Override",
+            "    public Leaf leaf() {",
+            "      return new LeafImpl();",
+            "    }",
+            "",
+            "    protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      private LeafImpl() {}",
+            // even though DaggerAncestor.LeafImpl.getPrunedDependency() was
+            // ModifiableBindingType.MISSING, it doesn't need to be reimplemented because there was
+            // a base implementation
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void productionSubcomponentAndModifiableFrameworkInstance() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Response", "ResponseDependency");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import com.google.common.util.concurrent.ListenableFuture;",
+            "import dagger.producers.ProductionSubcomponent;",
+            "import java.util.Set;",
+            "",
+            "@ProductionSubcomponent(modules = ResponseProducerModule.class)",
+            "interface Leaf {",
+            "  ListenableFuture<Set<Response>> responses();",
+            "",
+            "  @ProductionSubcomponent.Builder",
+            "  interface Builder {",
+            "    Leaf build();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.ResponseProducerModule",
+            "package test;",
+            "",
+            "import dagger.multibindings.IntoSet;",
+            "import dagger.producers.ProducerModule;",
+            "import dagger.producers.Produces;",
+            "",
+            "@ProducerModule",
+            "final class ResponseProducerModule {",
+            "  @Produces",
+            "  @IntoSet",
+            "  static Response response(ResponseDependency responseDependency) {",
+            "    return new Response();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import com.google.common.util.concurrent.ListenableFuture;",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.producers.Producer;",
+            "import dagger.producers.internal.CancellationListener;",
+            "import dagger.producers.internal.Producers;",
+            "import dagger.producers.internal.SetProducer;",
+            "import dagger.producers.monitoring.ProductionComponentMonitor;",
+            "import java.util.Set;",
+            "import java.util.concurrent.Executor;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf, CancellationListener {",
+            "  private Producer<Set<Response>> responsesEntryPoint;",
+            "  private Producer<Response> responseProducer;",
+            "  private Producer<Set<Response>> setOfResponseProducer;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization() {",
+            "    initialize();",
+            "  }",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.responseProducer =",
+            "        ResponseProducerModule_ResponseFactory.create(",
+            "            getProductionImplementationExecutorProvider(),",
+            "            getProductionComponentMonitorProvider(),",
+            "            getResponseDependencyProducer());",
+            "    this.setOfResponseProducer =",
+            "        SetProducer.<Response>builder(1, 0)",
+            "            .addProducer(responseProducer).build();",
+            "    this.responsesEntryPoint =",
+            "        Producers.entryPointViewOf(getSetOfResponseProducer(), this);",
+            "  }",
+            "",
+            "  @Override",
+            "  public ListenableFuture<Set<Response>> responses() {",
+            "    return responsesEntryPoint.get();",
+            "  }",
+            "",
+            "  protected abstract Provider<Executor>",
+            "      getProductionImplementationExecutorProvider();",
+            "",
+            "  protected abstract Provider<ProductionComponentMonitor>",
+            "      getProductionComponentMonitorProvider();",
+            "",
+            "  protected abstract Producer getResponseDependencyProducer();",
+            "",
+            "  protected Producer getSetOfResponseProducer() {",
+            "    return setOfResponseProducer;",
+            "  }",
+            "",
+            "  @Override",
+            "  public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {",
+            "    Producers.cancel(getSetOfResponseProducer(), mayInterruptIfRunning);",
+            "    Producers.cancel(responseProducer, mayInterruptIfRunning);",
+            "  }",
+            "}");
+
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.ExecutorModule",
+            "package test;",
+            "",
+            "import com.google.common.util.concurrent.MoreExecutors;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.producers.Production;",
+            "import java.util.concurrent.Executor;",
+            "",
+            "@Module",
+            "final class ExecutorModule {",
+            "  @Provides",
+            "  @Production",
+            "  static Executor executor() {",
+            "    return MoreExecutors.directExecutor();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import com.google.common.util.concurrent.ListenableFuture;",
+            "import dagger.producers.ProductionComponent;",
+            "",
+            "@ProductionComponent(",
+            "  modules = {",
+            "      ExecutorModule.class,",
+            "      ResponseDependencyProducerModule.class,",
+            "      RootMultibindingModule.class,",
+            "  })",
+            "interface Root {",
+            "  Leaf.Builder leaf();",
+            "",
+            "  @ProductionComponent.Builder",
+            "  interface Builder {",
+            "    Root build();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.ResponseDependencyProducerModule",
+            "package test;",
+            "",
+            "import com.google.common.util.concurrent.Futures;",
+            "import com.google.common.util.concurrent.ListenableFuture;",
+            "import dagger.producers.ProducerModule;",
+            "import dagger.producers.Produces;",
+            "",
+            "@ProducerModule",
+            "final class ResponseDependencyProducerModule {",
+            "  @Produces",
+            "  static ListenableFuture<ResponseDependency> responseDependency() {",
+            "    return Futures.immediateFuture(new ResponseDependency());",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.RootMultibindingModule",
+            "package test;",
+            "",
+            "import dagger.multibindings.IntoSet;",
+            "import dagger.producers.ProducerModule;",
+            "import dagger.producers.Produces;",
+            "",
+            "@ProducerModule",
+            "final class RootMultibindingModule {",
+            "  @Produces",
+            "  @IntoSet",
+            "  static Response response() {",
+            "    return new Response();",
+            "  }",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            "import dagger.internal.DoubleCheck;",
+            "import dagger.internal.InstanceFactory;",
+            "import dagger.internal.SetFactory;",
+            "import dagger.producers.Producer;",
+            "import dagger.producers.internal.CancellationListener;",
+            "import dagger.producers.internal.DelegateProducer;",
+            "import dagger.producers.internal.Producers;",
+            "import dagger.producers.internal.SetProducer;",
+            "import dagger.producers.monitoring.ProductionComponentMonitor;",
+            "import java.util.Set;",
+            "import java.util.concurrent.Executor;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root, CancellationListener {",
+            "  private Provider<Executor> productionImplementationExecutorProvider;",
+            "  private Provider<Root> rootProvider;",
+            "  private Provider<ProductionComponentMonitor> monitorProvider;",
+            "  private Producer<ResponseDependency> responseDependencyProducer;",
+            "  private Producer<Response> responseProducer;",
+            "",
+            "  private DaggerRoot() {",
+            "    initialize();",
+            "  }",
+            "",
+            "  public static Root.Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.productionImplementationExecutorProvider =",
+            "        DoubleCheck.provider((Provider) ExecutorModule_ExecutorFactory.create());",
+            "    this.rootProvider = InstanceFactory.create((Root) this);",
+            "    this.monitorProvider =",
+            "        DoubleCheck.provider(",
+            "            Root_MonitoringModule_MonitorFactory.create(",
+            "                rootProvider,",
+            "                SetFactory.<ProductionComponentMonitor.Factory>empty()));",
+            "    this.responseDependencyProducer =",
+            "        ResponseDependencyProducerModule_ResponseDependencyFactory.create(",
+            "            productionImplementationExecutorProvider, monitorProvider);",
+            "    this.responseProducer =",
+            "        RootMultibindingModule_ResponseFactory.create(",
+            "            productionImplementationExecutorProvider, monitorProvider);",
+            "  }",
+            "",
+            "  @Override",
+            "  public Leaf.Builder leaf() {",
+            "    return new LeafBuilder();",
+            "  }",
+            "",
+            "  @Override",
+            "  public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {",
+            "    Producers.cancel(responseProducer, mayInterruptIfRunning);",
+            "    Producers.cancel(responseDependencyProducer, mayInterruptIfRunning);",
+            "  }",
+            "",
+            "  private static final class Builder implements Root.Builder {",
+            "    @Override",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  private final class LeafBuilder implements Leaf.Builder {",
+            "    @Override",
+            "    public Leaf build() {",
+            "      return new LeafImpl();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf implements CancellationListener {",
+            "    private Producer<Set<Response>> setOfResponseProducer = new DelegateProducer<>();",
+            "",
+            "    private LeafImpl() {",
+            "      configureInitialization();",
+            "      initialize();",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() {",
+            "      DelegateProducer.setDelegate(",
+            "          setOfResponseProducer,",
+            "          SetProducer.<Response>builder(1, 1)",
+            "              .addCollectionProducer(super.getSetOfResponseProducer())",
+            "              .addProducer(DaggerRoot.this.responseProducer)",
+            "              .build());",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Provider<Executor> getProductionImplementationExecutorProvider() {",
+            "      return DaggerRoot.this.productionImplementationExecutorProvider;",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Provider<ProductionComponentMonitor>",
+            "        getProductionComponentMonitorProvider() {",
+            "      return DaggerRoot.this.monitorProvider;",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Producer getResponseDependencyProducer() {",
+            "      return DaggerRoot.this.responseDependencyProducer;",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Producer getSetOfResponseProducer() {",
+            "      return setOfResponseProducer;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void lazyOfModifiableBinding() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "MissingInLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Lazy;",
+            "import dagger.Subcomponent;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  Lazy<MissingInLeaf> lazy();",
+            "  Provider<Lazy<MissingInLeaf>> providerOfLazy();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.Lazy;",
+            "import dagger.internal.DoubleCheck;",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.ProviderOfLazy;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Lazy<MissingInLeaf> lazy() {",
+            "    return DoubleCheck.lazy(getMissingInLeafProvider());",
+            "  }",
+            "",
+            "  @Override",
+            "  public Provider<Lazy<MissingInLeaf>> providerOfLazy() {",
+            "    return ProviderOfLazy.create(getMissingInLeafProvider());",
+            "  }",
+            "",
+            "  protected abstract Provider getMissingInLeafProvider();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class AncestorModule {",
+            "  @Provides",
+            "  static MissingInLeaf satisfiedInAncestor() { return new MissingInLeaf(); }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected final Provider getMissingInLeafProvider() {",
+            "      return AncestorModule_SatisfiedInAncestorFactory.create();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void missingBindingAccessInLeafAndAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(
+        filesToCompile, "Missing", "DependsOnMissing", "ProvidedInAncestor_InducesSetBinding");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.multibindings.IntoSet;",
+            "import dagger.Provides;",
+            "import javax.inject.Provider;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  static DependsOnMissing test(",
+            "      Missing missing,",
+            "      Provider<Missing> missingProvider,",
+            "      ProvidedInAncestor_InducesSetBinding missingInLeaf) {",
+            "    return new DependsOnMissing();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @IntoSet",
+            "  static Object unresolvedSetBinding(",
+            "      Missing missing, Provider<Missing> missingProvider) {",
+            "    return new Object();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  DependsOnMissing instance();",
+            "  Provider<DependsOnMissing> frameworkInstance();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  private Provider<DependsOnMissing> testProvider;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization() {",
+            "    initialize();",
+            "  }",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.testProvider =",
+            "        LeafModule_TestFactory.create(",
+            "            getMissingProvider(), getProvidedInAncestor_InducesSetBindingProvider());",
+            "  }",
+            "",
+            "  @Override",
+            "  public DependsOnMissing instance() {",
+            "    return LeafModule_TestFactory.test(",
+            // TODO(b/117833324): remove these unnecessary casts
+            "        (Missing) getMissing(),",
+            "        getMissingProvider(),",
+            "        (ProvidedInAncestor_InducesSetBinding)",
+            "            getProvidedInAncestor_InducesSetBinding());",
+            "  }",
+            "",
+            "  @Override",
+            "  public Provider<DependsOnMissing> frameworkInstance() {",
+            "    return testProvider;",
+            "  }",
+            "",
+            "  protected abstract Object getMissing();",
+            "  protected abstract Provider getMissingProvider();",
+            "  protected abstract Object getProvidedInAncestor_InducesSetBinding();",
+            "  protected abstract Provider getProvidedInAncestor_InducesSetBindingProvider();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.multibindings.IntoSet;",
+            "import dagger.Provides;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "interface AncestorModule {",
+            "  @Provides",
+            "  static ProvidedInAncestor_InducesSetBinding providedInAncestor(",
+            "      Set<Object> setThatInducesMissingBindingInChildSubclassImplementation) {",
+            "    return new ProvidedInAncestor_InducesSetBinding();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @IntoSet",
+            "  static Object setContribution() {",
+            "    return new Object();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.DelegateFactory;",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.SetFactory;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    private Provider<Object> unresolvedSetBindingProvider;",
+            "    private Provider<Set<Object>> setOfObjectProvider;",
+            "    private Provider<ProvidedInAncestor_InducesSetBinding> ",
+            "        providedInAncestorProvider = ",
+            "            new DelegateFactory<>();",
+            "",
+            "    protected LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected void configureInitialization() {",
+            "      super.configureInitialization();",
+            "      initialize();",
+            "    }",
+            "",
+            "    private Object getUnresolvedSetBinding() {",
+            "      return LeafModule_UnresolvedSetBindingFactory.unresolvedSetBinding(",
+            // TODO(b/117833324): remove this unnecessary cast
+            "          (Missing) getMissing(), getMissingProvider());",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() {",
+            "      this.unresolvedSetBindingProvider =",
+            "          LeafModule_UnresolvedSetBindingFactory.create(getMissingProvider());",
+            "      this.setOfObjectProvider =",
+            "          SetFactory.<Object>builder(2, 0)",
+            "              .addProvider(AncestorModule_SetContributionFactory.create())",
+            "              .addProvider(unresolvedSetBindingProvider)",
+            "              .build();",
+            "      DelegateFactory.setDelegate(",
+            "          providedInAncestorProvider,",
+            "          AncestorModule_ProvidedInAncestorFactory.create(getSetOfObjectProvider()));",
+            "    }",
+            "",
+            "    protected Set<Object> getSetOfObject() {",
+            "      return ImmutableSet.<Object>of(",
+            "          AncestorModule_SetContributionFactory.setContribution(),",
+            "          getUnresolvedSetBinding());",
+            "    }",
+            "",
+            "    @Override",
+            "    protected final Object getProvidedInAncestor_InducesSetBinding() {",
+            "      return AncestorModule_ProvidedInAncestorFactory.providedInAncestor(",
+            "          getSetOfObject());",
+            "    }",
+            "",
+            "    protected Provider<Set<Object>> getSetOfObjectProvider() {",
+            "      return setOfObjectProvider;",
+            "    }",
+            "",
+            "    @Override",
+            "    protected final Provider getProvidedInAncestor_InducesSetBindingProvider() {",
+            "      return providedInAncestorProvider;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void subcomponentBuilders() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "InducesDependenciesOnBuilderFields");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  private final Object object;",
+            "",
+            "  LeafModule(Object object) {",
+            "    this.object = object;",
+            "  }",
+            "",
+            "  @Provides",
+            "  Object fromModule() {",
+            "    return object;",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.MultibindingsModule",
+            "package test;",
+            "",
+            "import dagger.Binds;",
+            "import dagger.Module;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "interface MultibindingsModule {",
+            "  @Binds",
+            "  @IntoSet",
+            "  String string(String string);",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.BindsInstance;",
+            "import dagger.Subcomponent;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent(modules = {LeafModule.class, MultibindingsModule.class})",
+            "interface Leaf {",
+            "  int bindsInstance();",
+            "  Object fromModule();",
+            "  InducesDependenciesOnBuilderFields inducesDependenciesOnBuilderFields();",
+            "",
+            "  @Subcomponent.Builder",
+            "  interface Builder {",
+            "    @BindsInstance Builder bindsInstance(int boundInstance);",
+            "    @BindsInstance Builder inducedInSubclass(String induced);",
+            "    Builder module(LeafModule module);",
+            "",
+            "    Leaf build();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  private Integer bindsInstance;",
+            "  private LeafModule leafModule;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization(",
+            "      LeafModule leafModuleParam, Integer bindsInstanceParam) {",
+            "    this.bindsInstance = bindsInstanceParam;",
+            "    this.leafModule = leafModuleParam;",
+            "  }",
+            "",
+            "  @Override",
+            "  public int bindsInstance() {",
+            "    return bindsInstance;",
+            "  }",
+            "",
+            "  @Override",
+            "  public Object fromModule() {",
+            "    return LeafModule_FromModuleFactory.fromModule(leafModule());",
+            "  }",
+            "",
+            "  @Override",
+            "  public abstract InducesDependenciesOnBuilderFields",
+            "      inducesDependenciesOnBuilderFields();",
+            "",
+            "  protected LeafModule leafModule() {",
+            "    return leafModule;",
+            "  }",
+            "",
+            "  public abstract static class Builder implements Leaf.Builder {",
+            "    protected Integer bindsInstance;",
+            "    protected String inducedInSubclass;",
+            "    protected LeafModule leafModule;",
+            "",
+            "    @Override",
+            "    public Builder bindsInstance(int boundInstance) {",
+            "      this.bindsInstance = Preconditions.checkNotNull(boundInstance);",
+            "      return this;",
+            "    }",
+            "",
+            "    @Override",
+            "    public Builder inducedInSubclass(String induced) {",
+            "      this.inducedInSubclass = Preconditions.checkNotNull(induced);",
+            "      return this;",
+            "    }",
+            "",
+            "    @Override",
+            "    public Builder module(LeafModule module) {",
+            "      this.leafModule = Preconditions.checkNotNull(module);",
+            "      return this;",
+            "    }",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = MultibindingInducingModule.class)",
+            "interface Ancestor {",
+            "  Leaf.Builder leaf();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.MultibindingInducingModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.multibindings.Multibinds;",
+            "import dagger.Provides;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "interface MultibindingInducingModule {",
+            "  @Provides",
+            "  static InducesDependenciesOnBuilderFields induce(",
+            "      Set<String> multibindingWithBuilderFieldDeps) { ",
+            "    return new InducesDependenciesOnBuilderFields();",
+            "  }",
+            "",
+            "  @Multibinds",
+            "  Set<String> multibinding();",
+            "}"));
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  @Override",
+            "  public abstract Leaf.Builder leaf();",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    private String inducedInSubclass;",
+            "",
+            "    protected LeafImpl() {}",
+            "",
+            "    protected void configureInitialization(",
+            "        LeafModule leafModule,",
+            "        Integer bindsInstance,",
+            "        String inducedInSubclassParam) {",
+            "      this.inducedInSubclass = inducedInSubclassParam;",
+            "      configureInitialization(leafModule, bindsInstance);",
+            "    }",
+            "",
+            "    protected Set<String> getSetOfString() {",
+            "      return ImmutableSet.<String>of(inducedInSubclass);",
+            "    }",
+            "",
+            "    @Override",
+            "    public final InducesDependenciesOnBuilderFields",
+            "        inducesDependenciesOnBuilderFields() {",
+            "      return MultibindingInducingModule_InduceFactory.induce(getSetOfString());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface Root {",
+            "  Ancestor ancestor();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Ancestor ancestor() {",
+            "    return new AncestorImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class AncestorImpl extends DaggerAncestor {",
+            "    private AncestorImpl() {}",
+            "",
+            "    @Override",
+            "    public Leaf.Builder leaf() {",
+            "      return new LeafBuilder();",
+            "    }",
+            "",
+            "    private final class LeafBuilder extends DaggerLeaf.Builder {",
+            "      @Override",
+            "      public Leaf build() {",
+            // TODO(b/117833324): Can we stick the validations into a method on the base class
+            // builder so that the contents of this method are just call to that and then new
+            // FooImpl? But repeated modules may make this more complicated, since those *should*
+            // be null
+            "        Preconditions.checkBuilderRequirement(bindsInstance, Integer.class);",
+            "        Preconditions.checkBuilderRequirement(inducedInSubclass, String.class);",
+            "        Preconditions.checkBuilderRequirement(leafModule, LeafModule.class);",
+            "        return new LeafImpl(leafModule, bindsInstance, inducedInSubclass);",
+            "      }",
+            "    }",
+            "",
+            "    protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      private final LeafModule leafModule;",
+            "",
+            "      private LeafImpl(",
+            "          LeafModule leafModuleParam,",
+            "          Integer bindsInstance,",
+            "          String inducedInSubclass) {",
+            "        this.leafModule = leafModuleParam;",
+            "        configureInitialization(leafModuleParam, bindsInstance, inducedInSubclass);",
+            "      }",
+            "",
+            "      @Override",
+            "      protected LeafModule leafModule() {",
+            "        return leafModule;",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void subcomponentBuilders_moduleWithUnusedInstanceBindings() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Used", "Unused");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.ModuleWithUsedBinding",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class ModuleWithUsedBinding {",
+            "  @Provides",
+            "  Used used() {",
+            "    return new Used();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.ModuleWithUnusedBinding",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class ModuleWithUnusedBinding {",
+            "  @Provides",
+            "  Unused unused() {",
+            "    return new Unused();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = {ModuleWithUsedBinding.class, ModuleWithUnusedBinding.class})",
+            "interface Leaf {",
+            "  Used used();",
+            "",
+            "  @Subcomponent.Builder",
+            "  interface Builder {",
+            "    Builder setUsed(ModuleWithUsedBinding module);",
+            "    Builder setUnused(ModuleWithUnusedBinding module);",
+            "    Leaf build();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  private ModuleWithUsedBinding moduleWithUsedBinding;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization(",
+            "      ModuleWithUsedBinding moduleWithUsedBindingParam) {",
+            "    this.moduleWithUsedBinding = moduleWithUsedBindingParam;",
+            "  }",
+            "",
+            "  @Override",
+            "  public Used used() {",
+            "    return ModuleWithUsedBinding_UsedFactory.used(",
+            "        moduleWithUsedBinding());",
+            "  }",
+            "",
+            "  protected ModuleWithUsedBinding moduleWithUsedBinding() {",
+            "    return moduleWithUsedBinding;",
+            "  }",
+            "",
+            "  public abstract static class Builder implements Leaf.Builder {",
+            "    protected ModuleWithUsedBinding moduleWithUsedBinding;",
+            "    protected ModuleWithUnusedBinding moduleWithUnusedBinding;",
+            "",
+            "    @Override",
+            "    public Builder setUsed(ModuleWithUsedBinding module) {",
+            "      this.moduleWithUsedBinding = Preconditions.checkNotNull(module);",
+            "      return this;",
+            "    }",
+            "",
+            "    @Override",
+            "    public Builder setUnused(ModuleWithUnusedBinding module) {",
+            "      this.moduleWithUnusedBinding = Preconditions.checkNotNull(module);",
+            "      return this;",
+            "    }",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface Root {",
+            "  Leaf.Builder leaf();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Leaf.Builder leaf() {",
+            "    return new LeafBuilder();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  private final class LeafBuilder extends DaggerLeaf.Builder {",
+            "    @Override",
+            "    public Leaf build() {",
+            "      if (moduleWithUsedBinding == null) {",
+            "        this.moduleWithUsedBinding = new ModuleWithUsedBinding();",
+            "      }",
+            // ModuleWithUnusedBinding is not verified since it's not used
+            "      return new LeafImpl(moduleWithUsedBinding);",
+            "    }",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    private final ModuleWithUsedBinding moduleWithUsedBinding;",
+            "",
+            "    private LeafImpl(ModuleWithUsedBinding moduleWithUsedBindingParam) {",
+            "      this.moduleWithUsedBinding = moduleWithUsedBindingParam;",
+            "      configureInitialization(moduleWithUsedBindingParam);",
+            "    }",
+            "",
+            "    @Override",
+            "    protected ModuleWithUsedBinding moduleWithUsedBinding() {",
+            "      return moduleWithUsedBinding;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void subcomponentBuilders_repeatedModule() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.RepeatedModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class RepeatedModule {",
+            "  @Provides",
+            "  int i() {",
+            "    return 1;",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = RepeatedModule.class)",
+            "interface Leaf {",
+            "  int i();",
+            "",
+            "  @Subcomponent.Builder",
+            "  interface Builder {",
+            "    Builder repeatedModule(RepeatedModule repeatedModule);",
+            "    Leaf build();",
+            "  }",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  private RepeatedModule repeatedModule;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization(RepeatedModule repeatedModuleParam) {",
+            "    this.repeatedModule = repeatedModuleParam;",
+            "  }",
+            "",
+            "  @Override",
+            "  public int i() {",
+            "    return repeatedModule().i();",
+            "  }",
+            "",
+            "  protected RepeatedModule repeatedModule() {",
+            "    return repeatedModule;",
+            "  }",
+            "",
+            "  public abstract static class Builder implements Leaf.Builder {",
+            "    protected RepeatedModule repeatedModule;",
+            "",
+            "    @Override",
+            "    public Builder repeatedModule(RepeatedModule repeatedModule) {",
+            "      this.repeatedModule = Preconditions.checkNotNull(repeatedModule);",
+            "      return this;",
+            "    }",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = RepeatedModule.class)",
+            "interface Root {",
+            "  Leaf.Builder leaf();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private final RepeatedModule repeatedModule;",
+            "",
+            "  private DaggerRoot(RepeatedModule repeatedModuleParam) {",
+            "    this.repeatedModule = repeatedModuleParam;",
+            "  }",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Leaf.Builder leaf() {",
+            "    return new LeafBuilder();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private RepeatedModule repeatedModule;",
+            "",
+            "    private Builder() {}",
+            "",
+            "    public Builder repeatedModule(RepeatedModule repeatedModule) {",
+            "      this.repeatedModule = Preconditions.checkNotNull(repeatedModule);",
+            "      return this;",
+            "    }",
+            "",
+            "    public Root build() {",
+            "      if (repeatedModule == null) {",
+            "        this.repeatedModule = new RepeatedModule();",
+            "      }",
+            "      return new DaggerRoot(repeatedModule);",
+            "    }",
+            "  }",
+            "",
+            "  private final class LeafBuilder extends DaggerLeaf.Builder {",
+            "    @Override",
+            "    public LeafBuilder repeatedModule(RepeatedModule repeatedModule) {",
+            "      throw new UnsupportedOperationException(",
+            "        String.format(",
+            "          \"%s cannot be set because it is inherited from the enclosing component\",",
+            "          RepeatedModule.class.getCanonicalName()));",
+            "    }",
+            "",
+            "    @Override",
+            "    public Leaf build() {",
+            "      return new LeafImpl();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    private LeafImpl() {",
+            "      configureInitialization(null);",
+            "    }",
+            "",
+            "    @Override",
+            "    protected RepeatedModule repeatedModule() {",
+            "      return DaggerRoot.this.repeatedModule;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void bindsWithMissingDependency() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "MissingInLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Binds;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Binds Object missingBindsDependency(MissingInLeaf missing);",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Object bindsWithMissingDependencyInLeaf();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract Object bindsWithMissingDependencyInLeaf();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.MissingInLeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "interface MissingInLeafModule {",
+            "  @Provides",
+            "  static MissingInLeaf boundInRoot() {",
+            "    return new MissingInLeaf();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = MissingInLeafModule.class)",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Leaf leaf() {",
+            "    return new LeafImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    private LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public Object bindsWithMissingDependencyInLeaf() {",
+            "      return MissingInLeafModule_BoundInRootFactory.boundInRoot();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void bindsWithMissingDependency_pruned() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "MissingInLeaf");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Binds;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Binds Object missingBindsDependency(MissingInLeaf missing);",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.DependsOnBindsWithMissingDep",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class DependsOnBindsWithMissingDep {",
+            "  @Inject DependsOnBindsWithMissingDep(Object bindsWithMissingDep) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  DependsOnBindsWithMissingDep DependsOnBindsWithMissingDep();",
+            "}"));
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public DependsOnBindsWithMissingDep DependsOnBindsWithMissingDep() {",
+            "    return new DependsOnBindsWithMissingDep(getObject());",
+            "  }",
+            "",
+            "  protected abstract Object getObject();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.PrunesInjectConstructorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "interface PrunesInjectConstructorModule {",
+            "  @Provides",
+            "  static DependsOnBindsWithMissingDep pruneInjectConstructor() {",
+            "    return new DependsOnBindsWithMissingDep(new Object());",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = PrunesInjectConstructorModule.class)",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Leaf leaf() {",
+            "    return new LeafImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    private LeafImpl() {}",
+            "",
+            "    @Override",
+            "    protected Object getObject() {",
+            "      " + PRUNED_METHOD_BODY,
+            "    }",
+            "",
+            "    @Override",
+            "    public DependsOnBindsWithMissingDep DependsOnBindsWithMissingDep() {",
+            "      return PrunesInjectConstructorModule_PruneInjectConstructorFactory",
+            "          .pruneInjectConstructor();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void modifiedProducerFromProvider() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "DependsOnModifiedProducerFromProvider");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.multibindings.IntoSet;",
+            "import dagger.producers.ProducerModule;",
+            "import dagger.producers.Produces;",
+            "import dagger.Provides;",
+            "import java.util.Set;",
+            "",
+            "@ProducerModule",
+            "interface LeafModule {",
+            "  @Produces",
+            "  static DependsOnModifiedProducerFromProvider dependsOnModified(Set<String> set) {",
+            "    return new DependsOnModifiedProducerFromProvider();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.producers.Producer;",
+            "import dagger.producers.ProductionSubcomponent;",
+            "import java.util.Set;",
+            "",
+            "@ProductionSubcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Producer<DependsOnModifiedProducerFromProvider>",
+            "      dependsOnModifiedProducerFromProvider();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import dagger.producers.Producer;",
+            "import dagger.producers.internal.CancellationListener;",
+            "import dagger.producers.internal.Producers;",
+            "import dagger.producers.monitoring.ProductionComponentMonitor;",
+            "import java.util.Set;",
+            "import java.util.concurrent.Executor;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf, CancellationListener {",
+            "  private Producer<DependsOnModifiedProducerFromProvider>",
+            "      dependsOnModifiedProducerFromProviderEntryPoint;",
+            "  private Producer<DependsOnModifiedProducerFromProvider> dependsOnModifiedProducer;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization() {",
+            "    initialize();",
+            "  }",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.dependsOnModifiedProducer =",
+            "        LeafModule_DependsOnModifiedFactory.create(",
+            "            getProductionImplementationExecutorProvider(),",
+            "            getProductionComponentMonitorProvider(),",
+            "            getSetOfStringProducer());",
+            "    this.dependsOnModifiedProducerFromProviderEntryPoint =",
+            "        Producers.entryPointViewOf(dependsOnModifiedProducer, this);",
+            "  }",
+            "",
+            "  @Override",
+            "  public Producer<DependsOnModifiedProducerFromProvider> ",
+            "      dependsOnModifiedProducerFromProvider() {",
+            "    return dependsOnModifiedProducerFromProviderEntryPoint;",
+            "  }",
+            "",
+            "  protected abstract Provider<Executor> ",
+            "      getProductionImplementationExecutorProvider();",
+            "",
+            "  protected abstract Provider<ProductionComponentMonitor>",
+            "      getProductionComponentMonitorProvider();",
+            "",
+            "  protected abstract Producer<Set<String>> getSetOfStringProducer();",
+            "",
+            "  @Override",
+            "  public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {",
+            "    Producers.cancel(dependsOnModifiedProducer, mayInterruptIfRunning);",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.RootModule",
+            "package test;",
+            "",
+            "import dagger.multibindings.IntoSet;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.producers.Production;",
+            "import java.util.Set;",
+            "import java.util.concurrent.Executor;",
+            "",
+            "@Module",
+            "interface RootModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static String induceModificationInLeaf() {",
+            "    return new String();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @Production",
+            "  static Executor productionExecutor() {",
+            "    return null;",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = RootModule.class)",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"));
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            "import dagger.internal.DelegateFactory;",
+            "import dagger.internal.DoubleCheck;",
+            "import dagger.internal.InstanceFactory;",
+            "import dagger.internal.SetFactory;",
+            "import dagger.producers.Producer;",
+            "import dagger.producers.internal.CancellationListener;",
+            "import dagger.producers.internal.DelegateProducer;",
+            "import dagger.producers.internal.Producers;",
+            "import dagger.producers.monitoring.ProductionComponentMonitor;",
+            "import java.util.Set;",
+            "import java.util.concurrent.Executor;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private DaggerRoot() {}",
+            "",
+            "  public static Builder builder() {",
+            "    return new Builder();",
+            "  }",
+            "",
+            "  public static Root create() {",
+            "    return new Builder().build();",
+            "  }",
+            "",
+            "  @Override",
+            "  public Leaf leaf() {",
+            "    return new LeafImpl();",
+            "  }",
+            "",
+            "  static final class Builder {",
+            "    private Builder() {}",
+            "",
+            "    public Root build() {",
+            "      return new DaggerRoot();",
+            "    }",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf implements CancellationListener {",
+            "    private Provider<Executor> productionImplementationExecutorProvider =",
+            "        new DelegateFactory<>();",
+            "    private Provider<Leaf> leafProvider;",
+            "    private Provider<ProductionComponentMonitor> monitorProvider =",
+            "        new DelegateFactory<>();",
+            "    private Provider<Set<String>> setOfStringProvider;",
+            "    private Producer<Set<String>> setOfStringProducer = new DelegateProducer<>();",
+            "",
+            "    private LeafImpl() {",
+            "      configureInitialization();",
+            "      initialize();",
+            "    }",
+            "",
+            "    @SuppressWarnings(\"unchecked\")",
+            "    private void initialize() {",
+            "      DelegateFactory.setDelegate(",
+            "          productionImplementationExecutorProvider,",
+            "          DoubleCheck.provider(",
+            "              (Provider) RootModule_ProductionExecutorFactory.create()));",
+            "      this.leafProvider = InstanceFactory.create((Leaf) this);",
+            "      DelegateFactory.setDelegate(",
+            "          monitorProvider,",
+            "          DoubleCheck.provider(",
+            "              Leaf_MonitoringModule_MonitorFactory.create(",
+            "                  leafProvider,",
+            "                  getSetOfProductionComponentMonitorFactoryProvider())));",
+            "      this.setOfStringProvider =",
+            "          SetFactory.<String>builder(1, 0)",
+            "              .addProvider(RootModule_InduceModificationInLeafFactory.create())",
+            "              .build();",
+            "      DelegateProducer.setDelegate(",
+            "          setOfStringProducer,",
+            "          Producers.producerFromProvider(getSetOfStringProvider()));",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Provider<Executor> getProductionImplementationExecutorProvider() {",
+            "      return productionImplementationExecutorProvider;",
+            "    }",
+            "",
+            "    protected Provider<Set<ProductionComponentMonitor.Factory>> ",
+            "        getSetOfProductionComponentMonitorFactoryProvider() {",
+            "      return SetFactory.<ProductionComponentMonitor.Factory>empty();",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Provider<ProductionComponentMonitor> ",
+            "        getProductionComponentMonitorProvider() {",
+            "      return monitorProvider;",
+            "    }",
+            "",
+            "    protected Provider<Set<String>> getSetOfStringProvider() {",
+            "      return setOfStringProvider;",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Producer<Set<String>> getSetOfStringProducer() {",
+            "      return setOfStringProducer;",
+            "    }",
+            "",
+            "    @Override",
+            "    public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {",
+            "      super.onProducerFutureCancelled(mayInterruptIfRunning);",
+            "      Producers.cancel(getSetOfStringProducer(), mayInterruptIfRunning);",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .hasSourceEquivalentTo(generatedRoot);
+  }
+
+  @Test
+  public void modifiableBindingMethods_namesDedupedAcrossImplementations() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "foo.Thing",
+            "package foo;",
+            "", // force multi-line format
+            "public interface Thing extends CharSequence {}"),
+        JavaFileObjects.forSourceLines(
+            "bar.Thing",
+            "package bar;",
+            "", // force multi-line format
+            "public interface Thing extends Runnable {}"),
+        JavaFileObjects.forSourceLines(
+            "test.WillInduceSetOfRunnable",
+            "package test;",
+            "", // force multi-line format
+            "class WillInduceSetOfRunnable {}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Provides",
+            "  static CharSequence depOnFooThing(foo.Thing thing) {",
+            "    return thing.toString();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @IntoSet",
+            "  static Runnable depOnBarThing(bar.Thing thing) {",
+            "    return () -> {};",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  CharSequence inducesFoo();",
+            "  WillInduceSetOfRunnable willInduceSetOfRunnable();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            "import foo.Thing;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public CharSequence inducesFoo() {",
+            "    return LeafModule_DepOnFooThingFactory.depOnFooThing(getThing());",
+            "  }",
+            "",
+            "  @Override",
+            "  public abstract WillInduceSetOfRunnable willInduceSetOfRunnable();",
+            "",
+            "  protected abstract Thing getThing();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.Multibinds;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "interface AncestorModule {",
+            "  @Provides",
+            "  static WillInduceSetOfRunnable induce(Set<Runnable> set) {",
+            "    return null;",
+            "  }",
+            "",
+            "  @Multibinds Set<Runnable> runnables();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  Leaf leaf();",
+            "}"));
+
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import bar.Thing;",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class LeafImpl extends DaggerLeaf {",
+            "    protected LeafImpl() {}",
+            "",
+            "    private Runnable getDepOnBarThing() {",
+            "      return LeafModule_DepOnBarThingFactory.depOnBarThing(getThing2());",
+            "    }",
+            "",
+            "    protected abstract Thing getThing2();",
+            "",
+            "    protected Set<Runnable> getSetOfRunnable() {",
+            "      return ImmutableSet.<Runnable>of(getDepOnBarThing());",
+            "    }",
+            "",
+            "    @Override",
+            "    public final WillInduceSetOfRunnable willInduceSetOfRunnable() {",
+            "      return AncestorModule_InduceFactory.induce(getSetOfRunnable());",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  /**
+   * This test verifies that Dagger can find the appropriate child subcomponent
+   * super-implementation, even if it is not enclosed in the current component's
+   * super-implementation. This can happen if a subcomponent is installed with a module's {@code
+   * subcomponents} attribute, but the binding is not accessed in a super-implementation. To exhibit
+   * this, we use multibindings that reference the pruned subcomponent, but make the multibinding
+   * also unresolved in the base implementation. An ancestor component defines a binding that
+   * depends on the multibinding, which induces the previously unresolved multibinding
+   * contributions, which itself induces the previously unresolved subcomponent.
+   */
+  @Test
+  public void subcomponentInducedFromAncestor() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Inducer");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.InducedSubcomponent",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface InducedSubcomponent {",
+            "  @Subcomponent.Builder",
+            "  interface Builder {",
+            "    InducedSubcomponent build();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.MaybeLeaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = InducedSubcomponentModule.class)",
+            "interface MaybeLeaf {",
+            "  Inducer inducer();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.MaybeLeaf",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module(subcomponents = InducedSubcomponent.class)",
+            "interface InducedSubcomponentModule {",
+            "  @Provides",
+            "  @IntoSet",
+            "  static Object inducedSet(InducedSubcomponent.Builder builder) {",
+            "    return new Object();",
+            "  }",
+            "}"));
+
+    JavaFileObject generatedMaybeLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerMaybeLeaf implements MaybeLeaf {",
+            "  protected DaggerMaybeLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract Inducer inducer();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerMaybeLeaf")
+        .hasSourceEquivalentTo(generatedMaybeLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.Multibinds;",
+            "import java.util.Set;",
+            "",
+            "@Module",
+            "interface AncestorModule {",
+            "  @Provides",
+            "  static Inducer inducer(Set<Object> set) {",
+            "    return null;",
+            "  }",
+            "",
+            "  @Multibinds Set<Object> set();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = AncestorModule.class)",
+            "interface Ancestor {",
+            "  MaybeLeaf noLongerLeaf();",
+            "}"));
+
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            "import com.google.common.collect.ImmutableSet;",
+            "import dagger.internal.GenerationOptions;",
+            "import java.util.Set;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected DaggerAncestor() {}",
+            "",
+            "  protected abstract class MaybeLeafImpl extends DaggerMaybeLeaf {",
+            "    protected MaybeLeafImpl() {}",
+            "",
+            "    private Object getInducedSet() {",
+            "      return InducedSubcomponentModule_InducedSetFactory.inducedSet(",
+            // TODO(b/117833324): remove this unnecessary cast
+            "          (InducedSubcomponent.Builder) getInducedSubcomponentBuilder());",
+            "    }",
+            "",
+            "    protected abstract Object getInducedSubcomponentBuilder();",
+            "",
+            "    protected Set<Object> getSetOfObject() {",
+            "      return ImmutableSet.<Object>of(getInducedSet());",
+            "    }",
+            "",
+            "    @Override",
+            "    public final Inducer inducer() {",
+            "      return AncestorModule_InducerFactory.inducer(getSetOfObject());",
+            "    }",
+            "",
+            "    protected abstract class InducedSubcomponentImpl extends",
+            "        DaggerInducedSubcomponent {",
+            //       ^ Note that this is DaggerInducedSubcomponent, not
+            //         DaggerMaybeLeaf.InducedSubcomponentImpl
+            "      protected InducedSubcomponentImpl() {}",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .hasSourceEquivalentTo(generatedAncestor);
+  }
+
+  @Test
+  public void rootScopedAtInjectConstructor_effectivelyMissingInSubcomponent() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "ProvidesMethodRootScoped");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.RootScope",
+            "package test;",
+            "",
+            "import javax.inject.Scope;",
+            "",
+            "@Scope",
+            "public @interface RootScope {}"),
+        JavaFileObjects.forSourceLines(
+            "test.AtInjectRootScoped",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "@RootScope",
+            "class AtInjectRootScoped {",
+            "  @Inject AtInjectRootScoped() {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  AtInjectRootScoped shouldBeEffectivelyMissingInLeaf();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public abstract AtInjectRootScoped shouldBeEffectivelyMissingInLeaf();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@RootScope",
+            "@Component",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"));
+
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    @Override",
+            "    public AtInjectRootScoped shouldBeEffectivelyMissingInLeaf() {",
+            "      return DaggerRoot.this.atInjectRootScopedProvider.get();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .containsElementsIn(generatedRoot);
+  }
+
+  @Test
+  public void prunedModuleWithInstanceState() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Pruned");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Modified",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class Modified {",
+            "  @Inject Modified(Pruned pruned) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class LeafModule {",
+            "  @Provides",
+            "  Pruned pruned() {",
+            "    return new Pruned();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Modified modified();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  @Override",
+            "  public Modified modified() {",
+            "    return new Modified(LeafModule_PrunedFactory.pruned(leafModule()));",
+            "  }",
+            "",
+            "  protected abstract LeafModule leafModule();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.RootModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "class RootModule {",
+            "  @Provides",
+            "  static Modified modified() {",
+            "    return new Modified(null);",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = RootModule.class)",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"));
+
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            IMPORT_GENERATED_ANNOTATION,
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    @Override",
+            "    public Modified modified() {",
+            "      return RootModule_ModifiedFactory.modified();",
+            "    }",
+            "",
+            "    @Override",
+            "    protected LeafModule leafModule() {",
+            "      return null;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .containsElementsIn(generatedRoot);
+  }
+
+  @Test
+  public void modifiableCycles() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.A",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class A {",
+            "  @Inject A(B b) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.B",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "import javax.inject.Provider;",
+            "",
+            "class B {",
+            "  @Inject B(Provider<A> a) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  Provider<A> frameworkInstanceCycle();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import dagger.internal.DelegateFactory;",
+            "import dagger.internal.GenerationOptions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  private Provider<A> aProvider;",
+            "  private Provider<B> bProvider;",
+            "",
+            "  protected DaggerLeaf() {}",
+            "",
+            "  protected void configureInitialization() {",
+            "    initialize();",
+            "  }",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.aProvider = new DelegateFactory<>();",
+            "    this.bProvider = B_Factory.create(frameworkInstanceCycle());",
+            "    DelegateFactory.setDelegate(aProvider, A_Factory.create(getBProvider()));",
+            "  }",
+            "",
+            "  @Override",
+            "  public Provider<A> frameworkInstanceCycle() {",
+            "    return aProvider;",
+            "  }",
+            "",
+            "  protected Provider getBProvider() {",
+            "    return bProvider;",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .hasSourceEquivalentTo(generatedLeaf);
+  }
+
+  /**
+   * This tests a regression case where the component builder in the base implementation used one
+   * set of disambiguated names from all of the {@link ComponentDescriptor#requirements()}, and the
+   * final implementation used a different set of disambiguated names from the resolved {@link
+   * BindingGraph#componentRequirements()}. This resulted in generated output that didn't compile,
+   * as the builder implementation attempted to use the new names in validation, which didn't line
+   * up with the old names.
+   */
+  @Test
+  public void componentBuilderFields_consistencyAcrossImplementations() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "a.Mod",
+            "package a;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import javax.inject.Named;",
+            "",
+            "@Module",
+            "public class Mod {",
+            "  @Provides",
+            "  @Named(\"a\")",
+            "  int i() { return 0; }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "b.Mod",
+            "package b;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import javax.inject.Named;",
+            "",
+            "@Module",
+            "public class Mod {",
+            "  @Provides",
+            "  @Named(\"b\")",
+            "  int i() { return 0; }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "c.Mod",
+            "package c;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import javax.inject.Named;",
+            "",
+            "@Module",
+            "public class Mod {",
+            "  @Provides",
+            "  @Named(\"c\")",
+            "  int i() { return 0; }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.HasUnusedModuleLeaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "import javax.inject.Named;",
+            "",
+            "@Subcomponent(modules = {a.Mod.class, b.Mod.class, c.Mod.class})",
+            "interface HasUnusedModuleLeaf {",
+            "  @Named(\"a\") int a();",
+            // b omitted intentionally
+            "  @Named(\"c\") int c();",
+            "",
+            "  @Subcomponent.Builder",
+            "  interface Builder {",
+            "    Builder setAMod(a.Mod mod);",
+            "    Builder setBMod(b.Mod mod);",
+            "    Builder setCMod(c.Mod mod);",
+            "    HasUnusedModuleLeaf build();",
+            "  }",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import a.Mod;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerHasUnusedModuleLeaf implements HasUnusedModuleLeaf {",
+            "  public abstract static class Builder implements HasUnusedModuleLeaf.Builder {",
+            "    protected Mod mod;",
+            "    protected b.Mod mod2;",
+            "    protected c.Mod mod3;",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerHasUnusedModuleLeaf")
+        .containsElementsIn(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface Root {",
+            "  HasUnusedModuleLeaf.Builder leaf();",
+            "}"));
+
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            "import a.Mod;",
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  private final class HasUnusedModuleLeafBuilder",
+            "      extends DaggerHasUnusedModuleLeaf.Builder {",
+            "    @Override",
+            "    public HasUnusedModuleLeaf build() {",
+            "      if (mod == null) {",
+            "        this.mod = new Mod();",
+            "      }",
+            // Before this regression was fixed, `mod3` was instead `mod2`, since the `b.Mod` was
+            // pruned from the graph and did not need validation.
+            "      if (mod3 == null) {",
+            "        this.mod3 = new c.Mod();",
+            "      }",
+            "      return new HasUnusedModuleLeafImpl(mod, mod3);",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .containsElementsIn(generatedRoot);
+  }
+
+  @Test
+  public void dependencyExpressionCasting() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.PublicType",
+            "package test;",
+            "", //
+            "public class PublicType {}"),
+        JavaFileObjects.forSourceLines(
+            "test.ModifiableNonPublicSubclass",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class ModifiableNonPublicSubclass extends PublicType {",
+            "  @Inject ModifiableNonPublicSubclass() {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Parameterized",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class Parameterized<T extends PublicType> {",
+            "  @Inject Parameterized(T t) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  Parameterized<ModifiableNonPublicSubclass> parameterizedWithNonPublicSubtype();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  @Override",
+            "  public Parameterized<ModifiableNonPublicSubclass> ",
+            "      parameterizedWithNonPublicSubtype() {",
+            "    return Parameterized_Factory.newInstance(",
+            "        (ModifiableNonPublicSubclass) getModifiableNonPublicSubclass());",
+            "  }",
+            "",
+            "  protected Object getModifiableNonPublicSubclass() {",
+            "    return new ModifiableNonPublicSubclass();",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .containsElementsIn(generatedLeaf);
+  }
+
+  @Test
+  public void multipleComponentMethodsForSameBindingRequest() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  String string1();",
+            "  String string2();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  @Override",
+            "  public final String string2() {",
+            "    return string1();",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .containsElementsIn(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.RootModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "interface RootModule {",
+            "  @Provides",
+            "  static String string() {",
+            "    return new String();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = RootModule.class)",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"));
+
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  protected final class LeafImpl extends DaggerLeaf {",
+            "    private LeafImpl() {}",
+            "",
+            "    @Override",
+            "    public String string1() {",
+            "      return RootModule_StringFactory.string();",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .containsElementsIn(generatedRoot);
+  }
+
+  @Test
+  public void boundInstanceUsedOnlyInInitialize() {
+    JavaFileObject subcomponent =
+        JavaFileObjects.forSourceLines(
+            "test.Sub",
+            "package test;",
+            "",
+            "import dagger.BindsInstance;",
+            "import dagger.Subcomponent;",
+            "import javax.inject.Provider;",
+            "",
+            "@Subcomponent",
+            "interface Sub {",
+            "  Provider<String> stringProvider();",
+            "",
+            "  @Subcomponent.Builder",
+            "  interface Builder {",
+            "    @BindsInstance",
+            "    Builder string(String string);",
+            "    Sub build();",
+            "  }",
+            "}");
+
+    JavaFileObject generated  =
+        JavaFileObjects.forSourceLines(
+            "test.Sub",
+            "package test;",
+            "",
+            "import dagger.internal.InstanceFactory;",
+            "import dagger.internal.Preconditions;",
+            IMPORT_GENERATED_ANNOTATION,
+            "import javax.inject.Provider;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerSub implements Sub {",
+            "  private Provider<String> stringProvider;",
+            "",
+            "  protected DaggerSub() {}",
+            "",
+            "  protected void configureInitialization(String stringParam) {",
+            "    initialize(stringParam);",
+            "  }",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize(final String stringParam) {",
+            "    this.stringProvider = InstanceFactory.create(stringParam);",
+            "  }",
+            "",
+            "  @Override",
+            "  public Provider<String> stringProvider() {",
+            "    return stringProvider;",
+            "  }",
+            "}");
+
+    Compilation compilation = compile(ImmutableList.of(subcomponent));
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerSub")
+        .containsElementsIn(generated);
+  }
+
+  @Test
+  public void packagePrivate_derivedFromFrameworkInstance_ComponentMethod() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.PackagePrivate",
+            "package test;",
+            "",
+            "import dagger.Reusable;",
+            "import javax.inject.Inject;",
+            "",
+            "@Reusable", // Use @Reusable to force a framework field
+            "class PackagePrivate {",
+            "  @Inject PackagePrivate() {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface Leaf {",
+            "  PackagePrivate packagePrivate();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  private Provider<PackagePrivate> packagePrivateProvider;",
+            "",
+            "  @Override",
+            "  public PackagePrivate packagePrivate() {",
+            "    return (PackagePrivate) getPackagePrivateProvider().get();",
+            "  }",
+            "",
+            "  protected Provider getPackagePrivateProvider() {",
+            "    return packagePrivateProvider;",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .containsElementsIn(generatedLeaf);
+  }
+
+  @Test
+  public void castModifiableMethodAccessedInFinalImplementation() {
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "PackagePrivate");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.PublicBaseType",
+            "package test;",
+            "", //
+            "public class PublicBaseType {}"),
+        JavaFileObjects.forSourceLines(
+            "test.PackagePrivateSubtype",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            // Force this to be a modifiable binding resolved in the ancestor even though the
+            // binding is requested in the leaf.
+            "@AncestorScope",
+            "class PackagePrivateSubtype extends PublicBaseType {",
+            "  @Inject PackagePrivateSubtype() {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorScope",
+            "package test;",
+            "",
+            "import javax.inject.Scope;",
+            "",
+            "@Scope @interface AncestorScope {}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.Binds;",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Module;",
+            "",
+            "@Module",
+            "interface LeafModule {",
+            "  @Binds PublicBaseType publicBaseType(PackagePrivateSubtype subtype);",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.InjectsOptionalOfModifiable",
+            "package test;",
+            "",
+            "import java.util.Optional;",
+            "import javax.inject.Inject;",
+            "",
+            "class InjectsOptionalOfModifiable {",
+            "  @Inject InjectsOptionalOfModifiable(",
+            "      Optional<PublicBaseType> optionalOfModifiable) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  InjectsOptionalOfModifiable injectsOptionalOfModifiable();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf {",
+            "  protected abstract Optional<PublicBaseType> getOptionalOfPublicBaseType();",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .containsElementsIn(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.InjectsPackagePrivateSubtype",
+            "package test;",
+            "",
+            "import java.util.Optional;",
+            "import javax.inject.Inject;",
+            "",
+            "class InjectsPackagePrivateSubtype {",
+            "  @Inject InjectsPackagePrivateSubtype(",
+            //     Force a modifiable binding method for PackagePrivateSubtype in Ancestor. The
+            //     final Leaf implementation will refer to this method, but will need to cast it
+            //     since the PackagePrivateSubtype is accessible from the current package, but the
+            //     method returns Object
+            "      PackagePrivateSubtype packagePrivateSubtype) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.AncestorModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "interface AncestorModule {",
+            "  @Provides",
+            "  static PackagePrivateSubtype packagePrivateSubtype() {",
+            "    return new PackagePrivateSubtype();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Ancestor",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@AncestorScope",
+            "@Subcomponent",
+            "interface Ancestor {",
+            "  InjectsPackagePrivateSubtype injectsPackagePrivateSubtype();",
+            "  Leaf leaf();",
+            "}"));
+
+    JavaFileObject generatedAncestor =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerAncestor",
+            "package test;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerAncestor implements Ancestor {",
+            "  protected Object getPackagePrivateSubtype() {",
+            "    return getPackagePrivateSubtypeProvider().get();",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerAncestor")
+        .containsElementsIn(generatedAncestor);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.RootModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Module;",
+            "",
+            "@Module",
+            "interface RootModule {",
+            "  @BindsOptionalOf",
+            "  PublicBaseType optionalPublicBaseType();",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = RootModule.class)",
+            "interface Root {",
+            "  Ancestor ancestor();",
+            "}"));
+
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root {",
+            "  protected final class AncestorImpl extends DaggerAncestor {",
+            "    protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
+            "      @Override",
+            "      protected Optional<PublicBaseType> getOptionalOfPublicBaseType() {",
+            "        return Optional.of(",
+            "            (PublicBaseType) AncestorImpl.this.getPackagePrivateSubtype());",
+            "      }",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .containsElementsIn(generatedRoot);
+  }
+
+  @Test
+  public void injectInLeaf_ProductionInRoot() {
+    // most of this is also covered in ProducesMethodShadowsInjectConstructorTest, but this test
+    // asserts that the correct PrunedConcreteBindingExpression is used
+    ImmutableList.Builder<JavaFileObject> filesToCompile = ImmutableList.builder();
+    createSimplePackagePrivateClasses(filesToCompile, "Dependency", "Missing");
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.Injected",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "class Injected {",
+            "  @Inject Injected(Dependency dependency, Missing missing) {}",
+            "",
+            "  Injected(Dependency dependency) {}",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.LeafModule",
+            "package test;",
+            "",
+            "import dagger.producers.ProducerModule;",
+            "import dagger.producers.Produces;",
+            "",
+            "@ProducerModule",
+            "interface LeafModule {",
+            "  @Produces",
+            "  static Object dependsOnInjectReplacedWithProduces(Injected injected) {",
+            "    return new Object();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Leaf",
+            "package test;",
+            "",
+            "import dagger.producers.Producer;",
+            "import dagger.producers.ProductionSubcomponent;",
+            "",
+            "@ProductionSubcomponent(modules = LeafModule.class)",
+            "interface Leaf {",
+            "  Producer<Object> objectProducer();",
+            "}"));
+
+    JavaFileObject generatedLeaf =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerLeaf",
+            "package test;",
+            "",
+            GENERATION_OPTIONS_ANNOTATION,
+            GENERATED_ANNOTATION,
+            "public abstract class DaggerLeaf implements Leaf, CancellationListener {",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.injectedProvider = Injected_Factory.create(",
+            "        getDependencyProvider(), getMissingProvider());",
+            "    this.injectedProducer = Producers.producerFromProvider(getInjectedProvider());",
+            "    this.dependsOnInjectReplacedWithProducesProducer =",
+            "        LeafModule_DependsOnInjectReplacedWithProducesFactory.create(",
+            "            getProductionImplementationExecutorProvider(),",
+            "            getProductionComponentMonitorProvider(),",
+            "            getInjectedProducer());",
+            "    this.objectProducerEntryPoint =",
+            "        Producers.entryPointViewOf(",
+            "            dependsOnInjectReplacedWithProducesProducer, this);",
+            "  }",
+            "",
+            "  protected abstract Provider getDependencyProvider();",
+            "  protected abstract Provider getMissingProvider();",
+            "",
+            "  protected Provider getInjectedProvider() {",
+            "    return injectedProvider;",
+            "  }",
+            "",
+            "  protected Producer getInjectedProducer() {",
+            "    return injectedProducer;",
+            "  }",
+            "}");
+    Compilation compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerLeaf")
+        .containsElementsIn(generatedLeaf);
+
+    filesToCompile.add(
+        JavaFileObjects.forSourceLines(
+            "test.RootModule",
+            "package test;",
+            "",
+            "import com.google.common.util.concurrent.MoreExecutors;",
+            "import dagger.Provides;",
+            "import dagger.producers.ProducerModule;",
+            "import dagger.producers.Produces;",
+            "import dagger.producers.Production;",
+            "import java.util.concurrent.Executor;",
+            "",
+            "@ProducerModule",
+            "interface RootModule {",
+            "  @Produces",
+            "  static Injected replaceInjectWithProduces(Dependency dependency) {",
+            "    return new Injected(dependency);",
+            "  }",
+            "",
+            "  @Produces",
+            "  static Dependency dependency() {",
+            "    return new Dependency();",
+            "  }",
+            "",
+            "  @Provides",
+            "  @Production",
+            "  static Executor executor() {",
+            "    return MoreExecutors.directExecutor();",
+            "  }",
+            "}"),
+        JavaFileObjects.forSourceLines(
+            "test.Root",
+            "package test;",
+            "",
+            "import dagger.producers.ProductionComponent;",
+            "",
+            "@ProductionComponent(modules = RootModule.class)",
+            "interface Root {",
+            "  Leaf leaf();",
+            "}"));
+
+    JavaFileObject generatedRoot =
+        JavaFileObjects.forSourceLines(
+            "test.DaggerRoot",
+            "package test;",
+            "",
+            GENERATED_ANNOTATION,
+            "final class DaggerRoot implements Root, CancellationListener {",
+            "  private Producer<Dependency> dependencyProducer;",
+            "  private Producer<Injected> replaceInjectWithProducesProducer;",
+            "",
+            "  @SuppressWarnings(\"unchecked\")",
+            "  private void initialize() {",
+            "    this.productionImplementationExecutorProvider =",
+            "        DoubleCheck.provider((Provider) RootModule_ExecutorFactory.create());",
+            "    this.rootProvider = InstanceFactory.create((Root) this);",
+            "    this.monitorProvider =",
+            "        DoubleCheck.provider(",
+            "            Root_MonitoringModule_MonitorFactory.create(",
+            "                rootProvider,",
+            "                SetFactory.<ProductionComponentMonitor.Factory>empty()));",
+            "    this.dependencyProducer =",
+            "        RootModule_DependencyFactory.create(",
+            "            productionImplementationExecutorProvider, monitorProvider);",
+            "    this.replaceInjectWithProducesProducer =",
+            "        RootModule_ReplaceInjectWithProducesFactory.create(",
+            "            productionImplementationExecutorProvider,",
+            "            monitorProvider,",
+            "            dependencyProducer);",
+            "  }",
+            "",
+            "  protected final class LeafImpl extends DaggerLeaf",
+            "      implements CancellationListener {",
+            "    @Override",
+            "    protected Provider getDependencyProvider() {",
+            "      return MissingBindingFactory.create();",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Provider getMissingProvider() {",
+            "      return MissingBindingFactory.create();",
+            "    }",
+            "",
+            "    @Override",
+            "    protected Producer getInjectedProducer() {",
+            "      return DaggerRoot.this.replaceInjectWithProducesProducer;",
+            "    }",
+            "  }",
+            "}");
+    compilation = compile(filesToCompile.build());
+    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerRoot")
+        .containsElementsIn(generatedRoot);
+  }
+
+  // TODO(ronshapiro): remove copies from AheadOfTimeSubcomponents*Test classes
+  private void createSimplePackagePrivateClasses(
+      ImmutableList.Builder<JavaFileObject> filesBuilder, String... ancillaryClasses) {
+    for (String className : ancillaryClasses) {
+      filesBuilder.add(
+          JavaFileObjects.forSourceLines(
+              String.format("test.%s", className),
+              "package test;",
+              "",
+              String.format("class %s { }", className)));
+    }
+  }
+
+  private static Compilation compile(Iterable<JavaFileObject> files, CompilerMode... modes) {
+    return compilerWithOptions(
+            ObjectArrays.concat(
+                new CompilerMode[] {AHEAD_OF_TIME_SUBCOMPONENTS_MODE}, modes, CompilerMode.class))
+        .compile(files);
+  }
+}
diff --git a/javatests/dagger/internal/codegen/AnnotationProtoConverterTest.java b/javatests/dagger/internal/codegen/AnnotationProtoConverterTest.java
new file mode 100644
index 0000000..fda5859
--- /dev/null
+++ b/javatests/dagger/internal/codegen/AnnotationProtoConverterTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 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.common.collect.Iterables.getOnlyElement;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.auto.common.AnnotationMirrors;
+import com.google.testing.compile.CompilationRule;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.lang.model.element.AnnotationMirror;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests {@link TypeProtoConverter}. */
+@RunWith(JUnit4.class)
+public class AnnotationProtoConverterTest {
+  @Rule public CompilationRule compilationRule = new CompilationRule();
+
+  private DaggerElements elements;
+  private DaggerTypes types;
+  private AnnotationProtoConverter annotationProtoConverter;
+
+  @Before
+  public void setUp() {
+    this.elements = new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
+    this.types = new DaggerTypes(compilationRule.getTypes(), elements);
+    this.annotationProtoConverter =
+        new AnnotationProtoConverter(new TypeProtoConverter(types, elements));
+  }
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @interface TestAnnotation {
+    byte b();
+    boolean bool();
+    short s();
+    char c();
+    int i();
+    long l();
+    double d();
+    float f();
+
+    String string();
+    RetentionPolicy enumValue();
+    Class<?> classValue();
+    HasDefaults[] nestedAnnotations();
+  }
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @interface HasDefaults {
+    int value() default 2;
+  }
+
+  @TestAnnotation(
+      b = 1,
+      bool = true,
+      s = 2,
+      c = 'c',
+      i = 4,
+      l = 5,
+      d = 6.0d,
+      f = 7.0f,
+      string = "hello, world",
+      enumValue = RetentionPolicy.CLASS,
+      classValue = AnnotationProtoConverter.class,
+      nestedAnnotations = {@HasDefaults, @HasDefaults(8)})
+  static class TestSubject {}
+
+  @Test
+  public void conversion() {
+    AnnotationMirror actual =
+        getOnlyElement(elements.getTypeElement(TestSubject.class).getAnnotationMirrors());
+    AnnotationMirror translated =
+        annotationProtoConverter.fromProto(AnnotationProtoConverter.toProto(actual));
+    assertThat(AnnotationMirrors.equivalence().equivalent(actual, translated)).isTrue();
+  }
+}
diff --git a/javatests/dagger/internal/codegen/AssistedErrorsTest.java b/javatests/dagger/internal/codegen/AssistedErrorsTest.java
deleted file mode 100644
index bf61412..0000000
--- a/javatests/dagger/internal/codegen/AssistedErrorsTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-
-import com.google.common.collect.ImmutableCollection;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class AssistedErrorsTest {
-  @Parameters(name = "{0}")
-  public static ImmutableCollection<Object[]> parameters() {
-    return CompilerMode.TEST_PARAMETERS;
-  }
-
-  private final CompilerMode compilerMode;
-
-  public AssistedErrorsTest(CompilerMode compilerMode) {
-    this.compilerMode = compilerMode;
-  }
-
-  @Test
-  public void testAssistedNotWithAssistedInjectionConstructor() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "",
-            "final class Foo {",
-            "  Foo(",
-            "      @Assisted String str",
-            "  ) {}",
-            "",
-            "  void someMethod(",
-            "      @Assisted int i",
-            "  ) {}",
-            "}");
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@Assisted parameters can only be used within an @AssistedInject-annotated constructor")
-        .inFile(foo)
-        .onLine(7);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@Assisted parameters can only be used within an @AssistedInject-annotated constructor")
-        .inFile(foo)
-        .onLine(11);
-  }
-
-  @Test
-  public void testNestedFactoryNotStatic() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import javax.inject.Qualifier;",
-            "",
-            "class Foo {",
-            "  @Qualifier @interface FooQualifier {}",
-            "",
-            "  @AssistedInject",
-            "  Foo(",
-            "      @FooQualifier @Assisted int i",
-            "  ) {}",
-            "}");
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("Qualifiers cannot be used with @Assisted parameters.")
-        .inFile(foo)
-        .onLine(12);
-  }
-}
diff --git a/javatests/dagger/internal/codegen/AssistedFactoryErrorsTest.java b/javatests/dagger/internal/codegen/AssistedFactoryErrorsTest.java
deleted file mode 100644
index 2bcfedc..0000000
--- a/javatests/dagger/internal/codegen/AssistedFactoryErrorsTest.java
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-
-import com.google.common.collect.ImmutableCollection;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class AssistedFactoryErrorsTest {
-  @Parameters(name = "{0}")
-  public static ImmutableCollection<Object[]> parameters() {
-    return CompilerMode.TEST_PARAMETERS;
-  }
-
-  private final CompilerMode compilerMode;
-
-  public AssistedFactoryErrorsTest(CompilerMode compilerMode) {
-    this.compilerMode = compilerMode;
-  }
-
-  @Test
-  public void testFactoryNotAbstract() {
-    JavaFileObject factory =
-        JavaFileObjects.forSourceLines(
-            "test.Factory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory class Factory {}");
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(factory);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "The @AssistedFactory-annotated type must be either an abstract class or interface.");
-  }
-
-  @Test
-  public void testNestedFactoryNotStatic() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(@Assisted int i) {}",
-            "",
-            "  @AssistedFactory",
-            "  abstract class Factory {",
-            "    abstract Foo create(int i);",
-            "  }",
-            "}");
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("Nested @AssistedFactory-annotated types must be static.");
-  }
-
-  @Test
-  public void testFactoryMissingAbstractMethod() {
-    JavaFileObject factory =
-        JavaFileObjects.forSourceLines(
-            "test.Factory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory interface Factory {}");
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(factory);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "The @AssistedFactory-annotated type is missing an abstract, non-default method whose"
-                + " return type matches the assisted injection type.");
-  }
-
-  @Test
-  public void testFactoryReturnsNonDeclaredType() {
-    JavaFileObject noInject =
-        JavaFileObjects.forSourceLines(
-            "test.NoInject", "package test;", "", "final class NoInject {}");
-    JavaFileObject noAssistedParam =
-        JavaFileObjects.forSourceLines(
-            "test.NoAssistedParam",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "final class NoAssistedParam {",
-            "  @AssistedInject NoAssistedParam() {}",
-            "}");
-    JavaFileObject factory =
-        JavaFileObjects.forSourceLines(
-            "test.Factory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory",
-            "interface Factory<T> {",
-            "  int createInt();", // Fails return type not @AssistedInject
-            "",
-            "  NoInject createNoInject();", // Fails return type not @AssistedInject
-            "",
-            "  NoAssistedParam createNoAssistedParam();", // Succeeds
-            "",
-            "  T createT();", // Fails return type not @AssistedInject
-            "}");
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(factory, noInject, noAssistedParam);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(4);
-
-    assertThat(compilation)
-        .hadErrorContaining(
-            "The @AssistedFactory-annotated type should contain a single abstract, non-default "
-                + "method but found multiple: ["
-                + "createInt(), createNoInject(), createNoAssistedParam(), createT()]")
-        .inFile(factory)
-        .onLine(6);
-
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Invalid return type: int. "
-                + "An assisted factory's abstract method must return a type with an "
-                + "@AssistedInject-annotated constructor.")
-        .inFile(factory)
-        .onLine(7);
-
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Invalid return type: test.NoInject. "
-                + "An assisted factory's abstract method must return a type with an "
-                + "@AssistedInject-annotated constructor.")
-        .inFile(factory)
-        .onLine(9);
-
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Invalid return type: T. "
-                + "An assisted factory's abstract method must return a type with an "
-                + "@AssistedInject-annotated constructor.")
-        .inFile(factory)
-        .onLine(13);
-  }
-
-  @Test
-  public void testFactoryMultipleAbstractMethods() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo {",
-            "  @AssistedInject Foo(@Assisted int i) {}",
-            "}");
-
-    JavaFileObject fooFactoryInterface =
-        JavaFileObjects.forSourceLines(
-            "test.FooFactoryInterface",
-            "package test;",
-            "",
-            "interface FooFactoryInterface {",
-            " Foo createFoo1(int i);",
-            "}");
-
-    JavaFileObject fooFactory =
-        JavaFileObjects.forSourceLines(
-            "test.FooFactory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory",
-            "interface FooFactory extends FooFactoryInterface {",
-            " Foo createFoo2(int i);",
-            "",
-            " Foo createFoo3(int i);",
-            "}");
-
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, fooFactory, fooFactoryInterface);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "The @AssistedFactory-annotated type should contain a single abstract, non-default "
-                + "method but found multiple: [createFoo1(int), createFoo2(int), createFoo3(int)]");
-  }
-
-  @Test
-  public void testFactoryMismatchingParameter() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo {",
-            "  @AssistedInject Foo(@Assisted int i) {}",
-            "}");
-
-    JavaFileObject fooFactory =
-        JavaFileObjects.forSourceLines(
-            "test.FooFactory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory",
-            "interface FooFactory {",
-            " Foo create(String i);",
-            "}");
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, fooFactory);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "The parameters in the factory method must match the @Assisted parameters in "
-                + "test.Foo.\n"
-                + "        Actual: test.FooFactory#create(java.lang.String)\n"
-                + "      Expected: test.FooFactory#create(int)");
-  }
-
-  @Test
-  public void testFactoryMismatchingGenericParameter() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo<T> {",
-            "  @AssistedInject Foo(@Assisted T t) {}",
-            "}");
-
-    JavaFileObject fooFactory =
-        JavaFileObjects.forSourceLines(
-            "test.FooFactory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory",
-            "interface FooFactory<T> {",
-            "  Foo<T> create(String str);",
-            "}");
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, fooFactory);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "The parameters in the factory method must match the @Assisted parameters in "
-                + "test.Foo<T>.\n"
-                + "        Actual: test.FooFactory#create(java.lang.String)\n"
-                + "      Expected: test.FooFactory#create(T)");
-  }
-
-  @Test
-  public void testFactoryDuplicateGenericParameter() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo<T> {",
-            "  @AssistedInject Foo(@Assisted String str, @Assisted T t) {}",
-            "}");
-
-    JavaFileObject fooFactory =
-        JavaFileObjects.forSourceLines(
-            "test.FooFactory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory",
-            "interface FooFactory {",
-            "  Foo<String> create(String str1, String str2);",
-            "}");
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, fooFactory);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@AssistedFactory method has duplicate @Assisted types: @Assisted java.lang.String");
-  }
-
-  @Test
-  public void testAssistedInjectionRequest() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo {",
-            "  @AssistedInject Foo(@Assisted String str) {}",
-            "}");
-
-    JavaFileObject bar =
-        JavaFileObjects.forSourceLines(
-            "test.Bar",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "import javax.inject.Provider;",
-            "",
-            "class Bar {",
-            "  @Inject",
-            "  Bar(Foo foo, Provider<Foo> fooProvider) {}",
-            "}");
-
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
-            "test.FooModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "import javax.inject.Provider;",
-            "",
-            "@Module",
-            "class FooModule {",
-            "  @Provides",
-            "  static int provideInt(Foo foo, Provider<Foo> fooProvider) {",
-            "    return 0;",
-            "  }",
-            "}");
-
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import javax.inject.Provider;",
-            "",
-            "@Component",
-            "interface FooComponent {",
-            "  Foo foo();",
-            "",
-            "  Provider<Foo> fooProvider();",
-            "}");
-
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, bar, module, component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(6);
-
-    String fooError =
-        "Dagger does not support injecting @AssistedInject type, test.Foo. "
-            + "Did you mean to inject its assisted factory type instead?";
-    assertThat(compilation).hadErrorContaining(fooError).inFile(bar).onLine(8);
-    assertThat(compilation).hadErrorContaining(fooError).inFile(module).onLine(10);
-    assertThat(compilation).hadErrorContaining(fooError).inFile(component).onLine(8);
-
-    String fooProviderError =
-        "Dagger does not support injecting @AssistedInject type, javax.inject.Provider<test.Foo>. "
-            + "Did you mean to inject its assisted factory type instead?";
-    assertThat(compilation).hadErrorContaining(fooProviderError).inFile(bar).onLine(8);
-    assertThat(compilation).hadErrorContaining(fooProviderError).inFile(module).onLine(10);
-    assertThat(compilation).hadErrorContaining(fooProviderError).inFile(component).onLine(10);
-  }
-
-  @Test
-  public void testProvidesAssistedBindings() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "class Foo {",
-            "  @AssistedInject Foo(@Assisted int i) {}",
-            "",
-            "  @AssistedFactory",
-            "  interface Factory {",
-            "    Foo create(int i);",
-            "  }",
-            "}");
-
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
-            "test.FooModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "import javax.inject.Provider;",
-            "",
-            "@Module",
-            "class FooModule {",
-            "  @Provides",
-            "  static Foo provideFoo() {",
-            "    return null;",
-            "  }",
-            "",
-            "  @Provides",
-            "  static Foo.Factory provideFooFactory() {",
-            "    return null;",
-            "  }",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo, module);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation)
-        .hadErrorContaining("[test.Foo] Dagger does not support providing @AssistedInject types.")
-        .inFile(module)
-        .onLine(10);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "[test.Foo.Factory] Dagger does not support providing @AssistedFactory types.")
-        .inFile(module)
-        .onLine(15);
-  }
-
-  @Test
-  public void testProvidesAssistedBindingsAsFactoryBindsInstance() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "class Foo {",
-            "  @AssistedInject Foo(@Assisted int i) {}",
-            "",
-            "  @AssistedFactory",
-            "  interface Factory {",
-            "    Foo create(int i);",
-            "  }",
-            "}");
-
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.BindsInstance;",
-            "",
-            "@Component",
-            "interface FooComponent {",
-            "  @Component.Factory",
-            "  interface Factory {",
-            "    FooComponent create(",
-            "        @BindsInstance Foo foo,",
-            "        @BindsInstance Foo.Factory fooFactory);",
-            "  }",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo, component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation)
-        .hadErrorContaining("[test.Foo] Dagger does not support providing @AssistedInject types.")
-        .inFile(component)
-        .onLine(11);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "[test.Foo.Factory] Dagger does not support providing @AssistedFactory types.")
-        .inFile(component)
-        .onLine(12);
-  }
-
-  @Test
-  public void testProvidesAssistedBindingsAsBuilderBindsInstance() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "class Foo {",
-            "  @AssistedInject Foo(@Assisted int i) {}",
-            "",
-            "  @AssistedFactory",
-            "  interface Factory {",
-            "    Foo create(int i);",
-            "  }",
-            "}");
-
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.BindsInstance;",
-            "",
-            "@Component",
-            "interface FooComponent {",
-            "  @Component.Builder",
-            "  interface Builder {",
-            "    @BindsInstance Builder foo(Foo foo);",
-            "    @BindsInstance Builder fooFactory(Foo.Factory fooFactory);",
-            "    FooComponent build();",
-            "  }",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo, component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation)
-        .hadErrorContaining("[test.Foo] Dagger does not support providing @AssistedInject types.")
-        .inFile(component)
-        .onLine(10);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "[test.Foo.Factory] Dagger does not support providing @AssistedFactory types.")
-        .inFile(component)
-        .onLine(11);
-  }
-
-  @Test
-  public void testInjectsProviderOfAssistedFactory() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "class Foo {",
-            "  @AssistedInject Foo(@Assisted int i) {}",
-            "",
-            "  @AssistedFactory",
-            "  interface Factory {",
-            "    Foo create(int i);",
-            "  }",
-            "}");
-
-    JavaFileObject bar =
-        JavaFileObjects.forSourceLines(
-            "test.Bar",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "import javax.inject.Provider;",
-            "",
-            "class Bar {",
-            "  @Inject",
-            "  Bar(Foo.Factory fooFactory, Provider<Foo.Factory> fooFactoryProvider) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo, bar);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Dagger does not support injecting Provider<T>, Lazy<T>, Producer<T>, or Produced<T> "
-                + "when T is an @AssistedFactory-annotated type such as test.Foo.Factory")
-        .inFile(bar)
-        .onLine(8);
-  }
-
-  @Test
-  public void testScopedAssistedInjection() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import dagger.assisted.AssistedFactory;",
-            "import javax.inject.Singleton;",
-            "",
-            "@Singleton",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(@Assisted int i) {}",
-            "",
-            "  @AssistedFactory",
-            "  interface Factory {",
-            "    Foo create(int i);",
-            "  }",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("A type with an @AssistedInject-annotated constructor cannot be scoped")
-        .inFile(foo)
-        .onLine(8);
-  }
-
-  @Test
-  public void testMultipleInjectAnnotations() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import javax.inject.Inject;",
-            "",
-            "class Foo {",
-            "  @Inject",
-            "  @AssistedInject",
-            "  Foo(@Assisted int i) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Constructors cannot be annotated with both @Inject and @AssistedInject");
-  }
-
-  @Test
-  public void testAssistedInjectNotOnConstructor() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  void someMethod() {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-
-    // Note: this isn't actually a Dagger error, it's a javac error since @AssistedInject only
-    // targets constructors. However, it's good to have this test in case that ever changes.
-    assertThat(compilation)
-        .hadErrorContaining("annotation type not applicable to this kind of declaration")
-        .inFile(foo)
-        .onLine(6);
-  }
-
-  @Test
-  public void testAssistedInjectWithNoAssistedParametersIsNotInjectable() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class Foo {",
-            "  @Inject",
-            "  Foo(Bar bar) {}",
-            "}");
-
-    JavaFileObject bar =
-        JavaFileObjects.forSourceLines(
-            "test.Bar",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedInject;",
-            "import javax.inject.Inject;",
-            "",
-            "class Bar {",
-            "  @AssistedInject",
-            "  Bar() {}",
-            "}");
-
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface FooComponent {",
-            "  Foo foo();",
-            "}");
-
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, bar, component);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "Dagger does not support injecting @AssistedInject type, test.Bar. "
-                + "Did you mean to inject its assisted factory type instead?")
-        .inFile(foo)
-        .onLine(7);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "\033[1;31m[Dagger/MissingBinding]\033[0m "
-                + "Foo cannot be provided without an @Inject constructor or an @Provides-annotated "
-                + "method.");
-  }
-
-  @Test
-  public void testInaccessibleFoo() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.subpackage.InaccessibleFoo",
-            "package test.subpackage;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class InaccessibleFoo {",
-            "  @AssistedInject InaccessibleFoo(@Assisted int i) {}",
-            "}");
-
-    JavaFileObject fooFactory =
-        JavaFileObjects.forSourceLines(
-            "test.subpackage.InaccessibleFooFactory",
-            "package test.subpackage;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory",
-            "public interface InaccessibleFooFactory {",
-            "  InaccessibleFoo create(int i);",
-            "}");
-
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.FooFactoryComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import test.subpackage.InaccessibleFooFactory;",
-            "",
-            "@Component",
-            "interface FooFactoryComponent {",
-            "  InaccessibleFooFactory inaccessibleFooFactory();",
-            "}");
-
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, fooFactory, component);
-
-    if (compilerMode == CompilerMode.FAST_INIT_MODE) {
-      // TODO(bcorso): Remove once we fix inaccessible assisted factory imlementation for fastInit.
-      assertThat(compilation).failed();
-      assertThat(compilation).hadErrorCount(1);
-      assertThat(compilation)
-          .hadErrorContaining(
-              "test.subpackage.InaccessibleFoo is not public in test.subpackage; cannot be "
-                  + "accessed from outside package");
-    } else {
-      assertThat(compilation).succeeded();
-    }
-  }
-
-  @Test
-  public void testAssistedFactoryMethodWithTypeParametersFails() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedInject;",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "class Foo<T> {",
-            "  @AssistedInject",
-            "  Foo() {}",
-            "",
-            "  @AssistedFactory",
-            "  interface FooFactory {",
-            "    <T> Foo<T> create();",
-            "  }",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@AssistedFactory does not currently support type parameters in the creator method.")
-        .inFile(foo)
-        .onLine(12);
-  }
-}
diff --git a/javatests/dagger/internal/codegen/AssistedFactoryTest.java b/javatests/dagger/internal/codegen/AssistedFactoryTest.java
deleted file mode 100644
index d752321..0000000
--- a/javatests/dagger/internal/codegen/AssistedFactoryTest.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
-import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
-
-import com.google.common.collect.ImmutableCollection;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class AssistedFactoryTest {
-  @Parameters(name = "{0}")
-  public static ImmutableCollection<Object[]> parameters() {
-    return CompilerMode.TEST_PARAMETERS;
-  }
-
-  private final CompilerMode compilerMode;
-
-  public AssistedFactoryTest(CompilerMode compilerMode) {
-    this.compilerMode = compilerMode;
-  }
-
-  @Test
-  public void testAssistedFactory() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(@Assisted String str, Bar bar) {}",
-            "}");
-    JavaFileObject fooFactory =
-        JavaFileObjects.forSourceLines(
-            "test.FooFactory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory",
-            "interface FooFactory {",
-            "  Foo create(String factoryStr);",
-            "}");
-    JavaFileObject bar =
-        JavaFileObjects.forSourceLines(
-            "test.Bar",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class Bar {",
-            "  @Inject Bar() {}",
-            "}");
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface TestComponent {",
-            "  FooFactory fooFactory();",
-            "}");
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, bar, fooFactory, component);
-    assertThat(compilation).succeeded();
-    JavaFileObject generatedComponent =
-        compilerMode
-            .javaFileBuilder("test.DaggerTestComponent")
-            .addLines("package test;", "", GENERATED_CODE_ANNOTATIONS)
-            .addLinesIn(
-                FAST_INIT_MODE,
-                "final class DaggerTestComponent implements TestComponent {",
-                "",
-                "  private Foo foo(String str) {",
-                "    return new Foo(str, new Bar());",
-                "  }",
-                "",
-                "  @Override",
-                "  public FooFactory fooFactory() {",
-                "    return new FooFactory() {",
-                "      @Override",
-                "      public Foo create(String str) {",
-                "        return DaggerTestComponent.this.foo(str);",
-                "      }",
-                "    };",
-                "  }",
-                "}")
-            .addLinesIn(
-                DEFAULT_MODE,
-                "final class DaggerTestComponent implements TestComponent {",
-                "",
-                "  private Foo_Factory fooProvider;",
-                "",
-                "  private Provider<FooFactory> fooFactoryProvider;",
-                "",
-                "  @SuppressWarnings(\"unchecked\")",
-                "  private void initialize() {",
-                "    this.fooProvider = Foo_Factory.create(Bar_Factory.create());",
-                "    this.fooFactoryProvider = FooFactory_Impl.create(fooProvider);",
-                "  }",
-                "",
-                "  @Override",
-                "  public FooFactory fooFactory() {",
-                "    return fooFactoryProvider.get();",
-                "  }",
-                "}")
-            .build();
-    assertThat(compilation)
-        .generatedSourceFile("test.DaggerTestComponent")
-        .containsElementsIn(generatedComponent);
-  }
-
-  @Test
-  public void testAssistedFactoryCycle() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(@Assisted String str, Bar bar) {}",
-            "}");
-    JavaFileObject fooFactory =
-        JavaFileObjects.forSourceLines(
-            "test.FooFactory",
-            "package test;",
-            "",
-            "import dagger.assisted.AssistedFactory;",
-            "",
-            "@AssistedFactory",
-            "interface FooFactory {",
-            "  Foo create(String factoryStr);",
-            "}");
-    JavaFileObject bar =
-        JavaFileObjects.forSourceLines(
-            "test.Bar",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class Bar {",
-            "  @Inject Bar(FooFactory fooFactory) {}",
-            "}");
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface TestComponent {",
-            "  FooFactory fooFactory();",
-            "}");
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(foo, bar, fooFactory, component);
-    assertThat(compilation).succeeded();
-    JavaFileObject generatedComponent =
-        compilerMode
-            .javaFileBuilder("test.DaggerTestComponent")
-            .addLines("package test;", "", GENERATED_CODE_ANNOTATIONS)
-            .addLinesIn(
-                FAST_INIT_MODE,
-                "final class DaggerTestComponent implements TestComponent {",
-                "",
-                "  private Bar bar() {",
-                "    return new Bar(fooFactory());",
-                "  }",
-                "",
-                "  private Foo foo(String str) {",
-                "    return new Foo(str, bar());",
-                "  }",
-                "",
-                "  @Override",
-                "  public FooFactory fooFactory() {",
-                "    return new FooFactory() {",
-                "      @Override",
-                "      public Foo create(String str) {",
-                "        return DaggerTestComponent.this.foo(str);",
-                "      }",
-                "    };",
-                "  }",
-                "}")
-            .addLinesIn(
-                DEFAULT_MODE,
-                "final class DaggerTestComponent implements TestComponent {",
-                "",
-                "  private Provider<FooFactory> fooFactoryProvider;",
-                "",
-                "  private Provider<Bar> barProvider;",
-                "",
-                "  private Foo_Factory fooProvider;",
-                "",
-                "  @SuppressWarnings(\"unchecked\")",
-                "  private void initialize() {",
-                "    this.fooFactoryProvider = new DelegateFactory<>();",
-                "    this.barProvider = Bar_Factory.create(fooFactoryProvider);",
-                "    this.fooProvider = Foo_Factory.create(barProvider);",
-                "    DelegateFactory.setDelegate(",
-                "        fooFactoryProvider, FooFactory_Impl.create(fooProvider));",
-                "  }",
-                "",
-                "  @Override",
-                "  public FooFactory fooFactory() {",
-                "    return fooFactoryProvider.get();",
-                "  }",
-                "}")
-            .build();
-    assertThat(compilation)
-        .generatedSourceFile("test.DaggerTestComponent")
-        .containsElementsIn(generatedComponent);
-  }
-}
diff --git a/javatests/dagger/internal/codegen/AssistedInjectErrorsTest.java b/javatests/dagger/internal/codegen/AssistedInjectErrorsTest.java
deleted file mode 100644
index 47e2171..0000000
--- a/javatests/dagger/internal/codegen/AssistedInjectErrorsTest.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-
-import com.google.common.collect.ImmutableCollection;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class AssistedInjectErrorsTest {
-  @Parameters(name = "{0}")
-  public static ImmutableCollection<Object[]> parameters() {
-    return CompilerMode.TEST_PARAMETERS;
-  }
-
-  private final CompilerMode compilerMode;
-
-  public AssistedInjectErrorsTest(CompilerMode compilerMode) {
-    this.compilerMode = compilerMode;
-  }
-
-  @Test
-  public void testAssistedInjectWithDuplicateTypesFails() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(@Assisted String str1, @Assisted String str2) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@AssistedInject constructor has duplicate @Assisted type: @Assisted java.lang.String")
-        .inFile(foo)
-        .onLine(8);
-  }
-
-  @Test
-  public void testAssistedInjectWithDuplicateTypesEmptyQualifierFails() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(@Assisted(\"\") String str1, @Assisted String str2) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@AssistedInject constructor has duplicate @Assisted type: @Assisted java.lang.String")
-        .inFile(foo)
-        .onLine(8);
-  }
-
-  @Test
-  public void testAssistedInjectWithDuplicateQualifiedTypesFails() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo<T> {",
-            "  @AssistedInject",
-            "  Foo(@Assisted(\"MyQualfier\") String s1, @Assisted(\"MyQualfier\") String s2) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@AssistedInject constructor has duplicate @Assisted type: "
-                + "@Assisted(\"MyQualfier\") java.lang.String")
-        .inFile(foo)
-        .onLine(8);
-  }
-
-  @Test
-  public void testAssistedInjectWithDuplicateGenericTypesFails() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import java.util.List;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(@Assisted List<String> list1, @Assisted List<String> list2) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@AssistedInject constructor has duplicate @Assisted type: "
-                + "@Assisted java.util.List<java.lang.String>")
-        .inFile(foo)
-        .onLine(9);
-  }
-
-  @Test
-  public void testAssistedInjectWithDuplicateParameterizedTypesFails() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "",
-            "class Foo<T> {",
-            "  @AssistedInject",
-            "  Foo(@Assisted T t1, @Assisted T t2) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("@AssistedInject constructor has duplicate @Assisted type: @Assisted T")
-        .inFile(foo)
-        .onLine(8);
-  }
-
-  @Test
-  public void testAssistedInjectWithUniqueParameterizedTypesPasses() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import java.util.List;",
-            "",
-            "class Foo<T1, T2> {",
-            "  @AssistedInject",
-            "  Foo(@Assisted T1 t1, @Assisted T2 t2) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).succeeded();
-  }
-
-  @Test
-  public void testAssistedInjectWithUniqueGenericTypesPasses() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import java.util.List;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(@Assisted List<String> list1, @Assisted List<Integer> list2) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).succeeded();
-  }
-
-  @Test
-  public void testAssistedInjectWithUniqueQualifiedTypesPasses() {
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "test.Foo",
-            "package test;",
-            "",
-            "import dagger.assisted.Assisted;",
-            "import dagger.assisted.AssistedInject;",
-            "import java.util.List;",
-            "",
-            "class Foo {",
-            "  @AssistedInject",
-            "  Foo(",
-            "      @Assisted(\"1\") Integer i1,",
-            "      @Assisted(\"1\") String s1,",
-            "      @Assisted(\"2\") String s2,",
-            "      @Assisted String s3) {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(foo);
-    assertThat(compilation).succeeded();
-  }
-}
diff --git a/javatests/dagger/internal/codegen/BUILD b/javatests/dagger/internal/codegen/BUILD
index 979ae71..ad214ff 100644
--- a/javatests/dagger/internal/codegen/BUILD
+++ b/javatests/dagger/internal/codegen/BUILD
@@ -15,84 +15,42 @@
 # Description:
 #   Tests for the Dagger compiler/codegen
 
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
+package(default_visibility = ["//:src"])
+
 load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
-kt_jvm_library(
-    name = "kotlin_sources",
-    srcs = [
-        "KotlinInjectedQualifier.kt",
-        "KotlinObjectWithMemberInjection.kt",
-    ],
-    deps = [
-        "//java/dagger:core",
-    ],
-)
-
-# TODO(bcorso): Move this into a subpackage.
-java_library(
-    name = "compilers",
-    srcs = [
-        "CompilerMode.java",
-        "Compilers.java",
-        "JavaFileBuilder.java",
-    ],
-    deps = [
-        "//java/dagger/internal/codegen:package_info",
-        "//java/dagger/internal/codegen:processor",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "@com_google_auto_value_auto_value//jar",
-        "@google_bazel_common//third_party/java/compile_testing",
-    ],
-)
-
 GenJavaTests(
     name = "compiler_tests",
-    srcs = glob(
-        ["*.java"],
-        exclude = [
-            "CompilerMode.java",
-            "Compilers.java",
-            "JavaFileBuilder.java",
-        ],
-    ),
+    srcs = glob(["*.java"]),
     functional = False,
     javacopts = DOCLINT_HTML_AND_SYNTAX,
-    plugins = ["//java/dagger/internal/codegen/bootstrap"],
     deps = [
-        ":compilers",
-        ":kotlin_sources",
         "//java/dagger:core",
-        "//java/dagger/internal/codegen:package_info",
+        "//java/dagger/internal/codegen:base",
+        "//java/dagger/internal/codegen:binding",
+        "//java/dagger/internal/codegen:binding_graph_validation",
         "//java/dagger/internal/codegen:processor",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/bindinggraphvalidation",
-        "//java/dagger/internal/codegen/compileroption",
+        "//java/dagger/internal/codegen:validation",
+        "//java/dagger/internal/codegen:writing",
         "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
         "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/codegen/validation",
-        "//java/dagger/internal/codegen/writing",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
+        "//java/dagger/internal/codegen/serialization",
+        "//java/dagger/model",
         "//java/dagger/model/testing",
         "//java/dagger/producers",
         "//java/dagger/spi",
-        "@com_google_auto_value_auto_value//jar",
+        "@com_google_auto_value_auto_value//jar",  # For AutoAnnotationProcessor
+        "@google_bazel_common//third_party/java/auto:common",
         "@google_bazel_common//third_party/java/auto:value",
         "@google_bazel_common//third_party/java/compile_testing",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/javapoet",
         "@google_bazel_common//third_party/java/jsr250_annotations",
         "@google_bazel_common//third_party/java/jsr330_inject",
         "@google_bazel_common//third_party/java/junit",
         "@google_bazel_common//third_party/java/mockito",
         "@google_bazel_common//third_party/java/truth",
-        "@maven//:com_google_auto_auto_common",
+        "@google_bazel_common//third_party/java/truth:truth8",
     ],
 )
diff --git a/javatests/dagger/internal/codegen/BindsDependsOnSubcomponentValidationTest.java b/javatests/dagger/internal/codegen/BindsDependsOnSubcomponentValidationTest.java
deleted file mode 100644
index aa01b3a..0000000
--- a/javatests/dagger/internal/codegen/BindsDependsOnSubcomponentValidationTest.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.Compilers.daggerCompiler;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/**
- * Tests to make sure that delegate bindings where the impl depends on a binding in a subcomponent
- * properly fail. These are regression tests for b/147020838.
- */
-@RunWith(JUnit4.class)
-public class BindsDependsOnSubcomponentValidationTest {
-  @Test
-  public void testBinds() {
-    JavaFileObject parentComponent =
-        JavaFileObjects.forSourceLines(
-            "test.ParentComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component(modules = ParentModule.class)",
-            "interface ParentComponent {",
-            "  ChildComponent getChild();",
-            "}");
-    JavaFileObject parentModule =
-        JavaFileObjects.forSourceLines(
-            "test.ParentModule",
-            "package test;",
-            "",
-            "import dagger.Binds;",
-            "import dagger.Module;",
-            "",
-            "@Module",
-            "interface ParentModule {",
-            "  @Binds Foo bindFoo(FooImpl impl);",
-            "}");
-    JavaFileObject childComponent =
-        JavaFileObjects.forSourceLines(
-            "test.ChildComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent(modules = ChildModule.class)",
-            "interface ChildComponent {",
-            "  Foo getFoo();",
-            "}");
-    JavaFileObject childModule =
-        JavaFileObjects.forSourceLines(
-            "test.ChildModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "",
-            "@Module",
-            "interface ChildModule {",
-            "  @Provides static Long providLong() {",
-            "    return 0L;",
-            "  }",
-            "}");
-    JavaFileObject iface =
-        JavaFileObjects.forSourceLines("test.Foo", "package test;", "", "interface Foo {", "}");
-    JavaFileObject impl =
-        JavaFileObjects.forSourceLines(
-            "test.FooImpl",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class FooImpl implements Foo {",
-            "  @Inject FooImpl(Long l) {}",
-            "}");
-    Compilation compilation =
-        daggerCompiler()
-            .compile(parentComponent, parentModule, childComponent, childModule, iface, impl);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("Long cannot be provided without an @Inject constructor")
-        .inFile(parentComponent)
-        .onLineContaining("interface ParentComponent");
-  }
-
-  @Test
-  public void testSetBindings() {
-    JavaFileObject parentComponent =
-        JavaFileObjects.forSourceLines(
-            "test.ParentComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component(modules = ParentModule.class)",
-            "interface ParentComponent {",
-            "  ChildComponent getChild();",
-            "}");
-    JavaFileObject parentModule =
-        JavaFileObjects.forSourceLines(
-            "test.ParentModule",
-            "package test;",
-            "",
-            "import dagger.Binds;",
-            "import dagger.Module;",
-            "import dagger.multibindings.IntoSet;",
-            "",
-            "@Module",
-            "interface ParentModule {",
-            "  @Binds @IntoSet Foo bindFoo(FooImpl impl);",
-            "}");
-    JavaFileObject childComponent =
-        JavaFileObjects.forSourceLines(
-            "test.ChildComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "import java.util.Set;",
-            "",
-            "@Subcomponent(modules = ChildModule.class)",
-            "interface ChildComponent {",
-            "  Set<Foo> getFooSet();",
-            "}");
-    JavaFileObject childModule =
-        JavaFileObjects.forSourceLines(
-            "test.ChildModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "",
-            "@Module",
-            "interface ChildModule {",
-            "  @Provides static Long providLong() {",
-            "    return 0L;",
-            "  }",
-            "}");
-    JavaFileObject iface =
-        JavaFileObjects.forSourceLines("test.Foo", "package test;", "", "interface Foo {", "}");
-    JavaFileObject impl =
-        JavaFileObjects.forSourceLines(
-            "test.FooImpl",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class FooImpl implements Foo {",
-            "  @Inject FooImpl(Long l) {}",
-            "}");
-    Compilation compilation =
-        daggerCompiler()
-            .compile(parentComponent, parentModule, childComponent, childModule, iface, impl);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("Long cannot be provided without an @Inject constructor")
-        .inFile(parentComponent)
-        .onLineContaining("interface ParentComponent");
-  }
-
-  @Test
-  public void testSetValueBindings() {
-    JavaFileObject parentComponent =
-        JavaFileObjects.forSourceLines(
-            "test.ParentComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component(modules = ParentModule.class)",
-            "interface ParentComponent {",
-            "  ChildComponent getChild();",
-            "}");
-    JavaFileObject parentModule =
-        JavaFileObjects.forSourceLines(
-            "test.ParentModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "import dagger.multibindings.ElementsIntoSet;",
-            "import java.util.Collections;",
-            "import java.util.Set;",
-            "",
-            "@Module",
-            "interface ParentModule {",
-            "  @Provides @ElementsIntoSet",
-            "  static Set<Foo> provideFoo(FooImpl impl) {",
-            "    return Collections.singleton(impl);",
-            "  }",
-            "}");
-    JavaFileObject childComponent =
-        JavaFileObjects.forSourceLines(
-            "test.ChildComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "import java.util.Set;",
-            "",
-            "@Subcomponent(modules = ChildModule.class)",
-            "interface ChildComponent {",
-            "  Set<Foo> getFooSet();",
-            "}");
-    JavaFileObject childModule =
-        JavaFileObjects.forSourceLines(
-            "test.ChildModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "",
-            "@Module",
-            "interface ChildModule {",
-            "  @Provides static Long providLong() {",
-            "    return 0L;",
-            "  }",
-            "}");
-    JavaFileObject iface =
-        JavaFileObjects.forSourceLines("test.Foo", "package test;", "", "interface Foo {", "}");
-    JavaFileObject impl =
-        JavaFileObjects.forSourceLines(
-            "test.FooImpl",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class FooImpl implements Foo {",
-            "  @Inject FooImpl(Long l) {}",
-            "}");
-    Compilation compilation =
-        daggerCompiler()
-            .compile(parentComponent, parentModule, childComponent, childModule, iface, impl);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("Long cannot be provided without an @Inject constructor")
-        .inFile(parentComponent)
-        .onLineContaining("interface ParentComponent");
-  }
-
-  @Test
-  public void testMapBindings() {
-    JavaFileObject parentComponent =
-        JavaFileObjects.forSourceLines(
-            "test.ParentComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component(modules = ParentModule.class)",
-            "interface ParentComponent {",
-            "  ChildComponent getChild();",
-            "}");
-    JavaFileObject parentModule =
-        JavaFileObjects.forSourceLines(
-            "test.ParentModule",
-            "package test;",
-            "",
-            "import dagger.Binds;",
-            "import dagger.Module;",
-            "import dagger.multibindings.IntoMap;",
-            "import dagger.multibindings.StringKey;",
-            "",
-            "@Module",
-            "interface ParentModule {",
-            "  @Binds @IntoMap @StringKey(\"foo\") Foo bindFoo(FooImpl impl);",
-            "}");
-    JavaFileObject childComponent =
-        JavaFileObjects.forSourceLines(
-            "test.ChildComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "import java.util.Map;",
-            "",
-            "@Subcomponent(modules = ChildModule.class)",
-            "interface ChildComponent {",
-            "  Map<String, Foo> getFooSet();",
-            "}");
-    JavaFileObject childModule =
-        JavaFileObjects.forSourceLines(
-            "test.ChildModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "",
-            "@Module",
-            "interface ChildModule {",
-            "  @Provides static Long providLong() {",
-            "    return 0L;",
-            "  }",
-            "}");
-    JavaFileObject iface =
-        JavaFileObjects.forSourceLines("test.Foo", "package test;", "", "interface Foo {", "}");
-    JavaFileObject impl =
-        JavaFileObjects.forSourceLines(
-            "test.FooImpl",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class FooImpl implements Foo {",
-            "  @Inject FooImpl(Long l) {}",
-            "}");
-    Compilation compilation =
-        // TODO(erichang): make this flag the default and remove this
-        compilerWithOptions("-Adagger.strictMultibindingValidation=enabled")
-            .compile(parentComponent, parentModule, childComponent, childModule, iface, impl);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("Long cannot be provided without an @Inject constructor")
-        .inFile(parentComponent)
-        .onLineContaining("interface ParentComponent");
-  }
-}
diff --git a/javatests/dagger/internal/codegen/BindsMethodValidationTest.java b/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
index ab26010..6ba9e3e 100644
--- a/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
+++ b/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
@@ -25,6 +25,7 @@
 import dagger.multibindings.IntKey;
 import dagger.multibindings.LongKey;
 import dagger.producers.ProducerModule;
+import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Retention;
 import java.util.Collection;
@@ -78,8 +79,9 @@
 
   @Test
   public void throwsException() {
-    assertThatMethod("@Binds abstract Object throwsException(String s1) throws RuntimeException;")
-        .hasError("may not throw");
+    assertThatMethod("@Binds abstract Object throwsException(String s1) throws IOException;")
+        .importing(IOException.class)
+        .hasError("only throw unchecked");
   }
 
   @Test
diff --git a/javatests/dagger/internal/codegen/BindsMissingDelegateValidationTest.java b/javatests/dagger/internal/codegen/BindsMissingDelegateValidationTest.java
index bfc3617..28b75be 100644
--- a/javatests/dagger/internal/codegen/BindsMissingDelegateValidationTest.java
+++ b/javatests/dagger/internal/codegen/BindsMissingDelegateValidationTest.java
@@ -97,7 +97,7 @@
         .hadErrorContainingMatch(
             "\\Qtest.C.NotBound cannot be provided\\E|"
                 + message(
-                    "\\QObject is bound multiple times:",
+                    "\\Qjava.lang.Object is bound multiple times:",
                     "    @Binds Object test.C.TestModule.bindObject(test.C.NotBound)",
                     "    @Provides Object test.C.TestModule.provideObject()\\E"))
         .inFile(component)
diff --git a/javatests/dagger/internal/codegen/BindsOptionalOfMethodValidationTest.java b/javatests/dagger/internal/codegen/BindsOptionalOfMethodValidationTest.java
index ca3e5e4..fa44a6e 100644
--- a/javatests/dagger/internal/codegen/BindsOptionalOfMethodValidationTest.java
+++ b/javatests/dagger/internal/codegen/BindsOptionalOfMethodValidationTest.java
@@ -37,7 +37,7 @@
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-/** Tests {@link dagger.internal.codegen.validation.BindsOptionalOfMethodValidator}. */
+/** Tests {@link BindsOptionalOfMethodValidator}. */
 @RunWith(Parameterized.class)
 public class BindsOptionalOfMethodValidationTest {
   @Parameters(name = "{0}")
diff --git a/javatests/dagger/internal/codegen/CompilerMode.java b/javatests/dagger/internal/codegen/CompilerMode.java
index 86ce53d..23aa312 100644
--- a/javatests/dagger/internal/codegen/CompilerMode.java
+++ b/javatests/dagger/internal/codegen/CompilerMode.java
@@ -23,6 +23,9 @@
 enum CompilerMode {
   DEFAULT_MODE,
   FAST_INIT_MODE("-Adagger.fastInit=enabled"),
+  AHEAD_OF_TIME_SUBCOMPONENTS_MODE(
+      "-Adagger.experimentalAheadOfTimeSubcomponents=enabled",
+      "-Adagger.emitModifiableMetadataAnnotations=disabled"),
   JAVA7("-source", "7", "-target", "7"),
   ;
 
diff --git a/javatests/dagger/internal/codegen/Compilers.java b/javatests/dagger/internal/codegen/Compilers.java
index 26796bf..3e08f63 100644
--- a/javatests/dagger/internal/codegen/Compilers.java
+++ b/javatests/dagger/internal/codegen/Compilers.java
@@ -19,60 +19,42 @@
 import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_PATH;
 import static com.google.common.base.StandardSystemProperty.PATH_SEPARATOR;
 import static com.google.testing.compile.Compiler.javac;
-import static java.util.stream.Collectors.collectingAndThen;
-import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.joining;
 
 import com.google.auto.value.processor.AutoAnnotationProcessor;
 import com.google.common.base.Splitter;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.testing.compile.Compiler;
-import java.io.File;
-import java.util.Arrays;
 import javax.annotation.processing.Processor;
 
 /** {@link Compiler} instances for testing Dagger. */
-public final class Compilers {
+final class Compilers {
   private static final String GUAVA = "guava";
 
-  static final ImmutableList<File> CLASS_PATH_WITHOUT_GUAVA_OPTION =
-      Splitter.on(PATH_SEPARATOR.value()).splitToList(JAVA_CLASS_PATH.value()).stream()
-          .filter(jar -> !jar.contains(GUAVA))
-          // Remove Bazel's runner deploy jar which leaks Guava classes into the classpath and
-          // the compile testing tests.
-          .filter(jar -> !jar.contains("Runner_deploy.jar"))
-          .map(File::new)
-          .collect(collectingAndThen(toList(), ImmutableList::copyOf));
-
-  static final ImmutableList<String> DEFAULT_JAVACOPTS =
-      ImmutableList.of("-Adagger.experimentalDaggerErrorMessages=enabled");
+  static final ImmutableList<String> CLASS_PATH_WITHOUT_GUAVA_OPTION =
+      ImmutableList.of(
+          "-classpath",
+          Splitter.on(PATH_SEPARATOR.value()).splitToList(JAVA_CLASS_PATH.value()).stream()
+              .filter(jar -> !jar.contains(GUAVA))
+              .collect(joining(PATH_SEPARATOR.value())));
 
   /**
    * Returns a compiler that runs the Dagger and {@code @AutoAnnotation} processors, along with
    * extras.
    */
-  public static Compiler daggerCompiler(Processor... extraProcessors) {
+  static Compiler daggerCompiler(Processor... extraProcessors) {
     ImmutableList.Builder<Processor> processors = ImmutableList.builder();
     processors.add(new ComponentProcessor(), new AutoAnnotationProcessor());
     processors.add(extraProcessors);
-    return javac().withProcessors(processors.build()).withOptions(DEFAULT_JAVACOPTS);
+    return javac().withProcessors(processors.build());
   }
 
-  public static Compiler compilerWithOptions(CompilerMode... compilerModes) {
-    ImmutableList.Builder<String> options = ImmutableList.builder();
+  static Compiler compilerWithOptions(CompilerMode... compilerModes) {
+    FluentIterable<String> options = FluentIterable.of();
     for (CompilerMode compilerMode : compilerModes) {
-      options = options.addAll(compilerMode.javacopts());
+      options = options.append(compilerMode.javacopts());
     }
-    return compilerWithOptions(options.build());
+    return daggerCompiler().withOptions(options);
   }
-
-  public static Compiler compilerWithOptions(String... options) {
-    return compilerWithOptions(Arrays.asList(options));
-  }
-
-  public static Compiler compilerWithOptions(Iterable<String> options) {
-    return daggerCompiler()
-        .withOptions(ImmutableList.builder().addAll(DEFAULT_JAVACOPTS).addAll(options).build());
-  }
-
-  private Compilers() {}
 }
diff --git a/javatests/dagger/internal/codegen/ComponentBuilderTest.java b/javatests/dagger/internal/codegen/ComponentBuilderTest.java
index acf5437..f280bdd 100644
--- a/javatests/dagger/internal/codegen/ComponentBuilderTest.java
+++ b/javatests/dagger/internal/codegen/ComponentBuilderTest.java
@@ -17,14 +17,13 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.COMPONENT_BUILDER;
-import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.COMPONENT_BUILDER;
+import static dagger.internal.codegen.ErrorMessages.creatorMessagesFor;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
-import dagger.internal.codegen.binding.ErrorMessages;
 import java.util.Collection;
 import javax.tools.JavaFileObject;
 import org.junit.Test;
@@ -88,7 +87,7 @@
             "",
             "import dagger.internal.Preconditions;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  private static final class Builder implements TestComponent.Builder {",
             "    private TestModule testModule;",
@@ -109,7 +108,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(moduleFile, componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(moduleFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerTestComponent")
@@ -136,7 +135,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(MSGS.setterMethodsMustTakeOneArg())
@@ -169,7 +168,7 @@
             "  interface Builder extends Parent {}",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
@@ -199,7 +198,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(MSGS.setterMethodsMustReturnVoidOrBuilder())
@@ -228,7 +227,7 @@
             "  interface Builder extends Parent {}",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
@@ -257,7 +256,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(MSGS.methodsMayNotHaveTypeParameters())
@@ -286,7 +285,7 @@
             "  interface Builder extends Parent {}",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
@@ -319,7 +318,7 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(MSGS.bindsInstanceNotAllowedOnBothSetterMethodAndParameter())
@@ -353,7 +352,7 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
diff --git a/javatests/dagger/internal/codegen/ComponentCreatorTest.java b/javatests/dagger/internal/codegen/ComponentCreatorTest.java
index 0a7e40e..6f4ea8d 100644
--- a/javatests/dagger/internal/codegen/ComponentCreatorTest.java
+++ b/javatests/dagger/internal/codegen/ComponentCreatorTest.java
@@ -16,27 +16,28 @@
 
 package dagger.internal.codegen;
 
-import static com.google.common.truth.TruthJUnit.assume;
+import static com.google.common.collect.Sets.immutableEnumSet;
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.ComponentCreatorTest.CompilerType.JAVAC;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.COMPONENT_BUILDER;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.COMPONENT_FACTORY;
+import static dagger.internal.codegen.ComponentCreatorKind.BUILDER;
+import static dagger.internal.codegen.ComponentCreatorKind.FACTORY;
+import static dagger.internal.codegen.ComponentKind.COMPONENT;
+import static dagger.internal.codegen.ErrorMessages.componentMessagesFor;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.COMPONENT_BUILDER;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.COMPONENT_FACTORY;
-import static dagger.internal.codegen.binding.ComponentCreatorKind.BUILDER;
-import static dagger.internal.codegen.binding.ComponentCreatorKind.FACTORY;
-import static dagger.internal.codegen.binding.ComponentKind.COMPONENT;
-import static dagger.internal.codegen.binding.ErrorMessages.componentMessagesFor;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
-import dagger.internal.codegen.binding.ComponentCreatorAnnotation;
 import java.util.Collection;
+import java.util.List;
+import java.util.Set;
 import javax.tools.JavaFileObject;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -46,34 +47,22 @@
 /** Tests for properties of component creators shared by both builders and factories. */
 @RunWith(Parameterized.class)
 public class ComponentCreatorTest extends ComponentCreatorTestHelper {
-  enum CompilerType {
-    JAVAC
-  }
-
-  private final CompilerType compilerType;
-  private final CompilerMode compilerMode;
-
   @Parameters(name = "compilerMode={0}, creatorKind={1}")
   public static Collection<Object[]> parameters() {
-    return ImmutableList.of(
-      new Object[]{DEFAULT_MODE, COMPONENT_BUILDER, JAVAC},
-      new Object[]{DEFAULT_MODE, COMPONENT_FACTORY, JAVAC},
-      new Object[]{FAST_INIT_MODE, COMPONENT_BUILDER, JAVAC},
-      new Object[]{FAST_INIT_MODE, COMPONENT_FACTORY, JAVAC});
+    Set<List<Object>> params =
+        Sets.<Object>cartesianProduct(
+            immutableEnumSet(DEFAULT_MODE, FAST_INIT_MODE),
+            immutableEnumSet(COMPONENT_BUILDER, COMPONENT_FACTORY));
+    return ImmutableList.copyOf(Iterables.transform(params, Collection::toArray));
   }
 
   public ComponentCreatorTest(
-      CompilerMode compilerMode,
-      ComponentCreatorAnnotation componentCreatorAnnotation,
-      CompilerType compilerType) {
+      CompilerMode compilerMode, ComponentCreatorAnnotation componentCreatorAnnotation) {
     super(compilerMode, componentCreatorAnnotation);
-    this.compilerMode = compilerMode;
-    this.compilerType = compilerType;
   }
 
   @Test
   public void testEmptyCreator() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject injectableTypeFile =
         JavaFileObjects.forSourceLines(
             "test.SomeInjectableType",
@@ -106,7 +95,7 @@
             "test.DaggerSimpleComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerSimpleComponent implements SimpleComponent {",
             "  private static final class Builder implements SimpleComponent.Builder {",
             "    @Override",
@@ -124,7 +113,6 @@
 
   @Test
   public void testCanInstantiateModulesUserCannotSet() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject module =
         JavaFileObjects.forSourceLines(
             "test.TestModule",
@@ -161,7 +149,7 @@
             "",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  private final TestModule testModule;",
             "",
@@ -322,7 +310,6 @@
 
   @Test
   public void testCreatorWithBindsInstanceNoStaticCreateGenerated() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject componentFile =
         javaFileBuilder("test.SimpleComponent")
             .addLines(
@@ -360,7 +347,7 @@
                 "import dagger.internal.Preconditions;",
                 IMPORT_GENERATED_ANNOTATION,
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {",
                 "  private final Object object;",
                 "",
@@ -423,7 +410,6 @@
 
   @Test
   public void testCreatorWithPrimitiveBindsInstance() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject componentFile =
         javaFileBuilder("test.SimpleComponent")
             .addLines(
@@ -462,7 +448,7 @@
                 "import dagger.internal.Preconditions;",
                 IMPORT_GENERATED_ANNOTATION,
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {",
                 "  private final Integer i;",
                 "",
@@ -793,7 +779,6 @@
 
   @Test
   public void testMultipleSettersPerTypeFails() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject moduleFile =
         JavaFileObjects.forSourceLines(
             "test.TestModule",
@@ -852,7 +837,6 @@
 
   @Test
   public void testMultipleSettersPerTypeIncludingResolvedGenericsFails() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject moduleFile =
         JavaFileObjects.forSourceLines(
             "test.TestModule",
@@ -916,7 +900,6 @@
 
   @Test
   public void testExtraSettersFails() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject componentFile =
         javaFileBuilder("test.SimpleComponent")
             .addLines(
@@ -1049,7 +1032,6 @@
 
   @Test
   public void covariantFactoryMethodReturnType() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject foo =
         JavaFileObjects.forSourceLines(
             "test.Foo",
@@ -1090,7 +1072,6 @@
 
   @Test
   public void covariantFactoryMethodReturnType_hasNewMethod() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject foo =
         JavaFileObjects.forSourceLines(
             "test.Foo",
@@ -1152,7 +1133,6 @@
 
   @Test
   public void covariantFactoryMethodReturnType_hasNewMethod_factoryMethodInherited() {
-    assume().that(compilerType).isEqualTo(JAVAC);
     JavaFileObject foo =
         JavaFileObjects.forSourceLines(
             "test.Foo",
@@ -1270,13 +1250,4 @@
         .inFile(componentFile)
         .onLineContaining(process("interface Builder"));
   }
-
-  /** Compiles the given files with the set compiler mode's javacopts. */
-  @Override
-  Compilation compile(JavaFileObject... files) {
-    ImmutableList.Builder<String> options =
-        ImmutableList.<String>builder().addAll(compilerMode.javacopts());
-
-    return compilerWithOptions(options.build()).compile(files);
-  }
 }
diff --git a/javatests/dagger/internal/codegen/ComponentCreatorTestHelper.java b/javatests/dagger/internal/codegen/ComponentCreatorTestHelper.java
index 8ad4322..2ee120e 100644
--- a/javatests/dagger/internal/codegen/ComponentCreatorTestHelper.java
+++ b/javatests/dagger/internal/codegen/ComponentCreatorTestHelper.java
@@ -16,16 +16,13 @@
 
 package dagger.internal.codegen;
 
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.binding.ComponentCreatorKind.FACTORY;
-import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.ComponentCreatorKind.FACTORY;
+import static dagger.internal.codegen.ErrorMessages.creatorMessagesFor;
 import static java.util.stream.Collectors.joining;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
-import dagger.internal.codegen.binding.ComponentCreatorAnnotation;
-import dagger.internal.codegen.binding.ComponentCreatorKind;
-import dagger.internal.codegen.binding.ErrorMessages;
 import java.util.Arrays;
 import java.util.stream.Stream;
 import javax.tools.JavaFileObject;
@@ -87,6 +84,6 @@
 
   /** Compiles the given files with the set compiler mode's javacopts. */
   Compilation compile(JavaFileObject... files) {
-    return compilerWithOptions(compilerMode.javacopts()).compile(files);
+    return daggerCompiler().withOptions(compilerMode.javacopts()).compile(files);
   }
 }
diff --git a/javatests/dagger/internal/codegen/ComponentDependenciesTest.java b/javatests/dagger/internal/codegen/ComponentDependenciesTest.java
deleted file mode 100644
index bbfa51c..0000000
--- a/javatests/dagger/internal/codegen/ComponentDependenciesTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.daggerCompiler;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class ComponentDependenciesTest {
-  @Test
-  public void dependenciesWithTwoOfSameMethodOnDifferentInterfaces_fail() {
-    JavaFileObject interfaceOne = JavaFileObjects.forSourceLines("test.One",
-        "package test;",
-        "",
-        "interface One {",
-        "  String getOne();",
-        "}");
-    JavaFileObject interfaceTwo = JavaFileObjects.forSourceLines("test.Two",
-        "package test;",
-        "",
-        "interface Two {",
-        "  String getTwo();",
-        "}");
-    JavaFileObject mergedInterface = JavaFileObjects.forSourceLines("test.Merged",
-        "package test;",
-        "",
-        "interface Merged extends One, Two {}");
-    JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent",
-        "package test;",
-        "",
-        "import dagger.Component;",
-        "",
-        "@Component(dependencies = Merged.class)",
-        "interface TestComponent {",
-        "  String getString();",
-        "}");
-    Compilation compilation = daggerCompiler().compile(
-        interfaceOne, interfaceTwo, mergedInterface, componentFile);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorContaining("DuplicateBindings");
-  }
-
-  @Test
-  public void dependenciesWithTwoOfSameMethodOnDifferentInterfaces_producers_fail() {
-    JavaFileObject interfaceOne = JavaFileObjects.forSourceLines("test.One",
-        "package test;",
-        "",
-        "import com.google.common.util.concurrent.ListenableFuture;",
-        "",
-        "interface One {",
-        "  ListenableFuture<String> getOne();",
-        "}");
-    JavaFileObject interfaceTwo = JavaFileObjects.forSourceLines("test.Two",
-        "package test;",
-        "",
-        "import com.google.common.util.concurrent.ListenableFuture;",
-        "",
-        "interface Two {",
-        "  ListenableFuture<String> getTwo();",
-        "}");
-    JavaFileObject mergedInterface = JavaFileObjects.forSourceLines("test.Merged",
-        "package test;",
-        "",
-        "interface Merged extends One, Two {}");
-    JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent",
-        "package test;",
-        "",
-        "import com.google.common.util.concurrent.ListenableFuture;",
-        "import dagger.producers.ProductionComponent;",
-        "",
-        "@ProductionComponent(dependencies = Merged.class)",
-        "interface TestComponent {",
-        "  ListenableFuture<String> getString();",
-        "}");
-    Compilation compilation = daggerCompiler().compile(
-        interfaceOne, interfaceTwo, mergedInterface, componentFile);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorContaining("DuplicateBindings");
-  }
-
-  @Test
-  public void dependenciesWithTwoOfSameMethodButDifferentNullability_fail() {
-    JavaFileObject interfaceOne = JavaFileObjects.forSourceLines("test.One",
-        "package test;",
-        "",
-        "interface One {",
-        "  String getString();",
-        "}");
-    JavaFileObject interfaceTwo = JavaFileObjects.forSourceLines("test.Two",
-        "package test;",
-        "import javax.annotation.Nullable;",
-        "",
-        "interface Two {",
-        "  @Nullable String getString();",
-        "}");
-    JavaFileObject mergedInterface = JavaFileObjects.forSourceLines("test.Merged",
-        "package test;",
-        "",
-        "interface Merged extends One, Two {}");
-    JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent",
-        "package test;",
-        "",
-        "import dagger.Component;",
-        "",
-        "@Component(dependencies = Merged.class)",
-        "interface TestComponent {",
-        "  String getString();",
-        "}");
-    Compilation compilation = daggerCompiler().compile(
-        interfaceOne, interfaceTwo, mergedInterface, componentFile);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorContaining("DuplicateBindings");
-  }
-
-}
diff --git a/javatests/dagger/internal/codegen/ComponentFactoryTest.java b/javatests/dagger/internal/codegen/ComponentFactoryTest.java
index 0f155b9..403498b 100644
--- a/javatests/dagger/internal/codegen/ComponentFactoryTest.java
+++ b/javatests/dagger/internal/codegen/ComponentFactoryTest.java
@@ -17,14 +17,13 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.COMPONENT_FACTORY;
-import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.COMPONENT_FACTORY;
+import static dagger.internal.codegen.ErrorMessages.creatorMessagesFor;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
-import dagger.internal.codegen.binding.ErrorMessages;
 import java.util.Collection;
 import javax.tools.JavaFileObject;
 import org.junit.Test;
@@ -87,7 +86,7 @@
             "",
             "import dagger.internal.Preconditions;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  private static final class Factory implements TestComponent.Factory {",
             "    @Override",
@@ -98,7 +97,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(moduleFile, componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(moduleFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerTestComponent")
@@ -124,7 +123,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(String.format(MSGS.twoFactoryMethods(), "create()"))
@@ -153,7 +152,7 @@
             "  interface Factory extends Parent {}",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(String.format(MSGS.twoFactoryMethods(), "create()"))
diff --git a/javatests/dagger/internal/codegen/ComponentHierarchyValidationTest.java b/javatests/dagger/internal/codegen/ComponentHierarchyValidationTest.java
index 6fb1820..19eabac 100644
--- a/javatests/dagger/internal/codegen/ComponentHierarchyValidationTest.java
+++ b/javatests/dagger/internal/codegen/ComponentHierarchyValidationTest.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
 import static dagger.internal.codegen.TestUtils.message;
 
@@ -64,7 +63,8 @@
     assertThat(compilation).hadErrorContaining("test.Parent also has @Singleton");
 
     Compilation withoutScopeValidation =
-        compilerWithOptions("-Adagger.disableInterComponentScopeValidation=none")
+        daggerCompiler()
+            .withOptions("-Adagger.disableInterComponentScopeValidation=none")
             .compile(component, subcomponent);
     assertThat(withoutScopeValidation).succeeded();
   }
diff --git a/javatests/dagger/internal/codegen/ComponentProcessorTest.java b/javatests/dagger/internal/codegen/ComponentProcessorTest.java
index eee6a0c..2b79b6f 100644
--- a/javatests/dagger/internal/codegen/ComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/ComponentProcessorTest.java
@@ -20,10 +20,11 @@
 import static com.google.testing.compile.Compiler.javac;
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
+import static dagger.internal.codegen.GeneratedLines.NPE_FROM_COMPONENT_METHOD;
+import static dagger.internal.codegen.GeneratedLines.NPE_FROM_PROVIDES_METHOD;
 
 import com.google.auto.common.MoreElements;
 import com.google.common.base.Predicate;
@@ -106,15 +107,16 @@
         "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(parent, child, another, componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("List<Integer> is bound multiple times");
+        .hadErrorContaining("java.util.List<java.lang.Integer> is bound multiple times");
     assertThat(compilation)
-        .hadErrorContaining("@Provides List<Integer> ChildNumberModule.provideListB(Integer)");
+        .hadErrorContaining("@Provides List<Integer> test.ChildNumberModule.provideListB(Integer)");
     assertThat(compilation)
-        .hadErrorContaining("@Provides List<Integer> AnotherModule.provideListOfInteger()");
+        .hadErrorContaining("@Provides List<Integer> test.AnotherModule.provideListOfInteger()");
   }
 
   @Test public void privateNestedClassWithWarningThatIsAnErrorInComponent() {
@@ -140,7 +142,8 @@
         "  OuterClass outerClass();",
         "}");
     Compilation compilation =
-        compilerWithOptions(
+        daggerCompiler()
+            .withOptions(
                 compilerMode.javacopts().append("-Adagger.privateMemberValidation=WARNING"))
             .compile(outerClass, componentFile);
     assertThat(compilation).failed();
@@ -182,7 +185,7 @@
                 IMPORT_GENERATED_ANNOTATION,
                 "import javax.inject.Provider;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {")
             .addLinesIn(
                 FAST_INIT_MODE,
@@ -258,7 +261,8 @@
             .build();
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(injectableTypeFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -298,7 +302,7 @@
             .addLines(
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {")
             .addLinesIn(
                 FAST_INIT_MODE,
@@ -383,7 +387,8 @@
                 "  }")
             .build();
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(injectableTypeFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -417,7 +422,7 @@
             .addLines(
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerOuterType_SimpleComponent",
                 "    implements OuterType.SimpleComponent {",
                 "  private DaggerOuterType_SimpleComponent() {}",
@@ -441,7 +446,7 @@
             .build();
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(nestedTypesFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(nestedTypesFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerOuterType_SimpleComponent")
@@ -501,7 +506,7 @@
                 "import dagger.internal.Preconditions;",
                 IMPORT_GENERATED_ANNOTATION,
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final TestModule testModule;",
                 "",
@@ -509,13 +514,13 @@
                 "    this.testModule = testModuleParam;",
                 "  }",
                 "",
-                "  private B b() {",
+                "  private B getB() {",
                 "    return TestModule_BFactory.b(testModule, new C());",
                 "  }",
                 "",
                 "  @Override",
                 "  public A a() {",
-                "    return new A(b());",
+                "    return new A(getB());",
                 "  }",
                 "",
                 "  static final class Builder {",
@@ -537,7 +542,8 @@
             .build();
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(aFile, bFile, cFile, moduleFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -604,21 +610,22 @@
             .addLines(
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
-                "  private B b() {",
+                "  private B getB() {",
                 "    return TestModule_BFactory.b(new C());",
                 "  }",
                 "",
                 "  @Override",
                 "  public A a() {",
-                "    return new A(b());",
+                "    return new A(getB());",
                 "  }",
                 "}")
             .build();
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(aFile, bFile, cFile, moduleFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -701,7 +708,7 @@
         "import dagger.internal.Preconditions;",
         IMPORT_GENERATED_ANNOTATION,
         "",
-        GENERATED_CODE_ANNOTATIONS,
+        GENERATED_ANNOTATION,
         "final class DaggerTestComponent implements TestComponent {",
         "  static final class Builder {",
         "",
@@ -747,7 +754,8 @@
         "  }",
         "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 always,
                 testModule,
@@ -781,7 +789,7 @@
         "@Component(modules = RootModule.class)",
         "interface TestComponent {}");
     assertThat(
-            compilerWithOptions(compilerMode.javacopts()).compile(rootModule, component))
+            daggerCompiler().withOptions(compilerMode.javacopts()).compile(rootModule, component))
         .failed();
     assertThat(
             daggerCompiler(
@@ -820,7 +828,7 @@
             "  ChildComponent childComponent();",
             "}");
     assertThat(
-            compilerWithOptions(compilerMode.javacopts()).compile(subcomponent, component))
+            daggerCompiler().withOptions(compilerMode.javacopts()).compile(subcomponent, component))
         .failed();
     assertThat(
             daggerCompiler(
@@ -885,7 +893,7 @@
             "import dagger.internal.Preconditions;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParent implements Parent {",
             "",
             "  private DaggerParent() {}",
@@ -919,7 +927,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(component, module, subcomponent);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -953,7 +962,8 @@
         "  BClass bClass();",
         "}");
     assertThat(
-            compilerWithOptions(compilerMode.javacopts())
+            daggerCompiler()
+                .withOptions(compilerMode.javacopts())
                 .compile(aModule, aClass, bClass, component))
         .succeeded();
   }
@@ -997,7 +1007,7 @@
                 "",
                 "import com.google.errorprone.annotations.CanIgnoreReturnValue;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {",
                 "  @Override",
                 "  public void inject(SomeInjectedType instance) {",
@@ -1019,7 +1029,8 @@
             .build();
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(injectableTypeFile, injectedTypeFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1053,7 +1064,7 @@
             "test.DaggerSimpleComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerSimpleComponent implements SimpleComponent {",
             "  private Provider<SimpleComponent> simpleComponentProvider;",
             "",
@@ -1073,7 +1084,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(injectableTypeFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1117,7 +1129,7 @@
                 "",
                 "import com.google.errorprone.annotations.CanIgnoreReturnValue;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {",
                 "  @Override",
                 "  public SomeInjectedType createAndInject() {",
@@ -1135,7 +1147,8 @@
             .build();
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(injectableTypeFile, injectedTypeFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1185,9 +1198,11 @@
             .addLines(
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerBComponent implements BComponent {")
-            .addLinesIn(DEFAULT_MODE, "  private Provider<A> aProvider;")
+            .addLinesIn(
+                DEFAULT_MODE,
+                "  private Provider<A> aProvider;")
             .addLinesIn(
                 FAST_INIT_MODE,
                 "  private final AComponent aComponent;",
@@ -1197,7 +1212,7 @@
                 "    this.aComponent = aComponentParam;",
                 "  }",
                 "",
-                "  private Provider<A> aProvider() {",
+                "  private Provider<A> getAProvider() {",
                 "    Object local = aProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(0);",
@@ -1211,9 +1226,16 @@
                 "  private void initialize(final AComponent aComponentParam) {",
                 "    this.aProvider = new test_AComponent_a(aComponentParam);",
                 "  }")
-            .addLines("", "  @Override", "  public B b() {")
-            .addLinesIn(DEFAULT_MODE, "    return new B(aProvider);")
-            .addLinesIn(FAST_INIT_MODE, "    return new B(aProvider());")
+            .addLines(
+                "",
+                "  @Override",
+                "  public B b() {")
+            .addLinesIn(
+                DEFAULT_MODE,
+                "    return new B(aProvider);")
+            .addLinesIn(
+                FAST_INIT_MODE,
+                "    return new B(getAProvider());")
             .addLines(
                 "  }",
                 "",
@@ -1241,7 +1263,8 @@
                 "    ",
                 "    @Override()",
                 "    public A get() {",
-                "      return Preconditions.checkNotNullFromComponent(aComponent.a());",
+                "      return Preconditions.checkNotNull(",
+                "          aComponent.a(), " + NPE_FROM_COMPONENT_METHOD + ");",
                 "    }",
                 "  }",
                 "}")
@@ -1254,8 +1277,9 @@
                 "      switch (id) {",
                 "        case 0:",
                 "          return (T)",
-                "              Preconditions.checkNotNullFromComponent(",
-                "                  DaggerBComponent.this.aComponent.a());",
+                "              Preconditions.checkNotNull(",
+                "                  DaggerBComponent.this.aComponent.a(),",
+                "                  " + NPE_FROM_COMPONENT_METHOD + ");",
                 "        default:",
                 "          throw new AssertionError(id);",
                 "      }",
@@ -1263,7 +1287,8 @@
                 "  }")
             .build();
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(aFile, bFile, aComponentFile, bComponentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1318,7 +1343,7 @@
             "test.DaggerTestComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  private final TestModule testModule;",
             "  private final other.test.TestModule testModule2;",
@@ -1366,7 +1391,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(aFile, otherAFile, moduleFile, otherModuleFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1443,7 +1469,7 @@
             "import dagger.internal.Preconditions;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerBComponent implements BComponent {",
             "  private final AComponent aComponent;",
             "",
@@ -1454,17 +1480,20 @@
             "  @Override",
             "  public InjectedType injectedType() {",
             "    return new InjectedType(",
-            "        Preconditions.checkNotNullFromComponent(",
-            "            aComponent.someStringInjection()),",
+            "        Preconditions.checkNotNull(",
+            "            aComponent.someStringInjection(),",
+            "            \"Cannot return null from a non-@Nullable component method\"),",
             "        aComponent.someIntInjection(),",
             "        aComponent,",
-            "        Preconditions.checkNotNullFromComponent(",
-            "            aComponent.someClassInjection()));",
+            "        Preconditions.checkNotNull(",
+            "            aComponent.someClassInjection(),",
+            "            \"Cannot return null from a non-@Nullable component method\"));",
             "  }",
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(injectedTypeFile, aComponentFile, bComponentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1527,15 +1556,15 @@
                 "",
                 IMPORT_GENERATED_ANNOTATION,
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
-                "  private B b() {",
+                "  private B getB() {",
                 "    return new B(new C());",
                 "  }",
                 "",
                 "  @Override",
                 "  public A a() {",
-                "    return new A(b());",
+                "    return new A(getB());",
                 "  }",
                 "",
                 "  @Override",
@@ -1551,7 +1580,8 @@
             .build();
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(aFile, bFile, cFile, xFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1607,7 +1637,7 @@
             "",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerSimpleComponent implements SimpleComponent {",
             "  private DaggerSimpleComponent() {}",
             "",
@@ -1633,7 +1663,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 injectableTypeFile,
                 componentSupertypeAFile,
@@ -1676,7 +1707,7 @@
             "test.DaggerSimpleComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerSimpleComponent implements SimpleComponent {",
             "  @Override",
             "  public SomeInjectableType someInjectableType() {",
@@ -1684,7 +1715,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(injectableTypeFile, componentSupertype, depComponentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1731,7 +1763,8 @@
         "  C c();",
         "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(aFile, bFile, cFile, componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
@@ -1754,7 +1787,7 @@
             "  String[] array();",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(component);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining("String[] cannot be provided without an @Provides-annotated method");
@@ -1980,7 +2013,7 @@
             "  @Inject @AScope AClass() {}",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(aScope, aClass);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(aScope, aClass);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining("@Scope annotations are not allowed on @Inject constructors")
@@ -2049,7 +2082,7 @@
             "import dagger.internal.Preconditions;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParent implements Parent {",
             "  private DaggerParent() {",
             "  }",
@@ -2078,7 +2111,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(foo, module, component, prunedSubcomponent);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -2141,7 +2175,7 @@
     assertThat(compilation).failed();
     assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
-        .hadErrorContaining("String is bound multiple times")
+        .hadErrorContaining("java.lang.String is bound multiple times")
         .inFile(component)
         .onLineContaining("interface TestComponent");
   }
@@ -2149,7 +2183,8 @@
   @Test
   public void nullIncorrectlyReturnedFromNonNullableInlinedProvider() {
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 JavaFileObjects.forSourceLines(
                     "test.TestModule",
@@ -2190,7 +2225,7 @@
                 "test.TestModule_NonNullableStringFactory",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "public final class TestModule_NonNullableStringFactory",
                 "    implements Factory<String> {",
                 "  @Override",
@@ -2199,8 +2234,8 @@
                 "  }",
                 "",
                 "  public static String nonNullableString() {",
-                "    return Preconditions.checkNotNullFromProvides(",
-                "        TestModule.nonNullableString());",
+                "    return Preconditions.checkNotNull(",
+                "        TestModule.nonNullableString(), " + NPE_FROM_PROVIDES_METHOD + ");",
                 "  }",
                 "}"));
 
@@ -2210,7 +2245,7 @@
             .addLines(
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  @Override",
                 "  public String nonNullableString() {",
@@ -2239,7 +2274,8 @@
   @Test
   public void nullCheckingIgnoredWhenProviderReturnsPrimitive() {
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 JavaFileObjects.forSourceLines(
                     "test.TestModule",
@@ -2280,7 +2316,7 @@
                 "test.TestModule_PrimitiveIntegerFactory",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "public final class TestModule_PrimitiveIntegerFactory",
                 "    implements Factory<Integer> {",
                 "",
@@ -2300,7 +2336,7 @@
             .addLines(
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  @Override",
                 "  public Integer nonNullableInteger() {",
@@ -2376,9 +2412,9 @@
         JavaFileObjects.forSourceLines(
             "test.DaggerParent",
             "package test;",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParent implements Parent {",
-            "  private String string() {",
+            "  private String getString() {",
             "    return TestModule_StringFactory.string(numberProvider.get());",
             "  }",
             "}");
@@ -2446,7 +2482,7 @@
         JavaFileObjects.forSourceLines(
             "test.DaggerParent",
             "package test;",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParent implements Parent {",
             "  private final class ChildImpl implements Child {",
             "    @Override",
@@ -2513,7 +2549,7 @@
             "test.DaggerTestComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  @Override",
             "  public Injected injected() {",
@@ -2586,7 +2622,7 @@
             "test.DaggerTestComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  @Override",
             "  public String unqualified() {",
@@ -2640,7 +2676,7 @@
                 "",
                 IMPORT_GENERATED_ANNOTATION,
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "public final class DaggerPublicComponent implements PublicComponent {",
                 "  private DaggerPublicComponent() {}",
                 "",
diff --git a/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java b/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
index 049ff85..85e2d7b 100644
--- a/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
+++ b/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
@@ -17,8 +17,9 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
+import static dagger.internal.codegen.GeneratedLines.NPE_FROM_COMPONENT_METHOD;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
@@ -66,7 +67,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(component);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerTestComponent")
@@ -75,7 +76,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final Integer i;",
                 "  private final List<String> list;",
@@ -161,7 +162,8 @@
             "  long l();",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(module, otherPackageModule, component);
     assertThat(compilation).succeeded();
     JavaFileObject generatedComponent =
@@ -172,7 +174,7 @@
             "import other.OtherPackageModule;",
             "import other.OtherPackageModule_LFactory;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  private final ParentModule parentModule;",
             "  private final OtherPackageModule otherPackageModule;",
@@ -234,7 +236,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(dependency, component, subcomponent);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -244,7 +247,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final Dep dep;",
                 "",
@@ -264,13 +267,14 @@
                 "",
                 "  @Override",
                 "  public String methodOnDep() {",
-                "    return Preconditions.checkNotNullFromComponent(",
-                "        dep.string());",
+                "    return Preconditions.checkNotNull(",
+                "        dep.string(), " + NPE_FROM_COMPONENT_METHOD + " );",
                 "  }",
                 "",
                 "  @Override",
                 "  public Object otherMethodOnDep() {",
-                "    return Preconditions.checkNotNullFromComponent(dep.object());",
+                "    return Preconditions.checkNotNull(",
+                "        dep.object(), " + NPE_FROM_COMPONENT_METHOD + " );",
                 "  }",
                 "",
                 "  private final class TestSubcomponentImpl implements TestSubcomponent {",
@@ -357,7 +361,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final ParentModule parentModule;",
                 "",
@@ -366,15 +370,15 @@
                 "  }",
                 "",
                 "  private final class TestSubcomponentImpl implements TestSubcomponent {",
-                "    private Set<Object> setOfObject() {",
+                "    private Set<Object> getSetOfObject() {",
                 "      return ImmutableSet.<Object>of(",
                 "          ParentModule_ContributionFactory.contribution(),",
                 "          ChildModule_ContributionFactory.contribution());",
                 "    }",
                 "",
-                "    private Object object() {",
+                "    private Object getObject() {",
                 "      return ParentModule_ReliesOnMultibindingFactory.reliesOnMultibinding(",
-                "          DaggerTestComponent.this.parentModule, setOfObject());",
+                "          DaggerTestComponent.this.parentModule, getSetOfObject());",
                 "    }",
                 "  }",
                 "}");
@@ -385,7 +389,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final ParentModule parentModule;",
                 "",
@@ -421,7 +425,8 @@
                 "}");
     }
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(parentModule, childModule, component, subcomponent);
     assertThat(compilation).succeeded();
     assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/ComponentShardTest.java b/javatests/dagger/internal/codegen/ComponentShardTest.java
deleted file mode 100644
index fc59c92..0000000
--- a/javatests/dagger/internal/codegen/ComponentShardTest.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing.compile.CompilationSubject.assertThat;
-import static com.google.testing.compile.Compiler.javac;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
-import static java.util.stream.Collectors.joining;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.Compiler;
-import com.google.testing.compile.JavaFileObjects;
-import java.util.Arrays;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class ComponentShardTest {
-  private static final int BINDINGS_PER_SHARD = 10;
-
-  @Test
-  public void testNewShardCreated() {
-    // Create 2N + 1 bindings: N in DaggerTestComponent, N in Shard1, and 1 in Shard2
-    int numBindings = 2 * BINDINGS_PER_SHARD + 1;
-    ImmutableList.Builder<JavaFileObject> javaFileObjects = ImmutableList.builder();
-    ImmutableList.Builder<String> entryPoints = ImmutableList.builder();
-    for (int i = 0; i < numBindings; i++) {
-      String bindingName = "Binding" + i;
-      entryPoints.add(String.format("%1$s get%1$s();", bindingName));
-      entryPoints.add(String.format("Provider<%1$s> get%1$sProvider();", bindingName));
-
-      // Add dependencies between main component and shard1: 9 -> 10 -> Provider<9>
-      // Add dependencies between shard1 and shard2:        19 -> 20 -> Provider<19>
-      switch (i) {
-        case 9:
-          javaFileObjects.add(createBinding(bindingName, "Binding10 dep"));
-          break;
-        case 10:
-          javaFileObjects.add(createBinding(bindingName, "Provider<Binding9> dep"));
-          break;
-        case 19:
-          javaFileObjects.add(createBinding(bindingName, "Binding20 dep"));
-          break;
-        case 20:
-          javaFileObjects.add(createBinding(bindingName, "Provider<Binding19> dep"));
-          break;
-        default:
-          javaFileObjects.add(createBinding(bindingName));
-          break;
-      }
-    }
-
-    javaFileObjects.add(createComponent(entryPoints.build()));
-
-    // This generated component shows a couple things:
-    //   1. Binding locations:
-    //     * Binding #9 belongs to DaggerTestComponent
-    //     * Binding #10 belongs to Shard1
-    //     * Binding #20 belongs to Shard2
-    //   2. DaggerTestComponent entry point methods:
-    //     * Binding #9 implementation is inlined DaggerTestComponent.
-    //     * Binding #10 implementation is delegated to Shard1.
-    //     * Binding #20 implementation is delegated to Shard2.
-    //   3. Dependencies between component and shard:
-    //     * Binding #9 in DaggerTestComponent depends on #10 in Shard1.
-    //     * Binding #10 in Shard1 depends on Provider<#9> in DaggerTestComponent.
-    //   4. Dependencies between shard and shard:
-    //     * Binding #19 in Shard1 depends on #20 in Shard2.
-    //     * Binding #20 in Shard2 depends on Provider<#19> in Shard1.
-    JavaFileObject generatedComponent =
-        JavaFileObjects.forSourceLines(
-            "dagger.internal.codegen.DaggerTestComponent",
-                "package dagger.internal.codegen;",
-            GENERATED_CODE_ANNOTATIONS,
-                "final class DaggerTestComponent implements TestComponent {",
-                "  private final Shard1 shard1 = new Shard1();",
-                "",
-                "  private volatile Provider<Binding9> binding9Provider;",
-                "",
-                "  private volatile Object binding9 = new MemoizedSentinel();",
-                "",
-                "  @Override",
-                "  public Binding9 getBinding9() {",
-                "    Object local = binding9;",
-                "    if (local instanceof MemoizedSentinel) {",
-                "      synchronized (local) {",
-                "        local = binding9;",
-                "        if (local instanceof MemoizedSentinel) {",
-                "          local = new Binding9(DaggerTestComponent.this.shard1.binding10());",
-                "          binding9 = DoubleCheck.reentrantCheck(binding9, local);",
-                "        }",
-                "      }",
-                "    }",
-                "    return (Binding9) local;",
-                "  }",
-                "",
-                "  @Override",
-                "  public Provider<Binding9> getBinding9Provider() {",
-                "    Object local = binding9Provider;",
-                "    if (local == null) {",
-                "      local = new SwitchingProvider<>(9);",
-                "      binding9Provider = (Provider<Binding9>) local;",
-                "    }",
-                "    return (Provider<Binding9>) local;",
-                "  }",
-                "",
-                "  @Override",
-                "  public Binding10 getBinding10() {",
-                "    return DaggerTestComponent.this.shard1.binding10();",
-                "  }",
-                "",
-                "  @Override",
-                "  public Provider<Binding10> getBinding10Provider() {",
-                "    return DaggerTestComponent.this.shard1.binding10Provider();",
-                "  }",
-                "",
-                "  @Override",
-                "  public Binding20 getBinding20() {",
-                "    return DaggerTestComponent.this.shard2.binding20();",
-                "  }",
-                "",
-                "  @Override",
-                "  public Provider<Binding20> getBinding20Provider() {",
-                "    return DaggerTestComponent.this.shard2.binding20Provider();",
-                "  }",
-                "",
-                "  private final class Shard1 {",
-                "    private volatile Object binding10 = new MemoizedSentinel();",
-                "",
-                "    private volatile Provider<Binding10> binding10Provider;",
-                "",
-                "    private volatile Provider<Binding19> binding19Provider;",
-                "",
-                "    private volatile Object binding19 = new MemoizedSentinel();",
-                "",
-                "    private Binding10 binding10() {",
-                "      Object local = binding10;",
-                "      if (local instanceof MemoizedSentinel) {",
-                "        synchronized (local) {",
-                "          local = binding10;",
-                "          if (local instanceof MemoizedSentinel) {",
-                "            local = new Binding10(",
-                "                DaggerTestComponent.this.getBinding9Provider());",
-                "            binding10 = DoubleCheck.reentrantCheck(binding10, local);",
-                "          }",
-                "        }",
-                "      }",
-                "      return (Binding10) local;",
-                "    }",
-                "",
-                "    private Provider<Binding10> binding10Provider() {",
-                "      Object local = binding10Provider;",
-                "      if (local == null) {",
-                "        local = new SwitchingProvider<>(10);",
-                "        binding10Provider = (Provider<Binding10>) local;",
-                "      }",
-                "      return (Provider<Binding10>) local;",
-                "    }",
-                "",
-                "    private Provider<Binding19> binding19Provider() {",
-                "      Object local = binding19Provider;",
-                "      if (local == null) {",
-                "        local = new SwitchingProvider<>(19);",
-                "        binding19Provider = (Provider<Binding19>) local;",
-                "      }",
-                "      return (Provider<Binding19>) local;",
-                "    }",
-                "",
-                "    private Binding19 binding19() {",
-                "      Object local = binding19;",
-                "      if (local instanceof MemoizedSentinel) {",
-                "        synchronized (local) {",
-                "          local = binding19;",
-                "          if (local instanceof MemoizedSentinel) {",
-                "            local = new Binding19(DaggerTestComponent.this.shard2.binding20());",
-                "            binding19 = DoubleCheck.reentrantCheck(binding19, local);",
-                "          }",
-                "        }",
-                "      }",
-                "      return (Binding19) local;",
-                "    }",
-                "  }",
-                "",
-                "  private final class Shard2 {",
-                "    private volatile Object binding20 = new MemoizedSentinel();",
-                "",
-                "    private volatile Provider<Binding20> binding20Provider;",
-                "",
-                "    private Binding20 binding20() {",
-                "      Object local = binding20;",
-                "      if (local instanceof MemoizedSentinel) {",
-                "        synchronized (local) {",
-                "          local = binding20;",
-                "          if (local instanceof MemoizedSentinel) {",
-                "            local = new Binding20(",
-                "                DaggerTestComponent.this.shard1.binding19Provider());",
-                "            binding20 = DoubleCheck.reentrantCheck(binding20, local);",
-                "          }",
-                "        }",
-                "      }",
-                "      return (Binding20) local;",
-                "    }",
-                "",
-                "    private Provider<Binding20> binding20Provider() {",
-                "      Object local = binding20Provider;",
-                "      if (local == null) {",
-                "        local = new SwitchingProvider<>(20);",
-                "        binding20Provider = (Provider<Binding20>) local;",
-                "      }",
-                "      return (Provider<Binding20>) local;",
-                "    }",
-                "  }",
-                "}");
-
-    Compilation compilation = compilerWithAndroidMode().compile(javaFileObjects.build());
-    assertThat(compilation).succeededWithoutWarnings();
-    assertThat(compilation)
-        .generatedSourceFile("dagger.internal.codegen.DaggerTestComponent")
-        .containsElementsIn(generatedComponent);
-  }
-
-  private static JavaFileObject createBinding(String bindingName, String... deps) {
-    return JavaFileObjects.forSourceLines(
-        "dagger.internal.codegen." + bindingName,
-        "package dagger.internal.codegen;",
-        "",
-        "import javax.inject.Inject;",
-        "import javax.inject.Provider;",
-        "import javax.inject.Singleton;",
-        "",
-        "@Singleton",
-        "final class " + bindingName + " {",
-        "  @Inject",
-        "  " + bindingName + "(" + Arrays.stream(deps).collect(joining(", ")) + ") {}",
-        "}");
-  }
-
-  private static JavaFileObject createComponent(ImmutableList<String> entryPoints) {
-    return JavaFileObjects.forSourceLines(
-        "dagger.internal.codegen.TestComponent",
-        "package dagger.internal.codegen;",
-        "",
-        "import dagger.Component;",
-        "import javax.inject.Provider;",
-        "import javax.inject.Singleton;",
-        "",
-        "@Singleton",
-        "@Component",
-        "interface TestComponent {",
-        "  " + entryPoints.stream().collect(joining("\n  ")),
-        "}");
-  }
-
-  private static Compiler compilerWithAndroidMode() {
-    return javac()
-        .withProcessors(new ComponentProcessor())
-        .withOptions(
-            ImmutableSet.builder()
-                .add("-Adagger.keysPerComponentShard=" + BINDINGS_PER_SHARD)
-                .addAll(CompilerMode.FAST_INIT_MODE.javacopts())
-                .build());
-  }
-}
diff --git a/javatests/dagger/internal/codegen/ComponentValidationTest.java b/javatests/dagger/internal/codegen/ComponentValidationTest.java
index 6c642a4..169a318 100644
--- a/javatests/dagger/internal/codegen/ComponentValidationTest.java
+++ b/javatests/dagger/internal/codegen/ComponentValidationTest.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
 import static dagger.internal.codegen.TestUtils.message;
 
@@ -220,17 +219,6 @@
             message(
                 "test.ComponentShort contains a cycle in its component dependencies:",
                 "    test.ComponentShort"));
-
-    // Test that this also fails when transitive validation is disabled.
-    compilation =
-        compilerWithOptions("-Adagger.validateTransitiveComponentDependencies=DISABLED")
-            .compile(shortLifetime);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            message(
-                "test.ComponentShort contains a cycle in its component dependencies:",
-                "    test.ComponentShort"));
   }
 
   @Test
@@ -293,13 +281,6 @@
                 "    test.ComponentMedium",
                 "    test.ComponentShort"))
         .inFile(shortLifetime);
-
-    // Test that compilation succeeds when transitive validation is disabled because the cycle
-    // cannot be detected.
-    compilation =
-        compilerWithOptions("-Adagger.validateTransitiveComponentDependencies=DISABLED")
-            .compile(longLifetime, mediumLifetime, shortLifetime);
-    assertThat(compilation).succeeded();
   }
 
   @Test
diff --git a/javatests/dagger/internal/codegen/DaggerModuleMethodSubject.java b/javatests/dagger/internal/codegen/DaggerModuleMethodSubject.java
index 470b1ed..1fcf7bc 100644
--- a/javatests/dagger/internal/codegen/DaggerModuleMethodSubject.java
+++ b/javatests/dagger/internal/codegen/DaggerModuleMethodSubject.java
@@ -36,7 +36,7 @@
 import javax.tools.JavaFileObject;
 
 /** A {@link Truth} subject for testing Dagger module methods. */
-final class DaggerModuleMethodSubject extends Subject {
+final class DaggerModuleMethodSubject extends Subject<DaggerModuleMethodSubject, String> {
 
   /** A {@link Truth} subject factory for testing Dagger module methods. */
   static final class Factory implements Subject.Factory<DaggerModuleMethodSubject, String> {
diff --git a/javatests/dagger/internal/codegen/DelegateBindingExpressionTest.java b/javatests/dagger/internal/codegen/DelegateBindingExpressionTest.java
index bc729fc..2f4aecf 100644
--- a/javatests/dagger/internal/codegen/DelegateBindingExpressionTest.java
+++ b/javatests/dagger/internal/codegen/DelegateBindingExpressionTest.java
@@ -19,8 +19,8 @@
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.CompilationSubject;
@@ -144,14 +144,14 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerTestComponent implements TestComponent {")
                 .addLinesIn(
                     FAST_INIT_MODE,
                     "  private volatile Object regularScoped = new MemoizedSentinel();",
                     "  private volatile ReusableScoped reusableScoped;",
                     "",
-                    "  private RegularScoped regularScoped() {",
+                    "  private RegularScoped getRegularScoped() {",
                     "    Object local = regularScoped;",
                     "    if (local instanceof MemoizedSentinel) {",
                     "      synchronized (local) {",
@@ -165,7 +165,7 @@
                     "    return (RegularScoped) local;",
                     "  }",
                     "",
-                    "  private ReusableScoped reusableScoped() {",
+                    "  private ReusableScoped getReusableScoped() {",
                     "    Object local = reusableScoped;",
                     "    if (local == null) {",
                     "      local = new ReusableScoped();",
@@ -223,14 +223,14 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerTestComponent implements TestComponent {")
                 .addLinesIn(
                     FAST_INIT_MODE,
                     "  private volatile Object regularScoped = new MemoizedSentinel();",
                     "  private volatile ReusableScoped reusableScoped;",
                     "",
-                    "  private RegularScoped regularScoped() {",
+                    "  private RegularScoped getRegularScoped() {",
                     "    Object local = regularScoped;",
                     "    if (local instanceof MemoizedSentinel) {",
                     "      synchronized (local) {",
@@ -244,7 +244,7 @@
                     "    return (RegularScoped) local;",
                     "  }",
                     "",
-                    "  private ReusableScoped reusableScoped() {",
+                    "  private ReusableScoped getReusableScoped() {",
                     "    Object local = reusableScoped;",
                     "    if (local == null) {",
                     "      local = new ReusableScoped();",
@@ -299,14 +299,14 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerTestComponent implements TestComponent {")
                 .addLinesIn(
                     FAST_INIT_MODE,
                     "  private volatile Object regularScoped = new MemoizedSentinel();",
                     "  private volatile ReusableScoped reusableScoped;",
                     "",
-                    "  private RegularScoped regularScoped() {",
+                    "  private RegularScoped getRegularScoped() {",
                     "    Object local = regularScoped;",
                     "    if (local instanceof MemoizedSentinel) {",
                     "      synchronized (local) {",
@@ -320,7 +320,7 @@
                     "    return (RegularScoped) local;",
                     "  }",
                     "",
-                    "  private ReusableScoped reusableScoped() {",
+                    "  private ReusableScoped getReusableScoped() {",
                     "    Object local = reusableScoped;",
                     "    if (local == null) {",
                     "      local = new ReusableScoped();",
@@ -390,7 +390,8 @@
             "  other.Supertype supertype();",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(accessibleSupertype, inaccessibleSubtype, module, component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -401,7 +402,7 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerTestComponent implements TestComponent {")
                 .addLinesIn(
                     DEFAULT_MODE,
@@ -421,7 +422,7 @@
                     FAST_INIT_MODE,
                     "  private volatile Object subtype = new MemoizedSentinel();",
                     "",
-                    "  private Object subtype() {",
+                    "  private Object getSubtype() {",
                     "    Object local = subtype;",
                     "    if (local instanceof MemoizedSentinel) {",
                     "      synchronized (local) {",
@@ -437,7 +438,7 @@
                     "",
                     "  @Override",
                     "  public Supertype supertype() {",
-                    "    return (Supertype) subtype();",
+                    "    return (Supertype) getSubtype();",
                     "  }")
                 .build());
   }
@@ -498,7 +499,8 @@
             "  other.UsesSupertype usesSupertype();",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(supertype, subtype, usesSupertype, module, component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -509,7 +511,7 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerTestComponent implements TestComponent {")
                 .addLinesIn(
                     DEFAULT_MODE,
@@ -526,7 +528,7 @@
                     FAST_INIT_MODE,
                     "  private volatile Object subtype = new MemoizedSentinel();",
                     "",
-                    "  private Object subtype() {",
+                    "  private Object getSubtype() {",
                     "    Object local = subtype;",
                     "    if (local instanceof MemoizedSentinel) {",
                     "      synchronized (local) {",
@@ -542,7 +544,7 @@
                     "",
                     "  @Override",
                     "  public UsesSupertype usesSupertype() {",
-                    "    return UsesSupertype_Factory.newInstance(subtype());",
+                    "    return UsesSupertype_Factory.newInstance(getSubtype());",
                     "  }")
                 .build());
   }
@@ -588,7 +590,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(module, component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -599,7 +602,7 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerTestComponent implements TestComponent {")
                 .addLinesIn(
                     DEFAULT_MODE,
@@ -617,7 +620,7 @@
                     FAST_INIT_MODE,
                     "  private volatile Provider<String> provideStringProvider;",
                     "",
-                    "  private Provider<String> stringProvider() {",
+                    "  private Provider<String> getStringProvider() {",
                     "    Object local = provideStringProvider;",
                     "    if (local == null) {",
                     "      local = new SwitchingProvider<>(0);",
@@ -628,12 +631,12 @@
                     "",
                     "  @Override",
                     "  public Provider<CharSequence> charSequence() {",
-                    "    return (Provider) stringProvider();",
+                    "    return (Provider) getStringProvider();",
                     "  }",
                     "",
                     "  @Override",
                     "  public Provider<String> namedString() {",
-                    "    return stringProvider();",
+                    "    return getStringProvider();",
                     "  }",
                     "",
                     "  private final class SwitchingProvider<T> implements Provider<T> {",
@@ -689,7 +692,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(module, component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -700,7 +704,7 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerTestComponent implements TestComponent {")
                 .addLinesIn(
                     DEFAULT_MODE,
@@ -717,7 +721,7 @@
                     FAST_INIT_MODE,
                     "  private volatile Provider<String> provideStringProvider;",
                     "",
-                    "  private Provider<String> stringProvider() {",
+                    "  private Provider<String> getStringProvider() {",
                     "    Object local = provideStringProvider;",
                     "    if (local == null) {",
                     "      local = new SwitchingProvider<>(0);",
@@ -728,12 +732,12 @@
                     "",
                     "  @Override",
                     "  public Provider<CharSequence> charSequence() {",
-                    "    return (Provider) stringProvider();",
+                    "    return (Provider) getStringProvider();",
                     "  }",
                     "",
                     "  @Override",
                     "  public Provider<Object> object() {",
-                    "    return (Provider) stringProvider();",
+                    "    return (Provider) getStringProvider();",
                     "  }",
                     "",
                     "  private final class SwitchingProvider<T> implements Provider<T> {",
@@ -794,7 +798,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(supertype, injectableSubtype, module, component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -805,7 +810,7 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerRequestsSubtypeAsProvider",
                     "    implements RequestsSubtypeAsProvider {")
                 .addLinesIn(
@@ -819,7 +824,7 @@
                     FAST_INIT_MODE,
                     "  private volatile Provider subtypeProvider;",
                     "",
-                    "  private Provider subtypeProvider() {",
+                    "  private Provider getSubtypeProvider() {",
                     "    Object local = subtypeProvider;",
                     "    if (local == null) {",
                     "      local = new SwitchingProvider<>(0);",
@@ -830,7 +835,7 @@
                     "",
                     "  @Override",
                     "  public Provider<Supertype> supertypeProvider() {",
-                    "    return subtypeProvider();",
+                    "    return getSubtypeProvider();",
                     "  }",
                     "",
                     "  private final class SwitchingProvider<T> implements Provider<T> {",
@@ -883,10 +888,11 @@
             "@Singleton",
             "@Component(modules = TestModule.class)",
             "interface TestComponent {",
-            "  Provider<Object> object();",
+            "  Provider<Object> getObject();",
             "}");
 
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts())
+    Compilation compilation = daggerCompiler()
+        .withOptions(compilerMode.javacopts())
         .compile(module, component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -897,7 +903,7 @@
                 .addLines(
                     "package test;",
                     "",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerTestComponent implements TestComponent {")
                 .addLinesIn(
                     DEFAULT_MODE,
@@ -913,7 +919,7 @@
                     "  }",
                     "",
                     "  @Override",
-                    "  public Provider<Object> object() {",
+                    "  public Provider<Object> getObject() {",
                     "    return bindStringProvider;",
                     "  }",
                     "}")
@@ -923,7 +929,7 @@
                     "  private volatile Object object = new MemoizedSentinel();",
                     "  private volatile Provider<Object> bindStringProvider;",
                     "",
-                    "  private String string() {",
+                    "  private String getString() {",
                     "    Object local = string;",
                     "    if (local == null) {",
                     "      local = TestModule_ProvideStringFactory.provideString();",
@@ -932,13 +938,13 @@
                     "    return (String) local;",
                     "  }",
                     "",
-                    "  private Object object2() {",
+                    "  private Object getObject2() {",
                     "    Object local = object;",
                     "    if (local instanceof MemoizedSentinel) {",
                     "      synchronized (local) {",
                     "        local = object;",
                     "        if (local instanceof MemoizedSentinel) {",
-                    "          local = string();",
+                    "          local = getString();",
                     "          object = DoubleCheck.reentrantCheck(object, local);",
                     "        }",
                     "      }",
@@ -947,7 +953,7 @@
                     "  }",
                     "",
                     "  @Override",
-                    "  public Provider<Object> object() {",
+                    "  public Provider<Object> getObject() {",
                     "    Object local = bindStringProvider;",
                     "    if (local == null) {",
                     "      local = new SwitchingProvider<>(0);",
@@ -961,7 +967,7 @@
                     "    @Override",
                     "    public T get() {",
                     "      switch (id) {",
-                    "        case 0: return (T) DaggerTestComponent.this.object2();",
+                    "        case 0: return (T) DaggerTestComponent.this.getObject2();",
                     "        default: throw new AssertionError(id);",
                     "      }",
                     "    }",
@@ -971,7 +977,8 @@
 
   private CompilationSubject assertThatCompilationWithModule(JavaFileObject module) {
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 module,
                 COMPONENT,
diff --git a/javatests/dagger/internal/codegen/DependencyCycleValidationTest.java b/javatests/dagger/internal/codegen/DependencyCycleValidationTest.java
index 22547b5..4a4e0a5 100644
--- a/javatests/dagger/internal/codegen/DependencyCycleValidationTest.java
+++ b/javatests/dagger/internal/codegen/DependencyCycleValidationTest.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
 import static dagger.internal.codegen.TestUtils.endsWithMessage;
 import static dagger.internal.codegen.TestUtils.message;
@@ -76,14 +75,14 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    Outer.C is injected at",
-                "        Outer.A(cParam)",
-                "    Outer.A is injected at",
-                "        Outer.B(aParam)",
-                "    Outer.B is injected at",
-                "        Outer.C(bParam)",
-                "    Outer.C is requested at",
-                "        Outer.CComponent.getC()"))
+                "    test.Outer.C is injected at",
+                "        test.Outer.A(cParam)",
+                "    test.Outer.A is injected at",
+                "        test.Outer.B(aParam)",
+                "    test.Outer.B is injected at",
+                "        test.Outer.C(bParam)",
+                "    test.Outer.C is provided at",
+                "        test.Outer.CComponent.getC()"))
         .inFile(SIMPLE_CYCLIC_DEPENDENCY)
         .onLineContaining("interface CComponent");
 
@@ -93,28 +92,21 @@
   @Test
   public void cyclicDependencyWithModuleBindingValidation() {
     // Cycle errors should not show a dependency trace to an entry point when doing full binding
-    // graph validation. So ensure that the message doesn't end with "test.Outer.C is requested at
+    // graph validation. So ensure that the message doesn't end with "test.Outer.C is provided at
     // test.Outer.CComponent.getC()", as the previous test's message does.
     Pattern moduleBindingValidationError =
         endsWithMessage(
             "Found a dependency cycle:",
-            "    Outer.C is injected at",
-            "        Outer.A(cParam)",
-            "    Outer.A is injected at",
-            "        Outer.B(aParam)",
-            "    Outer.B is injected at",
-            "        Outer.C(bParam)",
-            "",
-            "======================",
-            "Full classname legend:",
-            "======================",
-            "Outer: test.Outer",
-            "========================",
-            "End of classname legend:",
-            "========================");
+            "    test.Outer.C is injected at",
+            "        test.Outer.A(cParam)",
+            "    test.Outer.A is injected at",
+            "        test.Outer.B(aParam)",
+            "    test.Outer.B is injected at",
+            "        test.Outer.C(bParam)");
 
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(SIMPLE_CYCLIC_DEPENDENCY);
     assertThat(compilation).failed();
 
@@ -171,16 +163,16 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    Outer.C is injected at",
-                "        Outer.A(cParam)",
-                "    Outer.A is injected at",
-                "        Outer.B(aParam)",
-                "    Outer.B is injected at",
-                "        Outer.C(bParam)",
-                "    Outer.C is injected at",
-                "        Outer.D(cParam)",
-                "    Outer.D is requested at",
-                "        Outer.DComponent.getD()"))
+                "    test.Outer.C is injected at",
+                "        test.Outer.A(cParam)",
+                "    test.Outer.A is injected at",
+                "        test.Outer.B(aParam)",
+                "    test.Outer.B is injected at",
+                "        test.Outer.C(bParam)",
+                "    test.Outer.C is injected at",
+                "        test.Outer.D(cParam)",
+                "    test.Outer.D is provided at",
+                "        test.Outer.DComponent.getD()"))
         .inFile(component)
         .onLineContaining("interface DComponent");
   }
@@ -234,16 +226,16 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    Outer.C is injected at",
-                "        Outer.CModule.c(c)",
-                "    Map<String,Outer.C> is injected at",
-                "        Outer.A(cMap)",
-                "    Outer.A is injected at",
-                "        Outer.B(aParam)",
-                "    Outer.B is injected at",
-                "        Outer.C(bParam)",
-                "    Outer.C is requested at",
-                "        Outer.CComponent.getC()"))
+                "    test.Outer.C is injected at",
+                "        test.Outer.CModule.c(c)",
+                "    java.util.Map<java.lang.String,test.Outer.C> is injected at",
+                "        test.Outer.A(cMap)",
+                "    test.Outer.A is injected at",
+                "        test.Outer.B(aParam)",
+                "    test.Outer.B is injected at",
+                "        test.Outer.C(bParam)",
+                "    test.Outer.C is provided at",
+                "        test.Outer.CComponent.getC()"))
         .inFile(component)
         .onLineContaining("interface CComponent");
   }
@@ -295,16 +287,16 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    Outer.C is injected at",
-                "        Outer.CModule.c(c)",
-                "    Set<Outer.C> is injected at",
-                "        Outer.A(cSet)",
-                "    Outer.A is injected at",
-                "        Outer.B(aParam)",
-                "    Outer.B is injected at",
-                "        Outer.C(bParam)",
-                "    Outer.C is requested at",
-                "        Outer.CComponent.getC()"))
+                "    test.Outer.C is injected at",
+                "        test.Outer.CModule.c(c)",
+                "    java.util.Set<test.Outer.C> is injected at",
+                "        test.Outer.A(cSet)",
+                "    test.Outer.A is injected at",
+                "        test.Outer.B(aParam)",
+                "    test.Outer.B is injected at",
+                "        test.Outer.C(bParam)",
+                "    test.Outer.C is provided at",
+                "        test.Outer.CComponent.getC()"))
         .inFile(component)
         .onLineContaining("interface CComponent");
   }
@@ -351,16 +343,16 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    Outer.C is injected at",
-                "        Outer.A(cParam)",
-                "    Outer.A is injected at",
-                "        Outer.B(aParam)",
-                "    Outer.B is injected at",
-                "        Outer.C(bParam)",
-                "    Provider<Outer.C> is injected at",
-                "        Outer.D(cParam)",
-                "    Outer.D is requested at",
-                "        Outer.DComponent.getD()"))
+                "    test.Outer.C is injected at",
+                "        test.Outer.A(cParam)",
+                "    test.Outer.A is injected at",
+                "        test.Outer.B(aParam)",
+                "    test.Outer.B is injected at",
+                "        test.Outer.C(bParam)",
+                "    javax.inject.Provider<test.Outer.C> is injected at",
+                "        test.Outer.D(cParam)",
+                "    test.Outer.D is provided at",
+                "        test.Outer.DComponent.getD()"))
         .inFile(component)
         .onLineContaining("interface DComponent");
   }
@@ -435,12 +427,12 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    String is injected at",
-                "        CycleModule.object(string)",
-                "    Object is injected at",
-                "        CycleModule.string(object)",
-                "    String is requested at",
-                "        Grandchild.entry()"))
+                "    java.lang.String is injected at",
+                "        test.CycleModule.object(string)",
+                "    java.lang.Object is injected at",
+                "        test.CycleModule.string(object)",
+                "    java.lang.String is provided at",
+                "        test.Grandchild.entry()"))
         .inFile(parent)
         .onLineContaining("interface Parent");
   }
@@ -517,12 +509,12 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    String is injected at",
-                "        CycleModule.object(string)",
-                "    Object is injected at",
-                "        CycleModule.string(object)",
-                "    String is requested at",
-                "        Child.entry() [Parent → Child]"))
+                "    java.lang.String is injected at",
+                "        test.CycleModule.object(string)",
+                "    java.lang.Object is injected at",
+                "        test.CycleModule.string(object)",
+                "    java.lang.String is provided at",
+                "        test.Child.entry() [test.Parent → test.Child]"))
         .inFile(parent)
         .onLineContaining("interface Parent");
   }
@@ -568,12 +560,12 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    Object is injected at",
-                "        TestModule.bindQualified(unqualified)",
-                "    @SomeQualifier Object is injected at",
-                "        TestModule.bindUnqualified(qualified)",
-                "    Object is requested at",
-                "        TestComponent.unqualified()"))
+                "    java.lang.Object is injected at",
+                "        test.TestModule.bindQualified(unqualified)",
+                "    @test.SomeQualifier java.lang.Object is injected at",
+                "        test.TestModule.bindUnqualified(qualified)",
+                "    java.lang.Object is provided at",
+                "        test.TestComponent.unqualified()"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
   }
@@ -610,10 +602,10 @@
         .hadErrorContaining(
             message(
                 "Found a dependency cycle:",
-                "    Object is injected at",
-                "        TestModule.bindToSelf(sameKey)",
-                "    Object is requested at",
-                "        TestComponent.selfReferential()"))
+                "    java.lang.Object is injected at",
+                "        test.TestModule.bindToSelf(sameKey)",
+                "    java.lang.Object is provided at",
+                "        test.TestComponent.selfReferential()"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
   }
@@ -667,7 +659,7 @@
                 "    test.B is injected at",
                 "        test.A.b",
                 "    test.A is injected at",
-                "        CycleComponent.inject(test.A)"))
+                "        test.CycleComponent.inject(test.A)"))
         .inFile(component)
         .onLineContaining("interface CycleComponent");
   }
diff --git a/javatests/dagger/internal/codegen/DiagnosticFormattingTest.java b/javatests/dagger/internal/codegen/DiagnosticFormattingTest.java
index 9b0dde0..a2da92f 100644
--- a/javatests/dagger/internal/codegen/DiagnosticFormattingTest.java
+++ b/javatests/dagger/internal/codegen/DiagnosticFormattingTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import dagger.internal.codegen.base.DiagnosticFormatting;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java b/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
index fbda59d..14a6fb9 100644
--- a/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
+++ b/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
 import static dagger.internal.codegen.TestUtils.message;
 import static org.junit.Assume.assumeFalse;
@@ -83,16 +82,14 @@
         "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
-            .compile(component);
+        daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Outer.A is bound multiple times:",
-                "    @Provides Outer.A Outer.AModule.provideA(String)",
-                "    Outer.A Outer.Parent.getA()"))
+                "test.Outer.A is bound multiple times:",
+                "    @Provides test.Outer.A test.Outer.AModule.provideA(String)",
+                "    test.Outer.A test.Outer.Parent.getA()"))
         .inFile(component)
         .onLineContaining("interface Child");
   }
@@ -137,16 +134,14 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
-            .compile(component);
+        daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Outer.A is bound multiple times:",
-                "    @Provides Outer.A Outer.Module1.provideA1()",
-                "    @Provides Outer.A Outer.Module2.provideA2(String)"))
+                "test.Outer.A is bound multiple times:",
+                "    @Provides test.Outer.A test.Outer.Module1.provideA1()",
+                "    @Provides test.Outer.A test.Outer.Module2.provideA2(String)"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
 
@@ -154,9 +149,9 @@
       assertThat(compilation)
           .hadErrorContaining(
               message(
-                  "Outer.A is bound multiple times:",
-                  "    @Provides Outer.A Outer.Module1.provideA1()",
-                  "    @Provides Outer.A Outer.Module2.provideA2(String)"))
+                  "test.Outer.A is bound multiple times:",
+                  "    @Provides test.Outer.A test.Outer.Module1.provideA1()",
+                  "    @Provides test.Outer.A test.Outer.Module2.provideA2(String)"))
           .inFile(component)
           .onLineContaining("class Module3");
     }
@@ -205,16 +200,14 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
-            .compile(component);
+        daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Outer.A is bound multiple times:",
-                "    @Provides Outer.A Outer.Module1.provideA1()",
-                "    @Binds Outer.A Outer.Module2.bindA2(Outer.B)"))
+                "test.Outer.A is bound multiple times:",
+                "    @Provides test.Outer.A test.Outer.Module1.provideA1()",
+                "    @Binds test.Outer.A test.Outer.Module2.bindA2(test.Outer.B)"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
 
@@ -222,9 +215,9 @@
       assertThat(compilation)
           .hadErrorContaining(
               message(
-                  "Outer.A is bound multiple times:",
-                  "    @Provides Outer.A Outer.Module1.provideA1()",
-                  "    @Binds Outer.A Outer.Module2.bindA2(Outer.B)"))
+                  "test.Outer.A is bound multiple times:",
+                  "    @Provides test.Outer.A test.Outer.Module1.provideA1()",
+                  "    @Binds test.Outer.A test.Outer.Module2.bindA2(test.Outer.B)"))
           .inFile(component)
           .onLineContaining("class Module3");
     }
@@ -275,22 +268,20 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
-            .compile(component);
+        daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Set<String> has incompatible bindings or declarations:",
+                "java.util.Set<java.lang.String> has incompatible bindings or declarations:",
                 "    Set bindings and declarations:",
-                "        @Binds @IntoSet String "
-                    + "Outer.TestModule1.bindStringSetElement(@Outer.SomeQualifier "
+                "        @Binds @dagger.multibindings.IntoSet String "
+                    + "test.Outer.TestModule1.bindStringSetElement(@test.Outer.SomeQualifier "
                     + "String)",
-                "        @Provides @IntoSet String "
-                    + "Outer.TestModule1.stringSetElement()",
+                "        @Provides @dagger.multibindings.IntoSet String "
+                    + "test.Outer.TestModule1.stringSetElement()",
                 "    Unique bindings and declarations:",
-                "        @Provides Set<String> Outer.TestModule2.stringSet()"))
+                "        @Provides Set<String> test.Outer.TestModule2.stringSet()"))
         .inFile(component)
         .onLineContaining(
             fullBindingGraphValidation ? "class TestModule3" : "interface TestComponent");
@@ -346,23 +337,23 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
-            .compile(component);
+        daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Map<String,String> has incompatible bindings "
+                "java.util.Map<java.lang.String,java.lang.String> has incompatible bindings "
                     + "or declarations:",
                 "    Map bindings and declarations:",
-                "        @Binds @IntoMap @StringKey(\"bar\") String"
-                    + " Outer.TestModule1.bindStringMapEntry(@Outer.SomeQualifier "
+                "        @Binds @dagger.multibindings.IntoMap "
+                    + "@dagger.multibindings.StringKey(\"bar\") String"
+                    + " test.Outer.TestModule1.bindStringMapEntry(@test.Outer.SomeQualifier "
                     + "String)",
-                "        @Provides @IntoMap @StringKey(\"foo\") String"
-                    + " Outer.TestModule1.stringMapEntry()",
+                "        @Provides @dagger.multibindings.IntoMap "
+                    + "@dagger.multibindings.StringKey(\"foo\") String"
+                    + " test.Outer.TestModule1.stringMapEntry()",
                 "    Unique bindings and declarations:",
-                "        @Provides Map<String,String> Outer.TestModule2.stringMap()"))
+                "        @Provides Map<String,String> test.Outer.TestModule2.stringMap()"))
         .inFile(component)
         .onLineContaining(
             fullBindingGraphValidation ? "class TestModule3" : "interface TestComponent");
@@ -403,19 +394,17 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
-            .compile(component);
+        daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Set<String> has incompatible bindings or declarations:",
+                "java.util.Set<java.lang.String> has incompatible bindings or declarations:",
                 "    Set bindings and declarations:",
-                "        @Multibinds Set<String> "
-                    + "Outer.TestModule1.stringSet()",
+                "        @dagger.multibindings.Multibinds Set<String> "
+                    + "test.Outer.TestModule1.stringSet()",
                 "    Unique bindings and declarations:",
-                "        @Provides Set<String> Outer.TestModule2.stringSet()"))
+                "        @Provides Set<String> test.Outer.TestModule2.stringSet()"))
         .inFile(component)
         .onLineContaining(
             fullBindingGraphValidation ? "class TestModule3" : "interface TestComponent");
@@ -458,20 +447,18 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
-            .compile(component);
+        daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Map<String,String> has incompatible bindings "
+                "java.util.Map<java.lang.String,java.lang.String> has incompatible bindings "
                     + "or declarations:",
                 "    Map bindings and declarations:",
-                "        @Multibinds Map<String,String> "
-                    + "Outer.TestModule1.stringMap()",
+                "        @dagger.multibindings.Multibinds Map<String,String> "
+                    + "test.Outer.TestModule1.stringMap()",
                 "    Unique bindings and declarations:",
-                "        @Provides Map<String,String> Outer.TestModule2.stringMap()"))
+                "        @Provides Map<String,String> test.Outer.TestModule2.stringMap()"))
         .inFile(component)
         .onLineContaining(
             fullBindingGraphValidation ? "class TestModule3" : "interface TestComponent");
@@ -587,24 +574,22 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
-            .compile(component);
+        daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Outer.A is bound multiple times:",
-                "    @Provides Outer.A Outer.Module01.provideA()",
-                "    @Provides Outer.A Outer.Module02.provideA()",
-                "    @Provides Outer.A Outer.Module03.provideA()",
-                "    @Provides Outer.A Outer.Module04.provideA()",
-                "    @Provides Outer.A Outer.Module05.provideA()",
-                "    @Provides Outer.A Outer.Module06.provideA()",
-                "    @Provides Outer.A Outer.Module07.provideA()",
-                "    @Provides Outer.A Outer.Module08.provideA()",
-                "    @Provides Outer.A Outer.Module09.provideA()",
-                "    @Provides Outer.A Outer.Module10.provideA()",
+                "test.Outer.A is bound multiple times:",
+                "    @Provides test.Outer.A test.Outer.Module01.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module02.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module03.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module04.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module05.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module06.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module07.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module08.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module09.provideA()",
+                "    @Provides test.Outer.A test.Outer.Module10.provideA()",
                 "    and 2 others"))
         .inFile(component)
         .onLineContaining(fullBindingGraphValidation ? "class Modules" : "interface TestComponent");
@@ -661,14 +646,14 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
+        daggerCompiler()
+            .withOptions(fullBindingGraphValidationOption())
             .compile(aComponent, bComponent);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Object is bound multiple times:",
+                "java.lang.Object is bound multiple times:",
                 "    @Provides Object test.A.AModule.abConflict()",
                 "    @Provides Object test.B.BModule.abConflict()"))
         .inFile(aComponent)
@@ -742,14 +727,14 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
+        daggerCompiler()
+            .withOptions(fullBindingGraphValidationOption())
             .compile(aComponent, bComponent, cComponent);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Object is bound multiple times:",
+                "java.lang.Object is bound multiple times:",
                 "    @Provides Object test.A.AModule.acConflict()",
                 "    @Provides Object test.C.CModule.acConflict()"))
         .inFile(aComponent)
@@ -818,14 +803,14 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                fullBindingGraphValidationOption())
+        daggerCompiler()
+            .withOptions(fullBindingGraphValidationOption())
             .compile(aComponent, bComponent, cComponent);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Object is bound multiple times:",
+                "java.lang.Object is bound multiple times:",
                 "    @Provides Object test.B.BModule.bcConflict()",
                 "    @Provides Object test.C.CModule.bcConflict()"))
         .inFile(fullBindingGraphValidation ? bComponent : aComponent)
@@ -948,10 +933,10 @@
     assertThat(compilation)
         .hadWarningContaining(
             message(
-                "Foo is bound multiple times:",
-                "    @Inject Foo(Set<String>) [Injected1]",
-                "    @Provides Foo Provided1.Provided1Module.provideFoo(Set<String>) "
-                    + "[Injected1 → Injected2 → Provided1]"))
+                "test.Foo is bound multiple times:",
+                "    @Inject test.Foo(Set<String>) [test.Injected1]",
+                "    @Provides test.Foo test.Provided1.Provided1Module.provideFoo(Set<String>) "
+                    + "[test.Injected1 → test.Injected2 → test.Provided1]"))
         .inFile(injected1)
         .onLineContaining("interface Injected1 {");
   }
@@ -1006,18 +991,17 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(
-                "-Adagger.nullableValidation=WARNING",
-                fullBindingGraphValidationOption())
+        daggerCompiler()
+            .withOptions("-Adagger.nullableValidation=WARNING", fullBindingGraphValidationOption())
             .compile(parentConflictsWithChild, child);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Object is bound multiple times:",
-                "    @Provides Object Child.ChildModule.nonNullableParentChildConflict()",
-                "    @Provides @Nullable Object"
-                    + " ParentConflictsWithChild.ParentModule.nullableParentChildConflict()"))
+                "java.lang.Object is bound multiple times:",
+                "    @Provides Object test.Child.ChildModule.nonNullableParentChildConflict()",
+                "    @Provides @javax.annotation.Nullable Object"
+                    + " test.ParentConflictsWithChild.ParentModule.nullableParentChildConflict()"))
         .inFile(parentConflictsWithChild)
         .onLineContaining(
             fullBindingGraphValidation
@@ -1091,7 +1075,7 @@
     Compilation compilation = daggerCompiler().compile(parent, parentModule, child, childModule);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("String is bound multiple times")
+        .hadErrorContaining("java.lang.String is bound multiple times")
         .inFile(parent)
         .onLineContaining("interface Parent");
     assertThat(compilation).hadErrorCount(1);
diff --git a/javatests/dagger/internal/codegen/ElementDescriptorsTest.java b/javatests/dagger/internal/codegen/ElementDescriptorsTest.java
deleted file mode 100644
index e97e360..0000000
--- a/javatests/dagger/internal/codegen/ElementDescriptorsTest.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2019 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.common.truth.Truth.assertThat;
-
-import com.google.testing.compile.CompilationRule;
-import dagger.internal.codegen.langmodel.DaggerElements;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.ElementFilter;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class ElementDescriptorsTest {
-
-  @Rule public CompilationRule compilation = new CompilationRule();
-
-  static class TestClassA<T> {
-    int field1;
-    String field2;
-    T field3;
-    List<String> field4;
-  }
-
-  @Test
-  public void fieldDescriptor() {
-    assertThat(getFieldDescriptors(TestClassA.class.getCanonicalName()))
-        .containsExactly(
-            "field1:I",
-            "field2:Ljava/lang/String;",
-            "field3:Ljava/lang/Object;",
-            "field4:Ljava/util/List;");
-  }
-
-  static class TestClassB<T> {
-    void method1(boolean yesOrNo, int number) {}
-
-    byte method2(char letter) {
-      return 0;
-    }
-
-    void method3(double realNumber1, float realNummber2) {}
-
-    void method4(long bigNumber, short littlerNumber) {}
-  }
-
-  @Test
-  public void methodDescriptor_primitives() {
-    assertThat(getMethodDescriptors(TestClassB.class.getCanonicalName()))
-        .containsExactly("method1(ZI)V", "method2(C)B", "method3(DF)V", "method4(JS)V");
-  }
-
-  static class TestClassC<T> {
-    void method1(Object something) {}
-
-    Object method2() {
-      return null;
-    }
-
-    List<String> method3(ArrayList<Integer> list) {
-      return null;
-    }
-
-    Map<String, Object> method4() {
-      return null;
-    }
-  }
-
-  @Test
-  public void methodDescriptor_javaTypes() {
-    assertThat(getMethodDescriptors(TestClassC.class.getCanonicalName()))
-        .containsExactly(
-            "method1(Ljava/lang/Object;)V",
-            "method2()Ljava/lang/Object;",
-            "method3(Ljava/util/ArrayList;)Ljava/util/List;",
-            "method4()Ljava/util/Map;");
-  }
-
-  static class TestClassD<T> {
-    void method1(TestDataClass data) {}
-
-    TestDataClass method2() {
-      return null;
-    }
-  }
-
-  @Test
-  public void methodDescriptor_testTypes() {
-    assertThat(getMethodDescriptors(TestClassD.class.getCanonicalName()))
-        .containsExactly(
-            "method1(Ldagger/internal/codegen/TestDataClass;)V",
-            "method2()Ldagger/internal/codegen/TestDataClass;");
-  }
-
-  static class TestClassE<T> {
-    void method1(TestDataClass[] data) {}
-
-    TestDataClass[] method2() {
-      return null;
-    }
-
-    void method3(int[] array) {}
-
-    void method4(int... array) {}
-  }
-
-  @Test
-  public void methodDescriptor_arrays() {
-    assertThat(getMethodDescriptors(TestClassE.class.getCanonicalName()))
-        .containsExactly(
-            "method1([Ldagger/internal/codegen/TestDataClass;)V",
-            "method2()[Ldagger/internal/codegen/TestDataClass;",
-            "method3([I)V",
-            "method4([I)V");
-  }
-
-  static class TestClassF<T> {
-    void method1(TestDataClass.MemberInnerData data) {}
-
-    void method2(TestDataClass.StaticInnerData data) {}
-
-    void method3(TestDataClass.EnumData enumData) {}
-
-    TestDataClass.StaticInnerData method4() {
-      return null;
-    }
-  }
-
-  @Test
-  public void methodDescriptor_innerTestType() {
-    assertThat(getMethodDescriptors(TestClassF.class.getCanonicalName()))
-        .containsExactly(
-            "method1(Ldagger/internal/codegen/TestDataClass$MemberInnerData;)V",
-            "method2(Ldagger/internal/codegen/TestDataClass$StaticInnerData;)V",
-            "method3(Ldagger/internal/codegen/TestDataClass$EnumData;)V",
-            "method4()Ldagger/internal/codegen/TestDataClass$StaticInnerData;");
-  }
-
-  @SuppressWarnings("TypeParameterUnusedInFormals")
-  static class TestClassG<T> {
-    void method1(T something) {}
-
-    T method2() {
-      return null;
-    }
-
-    List<? extends String> method3() {
-      return null;
-    }
-
-    Map<T, String> method4() {
-      return null;
-    }
-
-    ArrayList<Map<T, String>> method5() {
-      return null;
-    }
-
-    static <I, O extends I> O method6(I input) {
-      return null;
-    }
-
-    static <I, O extends String> O method7(I input) {
-      return null;
-    }
-
-    static <P extends Collection<String> & Comparable<String>> P method8() {
-      return null;
-    }
-
-    static <P extends String & List<Character>> P method9() {
-      return null;
-    }
-  }
-
-  @Test
-  public void methodDescriptor_erasure() {
-    assertThat(getMethodDescriptors(TestClassG.class.getCanonicalName()))
-        .containsExactly(
-            "method1(Ljava/lang/Object;)V",
-            "method2()Ljava/lang/Object;",
-            "method3()Ljava/util/List;",
-            "method4()Ljava/util/Map;",
-            "method5()Ljava/util/ArrayList;",
-            "method6(Ljava/lang/Object;)Ljava/lang/Object;",
-            "method7(Ljava/lang/Object;)Ljava/lang/String;",
-            "method8()Ljava/util/Collection;",
-            "method9()Ljava/lang/String;");
-  }
-
-  private Set<String> getFieldDescriptors(String className) {
-    TypeElement testElement = compilation.getElements().getTypeElement(className);
-    return ElementFilter.fieldsIn(testElement.getEnclosedElements()).stream()
-        .map(DaggerElements::getFieldDescriptor)
-        .collect(Collectors.toSet());
-  }
-
-  private Set<String> getMethodDescriptors(String className) {
-    TypeElement testElement = compilation.getElements().getTypeElement(className);
-    return ElementFilter.methodsIn(testElement.getEnclosedElements()).stream()
-        .map(DaggerElements::getMethodDescriptor)
-        .collect(Collectors.toSet());
-  }
-}
-
-@SuppressWarnings("ClassCanBeStatic")
-class TestDataClass {
-  class MemberInnerData {}
-
-  static class StaticInnerData {}
-
-  enum EnumData {
-    VALUE1,
-    VALUE2
-  }
-}
diff --git a/javatests/dagger/internal/codegen/ElidedFactoriesTest.java b/javatests/dagger/internal/codegen/ElidedFactoriesTest.java
index 6857039..58ddb82 100644
--- a/javatests/dagger/internal/codegen/ElidedFactoriesTest.java
+++ b/javatests/dagger/internal/codegen/ElidedFactoriesTest.java
@@ -17,8 +17,8 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
@@ -84,7 +84,7 @@
             "",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerSimpleComponent implements SimpleComponent {",
             "  private DaggerSimpleComponent() {}",
             "",
@@ -112,7 +112,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(injectedType, dependsOnInjected, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -184,7 +185,7 @@
                 IMPORT_GENERATED_ANNOTATION,
                 "import javax.inject.Provider;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {",
                 "  private volatile Object scopedType = new MemoizedSentinel();",
                 "  private volatile Provider<DependsOnScoped> dependsOnScopedProvider;",
@@ -199,7 +200,7 @@
                 "    return new Builder().build();",
                 "  }",
                 "",
-                "  private ScopedType scopedType() {",
+                "  private ScopedType getScopedType() {",
                 "    Object local = scopedType;",
                 "    if (local instanceof MemoizedSentinel) {",
                 "      synchronized (local) {",
@@ -213,11 +214,11 @@
                 "    return (ScopedType) local;",
                 "  }",
                 "",
-                "  private DependsOnScoped dependsOnScoped() {",
-                "    return new DependsOnScoped(scopedType());",
+                "  private DependsOnScoped getDependsOnScoped() {",
+                "    return new DependsOnScoped(getScopedType());",
                 "  }",
                 "",
-                "  private Provider<DependsOnScoped> dependsOnScopedProvider() {",
+                "  private Provider<DependsOnScoped> getDependsOnScopedProvider() {",
                 "    Object local = dependsOnScopedProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(0);",
@@ -228,7 +229,7 @@
                 "",
                 "  @Override",
                 "  public NeedsProvider needsProvider() {",
-                "    return new NeedsProvider(dependsOnScopedProvider());",
+                "    return new NeedsProvider(getDependsOnScopedProvider());",
                 "  }",
                 "",
                 "  static final class Builder {",
@@ -249,7 +250,7 @@
                 "    @Override",
                 "    public T get() {",
                 "      switch (id) {",
-                "        case 0: return (T) DaggerSimpleComponent.this.dependsOnScoped();",
+                "        case 0: return (T) DaggerSimpleComponent.this.getDependsOnScoped();",
                 "        default: throw new AssertionError(id);",
                 "      }",
                 "    }",
@@ -266,7 +267,7 @@
                 IMPORT_GENERATED_ANNOTATION,
                 "import javax.inject.Provider;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {",
                 "  private Provider<ScopedType> scopedTypeProvider;",
                 "  private Provider<DependsOnScoped> dependsOnScopedProvider;",
@@ -306,7 +307,8 @@
                 "}");
     }
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(scopedType, dependsOnScoped, componentFile, needsProvider);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -377,7 +379,7 @@
                 "import dagger.internal.MemoizedSentinel;",
                 IMPORT_GENERATED_ANNOTATION,
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {",
                 "  private volatile Object scopedType = new MemoizedSentinel();",
                 "",
@@ -391,7 +393,7 @@
                 "    return new Builder().build();",
                 "  }",
                 "",
-                "  private ScopedType scopedType() {",
+                "  private ScopedType getScopedType() {",
                 "    Object local = scopedType;",
                 "    if (local instanceof MemoizedSentinel) {",
                 "      synchronized (local) {",
@@ -423,7 +425,7 @@
                 "",
                 "    @Override",
                 "    public DependsOnScoped dependsOnScoped() {",
-                "      return new DependsOnScoped(DaggerSimpleComponent.this.scopedType());",
+                "      return new DependsOnScoped(DaggerSimpleComponent.this.getScopedType());",
                 "    }",
                 "  }",
                 "}");
@@ -438,7 +440,7 @@
                 IMPORT_GENERATED_ANNOTATION,
                 "import javax.inject.Provider;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerSimpleComponent implements SimpleComponent {",
                 "  private Provider<ScopedType> scopedTypeProvider;",
                 "",
@@ -484,7 +486,8 @@
                 "}");
     }
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(scopedType, dependsOnScoped, componentFile, subcomponentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/FrameworkFieldTest.java b/javatests/dagger/internal/codegen/FrameworkFieldTest.java
index be495d7..cbc8c03 100644
--- a/javatests/dagger/internal/codegen/FrameworkFieldTest.java
+++ b/javatests/dagger/internal/codegen/FrameworkFieldTest.java
@@ -24,7 +24,6 @@
 
 import com.google.testing.compile.CompilationRule;
 import com.squareup.javapoet.ClassName;
-import dagger.internal.codegen.binding.FrameworkField;
 import javax.inject.Inject;
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/javatests/dagger/internal/codegen/FrameworkTypeMapperTest.java b/javatests/dagger/internal/codegen/FrameworkTypeMapperTest.java
index e27534d..3e6e3ad 100644
--- a/javatests/dagger/internal/codegen/FrameworkTypeMapperTest.java
+++ b/javatests/dagger/internal/codegen/FrameworkTypeMapperTest.java
@@ -23,8 +23,6 @@
 import static dagger.model.RequestKind.PRODUCER;
 import static dagger.model.RequestKind.PROVIDER;
 
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.binding.FrameworkTypeMapper;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/javatests/dagger/internal/codegen/FullBindingGraphValidationTest.java b/javatests/dagger/internal/codegen/FullBindingGraphValidationTest.java
index b56bc04..944e307 100644
--- a/javatests/dagger/internal/codegen/FullBindingGraphValidationTest.java
+++ b/javatests/dagger/internal/codegen/FullBindingGraphValidationTest.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
 import static dagger.internal.codegen.TestUtils.endsWithMessage;
 
@@ -49,35 +48,9 @@
   // Make sure the error doesn't show other bindings or a dependency trace afterwards.
   private static final Pattern MODULE_WITH_ERRORS_MESSAGE =
       endsWithMessage(
-          "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
-          "    @Binds Object ModuleWithErrors.object1(String)",
-          "    @Binds Object ModuleWithErrors.object2(Long)",
-          "    in component: [ModuleWithErrors]",
-          "",
-          "======================",
-          "Full classname legend:",
-          "======================",
-          "ModuleWithErrors: test.ModuleWithErrors",
-          "========================",
-          "End of classname legend:",
-          "========================");
-
-  private static final Pattern INCLUDES_MODULE_WITH_ERRORS_MESSAGE =
-      endsWithMessage(
-          "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
-          "    @Binds Object ModuleWithErrors.object1(String)",
-          "    @Binds Object ModuleWithErrors.object2(Long)",
-          "    in component: [IncludesModuleWithErrors]",
-          "",
-          "======================",
-          "Full classname legend:",
-          "======================",
-          "IncludesModuleWithErrors: test.IncludesModuleWithErrors",
-          "ModuleWithErrors:         test.ModuleWithErrors",
-          "========================",
-          "End of classname legend:",
-          "========================");
-
+          "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
+          "    @Binds Object test.ModuleWithErrors.object1(String)",
+          "    @Binds Object test.ModuleWithErrors.object2(Long)");
 
   @Test
   public void moduleWithErrors_validationTypeNone() {
@@ -88,7 +61,8 @@
   @Test
   public void moduleWithErrors_validationTypeError() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(MODULE_WITH_ERRORS);
 
     assertThat(compilation).failed();
@@ -104,7 +78,8 @@
   @Test
   public void moduleWithErrors_validationTypeWarning() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=WARNING")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
             .compile(MODULE_WITH_ERRORS);
 
     assertThat(compilation).succeeded();
@@ -138,7 +113,8 @@
   @Test
   public void includesModuleWithErrors_validationTypeError() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(MODULE_WITH_ERRORS, INCLUDES_MODULE_WITH_ERRORS);
 
     assertThat(compilation).failed();
@@ -149,7 +125,7 @@
         .onLineContaining("interface ModuleWithErrors");
 
     assertThat(compilation)
-        .hadErrorContainingMatch("ModuleWithErrors has errors")
+        .hadErrorContainingMatch("test.ModuleWithErrors has errors")
         .inFile(INCLUDES_MODULE_WITH_ERRORS)
         .onLineContaining("ModuleWithErrors.class");
 
@@ -159,7 +135,8 @@
   @Test
   public void includesModuleWithErrors_validationTypeWarning() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=WARNING")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
             .compile(MODULE_WITH_ERRORS, INCLUDES_MODULE_WITH_ERRORS);
 
     assertThat(compilation).succeeded();
@@ -171,7 +148,7 @@
 
     // TODO(b/130284666)
     assertThat(compilation)
-        .hadWarningContainingMatch(INCLUDES_MODULE_WITH_ERRORS_MESSAGE)
+        .hadWarningContainingMatch(MODULE_WITH_ERRORS_MESSAGE)
         .inFile(INCLUDES_MODULE_WITH_ERRORS)
         .onLineContaining("interface IncludesModuleWithErrors");
 
@@ -207,19 +184,9 @@
   // Make sure the error doesn't show other bindings or a dependency trace afterwards.
   private static final Pattern COMBINED_WITH_A_MODULE_HAS_ERRORS_MESSAGE =
       endsWithMessage(
-          "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
-          "    @Binds Object AModule.object(String)",
-          "    @Binds Object CombinedWithAModuleHasErrors.object(Long)",
-          "    in component: [CombinedWithAModuleHasErrors]",
-          "",
-          "======================",
-          "Full classname legend:",
-          "======================",
-          "AModule:                      test.AModule",
-          "CombinedWithAModuleHasErrors: test.CombinedWithAModuleHasErrors",
-          "========================",
-          "End of classname legend:",
-          "========================");
+          "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
+          "    @Binds Object test.AModule.object(String)",
+          "    @Binds Object test.CombinedWithAModuleHasErrors.object(Long)");
 
   @Test
   public void moduleIncludingModuleWithCombinedErrors_validationTypeNone() {
@@ -231,7 +198,8 @@
   @Test
   public void moduleIncludingModuleWithCombinedErrors_validationTypeError() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(A_MODULE, COMBINED_WITH_A_MODULE_HAS_ERRORS);
 
     assertThat(compilation).failed();
@@ -247,7 +215,8 @@
   @Test
   public void moduleIncludingModuleWithCombinedErrors_validationTypeWarning() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=WARNING")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
             .compile(A_MODULE, COMBINED_WITH_A_MODULE_HAS_ERRORS);
 
     assertThat(compilation).succeeded();
@@ -280,38 +249,10 @@
   // Make sure the error doesn't show other bindings or a dependency trace afterwards.
   private static final Pattern SUBCOMPONENT_WITH_ERRORS_MESSAGE =
       endsWithMessage(
-          "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
-          "    @Binds Object AModule.object(String)",
-          "    @BindsInstance SubcomponentWithErrors.Builder"
-              + " SubcomponentWithErrors.Builder.object(Object)",
-          "    in component: [SubcomponentWithErrors]",
-          "",
-          "======================",
-          "Full classname legend:",
-          "======================",
-          "AModule:                test.AModule",
-          "SubcomponentWithErrors: test.SubcomponentWithErrors",
-          "========================",
-          "End of classname legend:",
-          "========================");
-
-  private static final Pattern MODULE_WITH_SUBCOMPONENT_WITH_ERRORS_MESSAGE =
-      endsWithMessage(
-          "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
-          "    @Binds Object AModule.object(String)",
-          "    @BindsInstance SubcomponentWithErrors.Builder"
-              + " SubcomponentWithErrors.Builder.object(Object)",
-          "    in component: [ModuleWithSubcomponentWithErrors → SubcomponentWithErrors]",
-          "",
-          "======================",
-          "Full classname legend:",
-          "======================",
-          "AModule:                          test.AModule",
-          "ModuleWithSubcomponentWithErrors: test.ModuleWithSubcomponentWithErrors",
-          "SubcomponentWithErrors:           test.SubcomponentWithErrors",
-          "========================",
-          "End of classname legend:",
-          "========================");
+          "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
+          "    @Binds Object test.AModule.object(String)",
+          "    @BindsInstance test.SubcomponentWithErrors.Builder"
+              + " test.SubcomponentWithErrors.Builder.object(Object)");
 
   @Test
   public void subcomponentWithErrors_validationTypeNone() {
@@ -323,7 +264,8 @@
   @Test
   public void subcomponentWithErrors_validationTypeError() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(SUBCOMPONENT_WITH_ERRORS, A_MODULE);
 
     assertThat(compilation).failed();
@@ -339,7 +281,8 @@
   @Test
   public void subcomponentWithErrors_validationTypeWarning() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=WARNING")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
             .compile(SUBCOMPONENT_WITH_ERRORS, A_MODULE);
 
     assertThat(compilation).succeeded();
@@ -375,13 +318,14 @@
   @Test
   public void moduleWithSubcomponentWithErrors_validationTypeError() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS, SUBCOMPONENT_WITH_ERRORS, A_MODULE);
 
     assertThat(compilation).failed();
 
     assertThat(compilation)
-        .hadErrorContainingMatch(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS_MESSAGE)
+        .hadErrorContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE)
         .inFile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS)
         .onLineContaining("interface ModuleWithSubcomponentWithErrors");
 
@@ -397,13 +341,14 @@
   @Test
   public void moduleWithSubcomponentWithErrors_validationTypeWarning() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=WARNING")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
             .compile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS, SUBCOMPONENT_WITH_ERRORS, A_MODULE);
 
     assertThat(compilation).succeeded();
 
     assertThat(compilation)
-        .hadWarningContainingMatch(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS_MESSAGE)
+        .hadWarningContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE)
         .inFile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS)
         .onLineContaining("interface ModuleWithSubcomponentWithErrors");
 
@@ -448,20 +393,9 @@
   // Make sure the error doesn't show other bindings or a dependency trace afterwards.
   private static final Pattern COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS_MESSAGE =
       endsWithMessage(
-          "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
-          "    @Binds Object AModule.object(String)",
-          "    @Binds Object CombinedWithASubcomponentHasErrors.object(Number)",
-          "    in component: [CombinedWithASubcomponentHasErrors → ASubcomponent]",
-          "",
-          "======================",
-          "Full classname legend:",
-          "======================",
-          "AModule:                            test.AModule",
-          "ASubcomponent:                      test.ASubcomponent",
-          "CombinedWithASubcomponentHasErrors: test.CombinedWithASubcomponentHasErrors",
-          "========================",
-          "End of classname legend:",
-          "========================");
+          "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
+          "    @Binds Object test.AModule.object(String)",
+          "    @Binds Object test.CombinedWithASubcomponentHasErrors.object(Number)");
 
   @Test
   public void moduleWithSubcomponentWithCombinedErrors_validationTypeNone() {
@@ -474,7 +408,8 @@
   @Test
   public void moduleWithSubcomponentWithCombinedErrors_validationTypeError() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS, A_SUBCOMPONENT, A_MODULE);
 
     assertThat(compilation).failed();
@@ -490,7 +425,8 @@
   @Test
   public void moduleWithSubcomponentWithCombinedErrors_validationTypeWarning() {
     Compilation compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=WARNING")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
             .compile(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS, A_SUBCOMPONENT, A_MODULE);
 
     assertThat(compilation).succeeded();
@@ -506,7 +442,8 @@
   @Test
   public void bothAliasesDifferentValues() {
     Compilation compilation =
-        compilerWithOptions(
+        daggerCompiler()
+            .withOptions(
                 "-Adagger.moduleBindingValidation=NONE",
                 "-Adagger.fullBindingGraphValidation=ERROR")
             .compile(MODULE_WITH_ERRORS);
@@ -525,7 +462,8 @@
   @Test
   public void bothAliasesSameValue() {
     Compilation compilation =
-        compilerWithOptions(
+        daggerCompiler()
+            .withOptions(
                 "-Adagger.moduleBindingValidation=NONE", "-Adagger.fullBindingGraphValidation=NONE")
             .compile(MODULE_WITH_ERRORS);
 
diff --git a/javatests/dagger/internal/codegen/GeneratedLines.java b/javatests/dagger/internal/codegen/GeneratedLines.java
index f9a1b70..2aa17ac 100644
--- a/javatests/dagger/internal/codegen/GeneratedLines.java
+++ b/javatests/dagger/internal/codegen/GeneratedLines.java
@@ -16,7 +16,9 @@
 
 package dagger.internal.codegen;
 
-import com.google.common.base.Joiner;
+import static dagger.internal.codegen.javapoet.CodeBlocks.stringLiteral;
+
+import com.squareup.javapoet.CodeBlock;
 
 /**
  * Common lines outputted during code generation.
@@ -27,12 +29,6 @@
         + "value = \"dagger.internal.codegen.ComponentProcessor\", "
         + "comments = \"https://dagger.dev\")";
 
-  private static final String SUPPRESS_WARNINGS_ANNOTATION =
-      "@SuppressWarnings({\"unchecked\", \"rawtypes\"})";
-
-  public static final String GENERATED_CODE_ANNOTATIONS =
-      Joiner.on('\n').join(GENERATED_ANNOTATION, SUPPRESS_WARNINGS_ANNOTATION);
-
   public static final String IMPORT_GENERATED_ANNOTATION =
       isBeforeJava9()
           ? "import javax.annotation.Generated;"
@@ -48,4 +44,10 @@
       return true;
     }
   }
+
+  public static final CodeBlock NPE_FROM_PROVIDES_METHOD =
+      stringLiteral("Cannot return null from a non-@Nullable @Provides method");
+
+  public static final CodeBlock NPE_FROM_COMPONENT_METHOD =
+      stringLiteral("Cannot return null from a non-@Nullable component method");
 }
diff --git a/javatests/dagger/internal/codegen/InjectConstructorFactoryGeneratorTest.java b/javatests/dagger/internal/codegen/InjectConstructorFactoryGeneratorTest.java
index 579e87a..e6e9706 100644
--- a/javatests/dagger/internal/codegen/InjectConstructorFactoryGeneratorTest.java
+++ b/javatests/dagger/internal/codegen/InjectConstructorFactoryGeneratorTest.java
@@ -20,9 +20,8 @@
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
 
 import com.google.common.collect.ImmutableList;
@@ -138,7 +137,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class GenericClass_Factory<T> implements Factory<GenericClass<T>> {",
             "  private final Provider<T> tProvider;",
             "",
@@ -148,7 +147,7 @@
             "",
             "  @Override",
             "  public GenericClass<T> get() {",
-            "    return newInstance(tProvider.get());",
+            "    return new GenericClass<T>(tProvider.get());",
             "  }",
             "",
             "  public static <T> GenericClass_Factory<T> create(Provider<T> tProvider) {",
@@ -187,9 +186,8 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class GenericClass_Factory<A, B> implements",
-            "    Factory<GenericClass<A, B>> {",
+            GENERATED_ANNOTATION,
+            "public final class GenericClass_Factory<A, B> implements Factory<GenericClass<A, B>> {",
             "  private final Provider<A> aProvider;",
             "  private final Provider<B> bProvider;",
             "",
@@ -201,7 +199,7 @@
             "",
             "  @Override",
             "  public GenericClass<A, B> get() {",
-            "    GenericClass<A, B> instance = newInstance();",
+            "    GenericClass<A, B> instance = new GenericClass<A, B>();",
             "    GenericClass_MembersInjector.injectA(instance, aProvider.get());",
             "    GenericClass_MembersInjector.injectRegister(instance, bProvider.get());",
             "    return instance;",
@@ -239,26 +237,24 @@
             "import dagger.internal.Factory;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class GenericClass_Factory<T> implements Factory<GenericClass<T>> {",
+            "  @SuppressWarnings(\"rawtypes\")",
+            "  private static final GenericClass_Factory INSTANCE = new GenericClass_Factory();",
+            "",
             "  @Override",
             "  public GenericClass<T> get() {",
-            "    return newInstance();",
+            "    return new GenericClass<T>();",
             "  }",
             "",
             "  @SuppressWarnings(\"unchecked\")",
             "  public static <T> GenericClass_Factory<T> create() {",
-            "    return InstanceHolder.INSTANCE;",
+            "    return INSTANCE;",
             "  }",
             "",
             "  public static <T> GenericClass<T> newInstance() {",
             "    return new GenericClass<T>();",
             "  }",
-            "",
-            "  private static final class InstanceHolder {",
-            "    @SuppressWarnings(\"rawtypes\")",
-            "    private static final GenericClass_Factory INSTANCE = new GenericClass_Factory();",
-            "  }",
             "}");
     assertAbout(javaSource()).that(file)
         .processedWith(new ComponentProcessor())
@@ -284,9 +280,8 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class GenericClass_Factory<A, B>",
-            "    implements Factory<GenericClass<A, B>> {",
+            GENERATED_ANNOTATION,
+            "public final class GenericClass_Factory<A, B> implements Factory<GenericClass<A, B>> {",
             "  private final Provider<A> aProvider;",
             "  private final Provider<B> bProvider;",
             "",
@@ -297,7 +292,7 @@
             "",
             "  @Override",
             "  public GenericClass<A, B> get() {",
-            "    return newInstance(aProvider.get(), bProvider.get());",
+            "    return new GenericClass<A, B>(aProvider.get(), bProvider.get());",
             "  }",
             "",
             "  public static <A, B> GenericClass_Factory<A, B> create(",
@@ -337,7 +332,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class GenericClass_Factory<A extends Number & Comparable<A>,",
             "        B extends List<? extends String>,",
             "        C extends List<? super String>>",
@@ -356,7 +351,8 @@
             "",
             "  @Override",
             "  public GenericClass<A, B, C> get() {",
-            "    return newInstance(aProvider.get(), bProvider.get(), cProvider.get());",
+            "    return new GenericClass<A, B, C>(",
+            "        aProvider.get(), bProvider.get(), cProvider.get());",
             "  }",
             "",
             "  public static <A extends Number & Comparable<A>,",
@@ -405,110 +401,64 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class GenericClass_Factory<A, B>",
             "    implements Factory<GenericClass<A, B>> {",
-            "  private final Provider<A> aProvider;",
-            "  private final Provider<A> a2Provider;",
-            "  private final Provider<A> paProvider;",
+            "  private final Provider<A> aAndA2AndPaAndLaProvider;",
             "  private final Provider<A> qaProvider;",
-            "  private final Provider<A> laProvider;",
-            "  private final Provider<String> sProvider;",
-            "  private final Provider<String> s2Provider;",
-            "  private final Provider<String> psProvider;",
+            "  private final Provider<String> sAndS2AndPsAndLsProvider;",
             "  private final Provider<String> qsProvider;",
-            "  private final Provider<String> lsProvider;",
-            "  private final Provider<B> bProvider;",
-            "  private final Provider<B> b2Provider;",
-            "  private final Provider<B> pbProvider;",
+            "  private final Provider<B> bAndB2AndPbAndLbProvider;",
             "  private final Provider<B> qbProvider;",
-            "  private final Provider<B> lbProvider;",
             "",
-            "  public GenericClass_Factory(",
-            "      Provider<A> aProvider,",
-            "      Provider<A> a2Provider,",
-            "      Provider<A> paProvider,",
+            "  public GenericClass_Factory(Provider<A> aAndA2AndPaAndLaProvider,",
             "      Provider<A> qaProvider,",
-            "      Provider<A> laProvider,",
-            "      Provider<String> sProvider,",
-            "      Provider<String> s2Provider,",
-            "      Provider<String> psProvider,",
+            "      Provider<String> sAndS2AndPsAndLsProvider,",
             "      Provider<String> qsProvider,",
-            "      Provider<String> lsProvider,",
-            "      Provider<B> bProvider,",
-            "      Provider<B> b2Provider,",
-            "      Provider<B> pbProvider,",
-            "      Provider<B> qbProvider,",
-            "      Provider<B> lbProvider) {",
-            "    this.aProvider = aProvider;",
-            "    this.a2Provider = a2Provider;",
-            "    this.paProvider = paProvider;",
+            "      Provider<B> bAndB2AndPbAndLbProvider,",
+            "      Provider<B> qbProvider) {",
+            "    this.aAndA2AndPaAndLaProvider = aAndA2AndPaAndLaProvider;",
             "    this.qaProvider = qaProvider;",
-            "    this.laProvider = laProvider;",
-            "    this.sProvider = sProvider;",
-            "    this.s2Provider = s2Provider;",
-            "    this.psProvider = psProvider;",
+            "    this.sAndS2AndPsAndLsProvider = sAndS2AndPsAndLsProvider;",
             "    this.qsProvider = qsProvider;",
-            "    this.lsProvider = lsProvider;",
-            "    this.bProvider = bProvider;",
-            "    this.b2Provider = b2Provider;",
-            "    this.pbProvider = pbProvider;",
+            "    this.bAndB2AndPbAndLbProvider = bAndB2AndPbAndLbProvider;",
             "    this.qbProvider = qbProvider;",
-            "    this.lbProvider = lbProvider;",
             "  }",
             "",
             "  @Override",
             "  public GenericClass<A, B> get() {",
-            "    return newInstance(",
-            "        aProvider.get(),",
-            "        a2Provider.get(),",
-            "        paProvider,",
-            "        qaProvider.get(),",
-            "        DoubleCheck.lazy(laProvider),",
-            "        sProvider.get(),",
-            "        s2Provider.get(),",
-            "        psProvider,",
-            "        qsProvider.get(),",
-            "        DoubleCheck.lazy(lsProvider),",
-            "        bProvider.get(),",
-            "        b2Provider.get(),",
-            "        pbProvider,",
-            "        qbProvider.get(),",
-            "        DoubleCheck.lazy(lbProvider));",
+            "    return new GenericClass<A, B>(",
+            "      aAndA2AndPaAndLaProvider.get(),",
+            "      aAndA2AndPaAndLaProvider.get(),",
+            "      aAndA2AndPaAndLaProvider,",
+            "      qaProvider.get(),",
+            "      DoubleCheck.lazy(aAndA2AndPaAndLaProvider),",
+            "      sAndS2AndPsAndLsProvider.get(),",
+            "      sAndS2AndPsAndLsProvider.get(),",
+            "      sAndS2AndPsAndLsProvider,",
+            "      qsProvider.get(),",
+            "      DoubleCheck.lazy(sAndS2AndPsAndLsProvider),",
+            "      bAndB2AndPbAndLbProvider.get(),",
+            "      bAndB2AndPbAndLbProvider.get(),",
+            "      bAndB2AndPbAndLbProvider,",
+            "      qbProvider.get(),",
+            "      DoubleCheck.lazy(bAndB2AndPbAndLbProvider));",
             "  }",
             "",
             "  public static <A, B> GenericClass_Factory<A, B> create(",
-            "      Provider<A> aProvider,",
-            "      Provider<A> a2Provider,",
-            "      Provider<A> paProvider,",
+            "      Provider<A> aAndA2AndPaAndLaProvider,",
             "      Provider<A> qaProvider,",
-            "      Provider<A> laProvider,",
-            "      Provider<String> sProvider,",
-            "      Provider<String> s2Provider,",
-            "      Provider<String> psProvider,",
+            "      Provider<String> sAndS2AndPsAndLsProvider,",
             "      Provider<String> qsProvider,",
-            "      Provider<String> lsProvider,",
-            "      Provider<B> bProvider,",
-            "      Provider<B> b2Provider,",
-            "      Provider<B> pbProvider,",
-            "      Provider<B> qbProvider,",
-            "      Provider<B> lbProvider) {",
+            "      Provider<B> bAndB2AndPbAndLbProvider,",
+            "      Provider<B> qbProvider) {",
             "    return new GenericClass_Factory<A, B>(",
-            "        aProvider,",
-            "        a2Provider,",
-            "        paProvider,",
+            "        aAndA2AndPaAndLaProvider,",
             "        qaProvider,",
-            "        laProvider,",
-            "        sProvider,",
-            "        s2Provider,",
-            "        psProvider,",
+            "        sAndS2AndPsAndLsProvider,",
             "        qsProvider,",
-            "        lsProvider,",
-            "        bProvider,",
-            "        b2Provider,",
-            "        pbProvider,",
-            "        qbProvider,",
-            "        lbProvider);",
+            "        bAndB2AndPbAndLbProvider,",
+            "        qbProvider);",
             "  }",
             "",
             "  public static <A, B> GenericClass<A, B> newInstance(",
@@ -551,11 +501,11 @@
     Compilation compilation = daggerCompiler().compile(file);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("Types may only contain one injected constructor")
+        .hadErrorContaining("Types may only contain one @Inject constructor")
         .inFile(file)
         .onLine(6);
     assertThat(compilation)
-        .hadErrorContaining("Types may only contain one injected constructor")
+        .hadErrorContaining("Types may only contain one @Inject constructor")
         .inFile(file)
         .onLine(8);
   }
@@ -652,7 +602,7 @@
         "  @Inject CheckedExceptionClass() throws Exception {}",
         "}");
     Compilation compilation =
-        compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
+        daggerCompiler().withOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .hadWarningContaining("Dagger does not support checked exceptions on @Inject constructors")
@@ -691,7 +641,7 @@
         "  }",
         "}");
     Compilation compilation =
-        compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
+        daggerCompiler().withOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .hadWarningContaining("Dagger does not support injection into private classes")
@@ -734,7 +684,7 @@
         "  }",
         "}");
     Compilation compilation =
-        compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
+        daggerCompiler().withOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .hadWarningContaining("Dagger does not support injection into private classes")
@@ -786,7 +736,7 @@
         "  @Inject private String s;",
         "}");
     Compilation compilation =
-        compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
+        daggerCompiler().withOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
     assertThat(compilation).succeeded(); // TODO: Verify warning message when supported
   }
 
@@ -817,7 +767,7 @@
         "  @Inject static String s;",
         "}");
     Compilation compilation =
-        compilerWithOptions("-Adagger.staticMemberValidation=WARNING").compile(file);
+        daggerCompiler().withOptions("-Adagger.staticMemberValidation=WARNING").compile(file);
     assertThat(compilation).succeeded(); // TODO: Verify warning message when supported
   }
 
@@ -888,7 +838,7 @@
         "  @Inject private void method(){}",
         "}");
     Compilation compilation =
-        compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
+        daggerCompiler().withOptions("-Adagger.privateMemberValidation=WARNING").compile(file);
     assertThat(compilation).succeeded(); // TODO: Verify warning message when supported
   }
 
@@ -919,7 +869,7 @@
         "  @Inject static void method(){}",
         "}");
     Compilation compilation =
-        compilerWithOptions("-Adagger.staticMemberValidation=WARNING").compile(file);
+        daggerCompiler().withOptions("-Adagger.staticMemberValidation=WARNING").compile(file);
     assertThat(compilation).succeeded(); // TODO: Verify warning message when supported
   }
 
@@ -1053,7 +1003,6 @@
         .hadErrorContaining("Producer may only be injected in @Produces methods");
   }
 
-
   @Test public void injectConstructor() {
     JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor",
         "package test;",
@@ -1072,7 +1021,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class InjectConstructor_Factory ",
             "    implements Factory<InjectConstructor> {",
             "",
@@ -1083,7 +1032,7 @@
             "  }",
             "",
             "  @Override public InjectConstructor get() {",
-            "    return newInstance(sProvider.get());",
+            "    return new InjectConstructor(sProvider.get());",
             "  }",
             "",
             "  public static InjectConstructor_Factory create(Provider<String> sProvider) {",
@@ -1119,39 +1068,28 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class AllInjections_Factory implements Factory<AllInjections> {",
             "  private final Provider<String> sProvider;",
-            "  private final Provider<String> sProvider2;",
-            "  private final Provider<String> sProvider3;",
             "",
-            "  public AllInjections_Factory(",
-            "      Provider<String> sProvider,",
-            "      Provider<String> sProvider2,",
-            "      Provider<String> sProvider3) {",
+            "  public AllInjections_Factory(Provider<String> sProvider) {",
             "    this.sProvider = sProvider;",
-            "    this.sProvider2 = sProvider2;",
-            "    this.sProvider3 = sProvider3;",
             "  }",
             "",
-            "  @Override",
-            "  public AllInjections get() {",
-            "    AllInjections instance = newInstance(sProvider.get());",
-            "    AllInjections_MembersInjector.injectS(instance, sProvider2.get());",
-            "    AllInjections_MembersInjector.injectS2(instance, sProvider3.get());",
+            "  @Override public AllInjections get() {",
+            "    AllInjections instance = new AllInjections(sProvider.get());",
+            "    AllInjections_MembersInjector.injectS(instance, sProvider.get());",
+            "    AllInjections_MembersInjector.injectS2(instance, sProvider.get());",
             "    return instance;",
             "  }",
             "",
-            "  public static AllInjections_Factory create(",
-            "      Provider<String> sProvider,",
-            "      Provider<String> sProvider2,",
-            "      Provider<String> sProvider3) {",
-            "    return new AllInjections_Factory(sProvider, sProvider2, sProvider3);",
+            "  public static AllInjections_Factory create(Provider<String> sProvider) {",
+            "    return new AllInjections_Factory(sProvider);",
             "  }",
             "",
             "  public static AllInjections newInstance(String s) {",
-            "    return new AllInjections(s);",
-            "  }",
+            "     return new AllInjections(s);",
+            "   }",
             "}");
     assertAbout(javaSource()).that(file).processedWith(new ComponentProcessor())
         .compilesWithoutError()
@@ -1180,7 +1118,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class InjectConstructor_Factory ",
             "    implements Factory<InjectConstructor> {",
             "",
@@ -1191,7 +1129,7 @@
             "  }",
             "",
             "  @Override public InjectConstructor get() {",
-            "    return newInstance(objectsProvider.get());",
+            "    return new InjectConstructor(objectsProvider.get());",
             "  }",
             "",
             "  public static InjectConstructor_Factory create(",
@@ -1232,7 +1170,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class InjectConstructor_Factory ",
             "    implements Factory<InjectConstructor> {",
             "",
@@ -1243,7 +1181,7 @@
             "  }",
             "",
             "  @Override public InjectConstructor get() {",
-            "    return newInstance(factoryProvider.get());",
+            "    return new InjectConstructor(factoryProvider.get());",
             "  }",
             "",
             "  public static InjectConstructor_Factory create(",
@@ -1289,7 +1227,7 @@
             "import javax.inject.Provider;",
             "import other.pkg.Outer;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class InjectConstructor_Factory ",
             "    implements Factory<InjectConstructor> {",
             "",
@@ -1300,7 +1238,7 @@
             "  }",
             "",
             "  @Override public InjectConstructor get() {",
-            "    return newInstance(factoryProvider.get());",
+            "    return new InjectConstructor(factoryProvider.get());",
             "  }",
             "",
             "  public static InjectConstructor_Factory create(",
@@ -1347,7 +1285,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class InjectConstructor_Factory ",
             "    implements Factory<InjectConstructor> {",
             "",
@@ -1362,7 +1300,8 @@
             "  }",
             "",
             "  @Override public InjectConstructor get() {",
-            "    return newInstance(otherPackageProvider.get(), samePackageProvider.get());",
+            "    return new InjectConstructor(",
+            "        otherPackageProvider.get(), samePackageProvider.get());",
             "  }",
             "",
             "  public static InjectConstructor_Factory create(",
@@ -1401,23 +1340,21 @@
             "import dagger.internal.Factory;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class SimpleType_Factory implements Factory<SimpleType> {",
+            "  private static final SimpleType_Factory INSTANCE = new SimpleType_Factory();",
+            "",
             "  @Override public SimpleType get() {",
-            "    return newInstance();",
+            "    return new SimpleType();",
             "  }",
             "",
             "  public static SimpleType_Factory create() {",
-            "    return InstanceHolder.INSTANCE;",
+            "    return INSTANCE;",
             "  }",
             "",
             "  public static SimpleType newInstance() {",
             "    return new SimpleType();",
             "  }",
-            "",
-            "  private static final class InstanceHolder {",
-            "    private static final SimpleType_Factory INSTANCE = new SimpleType_Factory();",
-            "  }",
             "}");
     assertAbout(javaSource())
         .that(simpleType)
@@ -1449,23 +1386,21 @@
             "import dagger.internal.Factory;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class OuterType_A_Factory implements Factory<OuterType.A> {",
+            "  private static final OuterType_A_Factory INSTANCE = new OuterType_A_Factory();",
+            "",
             "  @Override public OuterType.A get() {",
-            "    return newInstance();",
+            "    return new OuterType.A();",
             "  }",
             "",
             "  public static OuterType_A_Factory create() {",
-            "    return InstanceHolder.INSTANCE;",
+            "    return INSTANCE;",
             "  }",
             "",
             "  public static OuterType.A newInstance() {",
             "    return new OuterType.A();",
             "  }",
-            "",
-            "  private static final class InstanceHolder {",
-            "    private static final OuterType_A_Factory INSTANCE = new OuterType_A_Factory();",
-            "  }",
             "}");
     assertAbout(javaSources()).that(ImmutableList.of(nestedTypesFile))
         .processedWith(new ComponentProcessor())
diff --git a/javatests/dagger/internal/codegen/KeyFactoryTest.java b/javatests/dagger/internal/codegen/KeyFactoryTest.java
index fdf62cb..d526ec9 100644
--- a/javatests/dagger/internal/codegen/KeyFactoryTest.java
+++ b/javatests/dagger/internal/codegen/KeyFactoryTest.java
@@ -24,11 +24,8 @@
 import com.google.common.collect.Iterables;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.testing.compile.CompilationRule;
-import dagger.BindsInstance;
-import dagger.Component;
 import dagger.Module;
 import dagger.Provides;
-import dagger.internal.codegen.binding.KeyFactory;
 import dagger.internal.codegen.langmodel.DaggerElements;
 import dagger.internal.codegen.langmodel.DaggerTypes;
 import dagger.model.Key;
@@ -41,7 +38,6 @@
 import java.util.Set;
 import javax.inject.Inject;
 import javax.inject.Qualifier;
-import javax.inject.Singleton;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
@@ -61,12 +57,16 @@
 public class KeyFactoryTest {
   @Rule public CompilationRule compilationRule = new CompilationRule();
 
-  @Inject DaggerElements elements;
-  @Inject DaggerTypes types;
-  @Inject KeyFactory keyFactory;
+  private DaggerElements elements;
+  private DaggerTypes types;
+  private KeyFactory keyFactory;
 
   @Before public void setUp() {
-    DaggerKeyFactoryTest_TestComponent.factory().create(compilationRule).inject(this);
+    this.elements = new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
+    this.types = new DaggerTypes(compilationRule.getTypes(), elements);
+    TypeProtoConverter typeProtoConverter = new TypeProtoConverter(types, elements);
+    this.keyFactory = new KeyFactory(
+        types, elements, typeProtoConverter, new AnnotationProtoConverter(typeProtoConverter));
   }
 
   @Test public void forInjectConstructorWithResolvedType() {
@@ -250,7 +250,7 @@
     ExecutableElement integerMethod = Iterables.getOnlyElement(
         ElementFilter.methodsIn(boxedPrimitiveHolder.getEnclosedElements()));
 
-    // TODO(user): Truth subject for TypeMirror and TypeElement
+    // TODO(cgruber): Truth subject for TypeMirror and TypeElement
     TypeMirror intType = intMethod.getReturnType();
     assertThat(intType.getKind().isPrimitive()).isTrue();
     TypeMirror integerType = integerMethod.getReturnType();
@@ -329,28 +329,4 @@
       throw new UnsupportedOperationException();
     }
   }
-
-  @Singleton
-  @Component(modules = {TestModule.class})
-  interface TestComponent {
-    void inject(KeyFactoryTest test);
-
-    @Component.Factory
-    interface Factory {
-      TestComponent create(@BindsInstance CompilationRule compilationRule);
-    }
-  }
-
-  @Module
-  static class TestModule {
-    @Provides
-    static DaggerElements elements(CompilationRule compilationRule) {
-      return new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
-    }
-
-    @Provides
-    static DaggerTypes types(CompilationRule compilationRule, DaggerElements elements) {
-      return new DaggerTypes(compilationRule.getTypes(), elements);
-    }
-  }
 }
diff --git a/javatests/dagger/internal/codegen/KotlinInjectedQualifier.kt b/javatests/dagger/internal/codegen/KotlinInjectedQualifier.kt
deleted file mode 100644
index 05e2758..0000000
--- a/javatests/dagger/internal/codegen/KotlinInjectedQualifier.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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 javax.inject.Inject
-import javax.inject.Named
-
-class KotlinInjectedQualifier {
-  @Inject
-  @Named("TheString")
-  lateinit var qualifiedString: String
-}
diff --git a/javatests/dagger/internal/codegen/KotlinObjectWithMemberInjection.kt b/javatests/dagger/internal/codegen/KotlinObjectWithMemberInjection.kt
deleted file mode 100644
index 619c1dd..0000000
--- a/javatests/dagger/internal/codegen/KotlinObjectWithMemberInjection.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 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 javax.inject.Inject
-
-object KotlinObjectWithMemberInjection {
-  @Inject
-  lateinit var property: String
-}
-
-object KotlinObjectWithSetterMemberInjection {
-  @set:Inject
-  lateinit var setterProperty: String
-}
-
-class KotlinClassWithMemberInjectedCompanion {
-  companion object {
-    @Inject
-    lateinit var property: String
-  }
-}
-
-class KotlinClassWithSetterMemberInjectedCompanion {
-  companion object {
-    @set:Inject
-    lateinit var setterProperty: String
-  }
-}
-
-class KotlinClassWithMemberInjectedNamedCompanion {
-  companion object TheCompanion {
-    @Inject
-    lateinit var property: String
-  }
-}
-
-class KotlinClassWithSetterMemberInjectedNamedCompanion {
-  companion object TheCompanion {
-    @set:Inject
-    lateinit var setterProperty: String
-  }
-}
diff --git a/javatests/dagger/internal/codegen/MapBindingComponentProcessorTest.java b/javatests/dagger/internal/codegen/MapBindingComponentProcessorTest.java
index ed9dd65..ad48712 100644
--- a/javatests/dagger/internal/codegen/MapBindingComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/MapBindingComponentProcessorTest.java
@@ -17,9 +17,8 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
@@ -129,7 +128,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final MapModuleOne mapModuleOne;",
                 "  private final MapModuleTwo mapModuleTwo;",
@@ -138,7 +137,7 @@
                 "  private volatile Provider<Map<PathEnum, Provider<Handler>>>",
                 "      mapOfPathEnumAndProviderOfHandlerProvider;",
                 "",
-                "  private Provider<Handler> provideAdminHandlerProvider() {",
+                "  private Provider<Handler> getProvideAdminHandlerProvider() {",
                 "    Object local = provideAdminHandlerProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(1);",
@@ -147,7 +146,7 @@
                 "    return (Provider<Handler>) local;",
                 "  }",
                 "",
-                "  private Provider<Handler> provideLoginHandlerProvider() {",
+                "  private Provider<Handler> getProvideLoginHandlerProvider() {",
                 "    Object local = provideLoginHandlerProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(2);",
@@ -157,10 +156,10 @@
                 "  }",
                 "",
                 "  private Map<PathEnum, Provider<Handler>>",
-                "        mapOfPathEnumAndProviderOfHandler() {",
+                "        getMapOfPathEnumAndProviderOfHandler() {",
                 "    return ImmutableMap.<PathEnum, Provider<Handler>>of(",
-                "        PathEnum.ADMIN, provideAdminHandlerProvider(),",
-                "        PathEnum.LOGIN, provideLoginHandlerProvider());",
+                "        PathEnum.ADMIN, getProvideAdminHandlerProvider(),",
+                "        PathEnum.LOGIN, getProvideLoginHandlerProvider());",
                 "  }",
                 "",
                 "  @Override",
@@ -187,7 +186,7 @@
                 "      switch (id) {",
                 "        case 0:",
                 "            return (T) DaggerTestComponent.this",
-                "                 .mapOfPathEnumAndProviderOfHandler();",
+                "                 .getMapOfPathEnumAndProviderOfHandler();",
                 "        case 1:",
                 "            return (T) MapModuleOne_ProvideAdminHandlerFactory",
                 "                .provideAdminHandler(DaggerTestComponent.this.mapModuleOne);",
@@ -206,7 +205,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private Provider<Handler> provideAdminHandlerProvider;",
                 "  private Provider<Handler> provideLoginHandlerProvider;",
@@ -235,7 +234,8 @@
                 "}");
     }
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 mapModuleOneFile,
                 mapModuleTwoFile,
@@ -357,7 +357,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private Provider<Map<Class<?>, Integer>> mapOfClassOfAndIntegerProvider;",
                 "",
@@ -367,7 +367,7 @@
                 "  private Provider<Map<MapKeys.ComplexKey, Integer>>",
                 "      mapOfComplexKeyAndIntegerProvider;",
                 "",
-                "  private Map mapOfPackagePrivateEnumAndInteger() {",
+                "  private Map getMapOfPackagePrivateEnumAndInteger() {",
                 "    return ImmutableMap.of(",
                 "        MapModule_EnumKeyMapKey.create(), MapModule.enumKey());",
                 "  }",
@@ -411,7 +411,7 @@
                 "",
                 "  @Override",
                 "  public Object inaccessibleEnum() {",
-                "    return mapOfPackagePrivateEnumAndInteger();",
+                "    return getMapOfPackagePrivateEnumAndInteger();",
                 "  }",
                 "",
                 "  @Override",
@@ -443,7 +443,7 @@
                 "mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey",
                 "package mapkeys;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "public final class MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey {",
                 "  public static MapKeys.ComplexKey create() {",
                 "    return MapKeys_ComplexKeyCreator.createComplexKey(",
@@ -459,7 +459,7 @@
                 "mapkeys.MapModule_ClassKeyMapKey",
                 "package mapkeys;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "public final class MapModule_ClassKeyMapKey {",
                 "  public static Class<?> create() {",
                 "    return MapKeys.Inaccessible.class;",
@@ -536,7 +536,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final MapModuleOne mapModuleOne;",
                 "  private final MapModuleTwo mapModuleTwo;",
@@ -545,7 +545,7 @@
                 "  private volatile Provider<Map<String, Provider<Handler>>>",
                 "      mapOfStringAndProviderOfHandlerProvider;",
                 "",
-                "  private Provider<Handler> provideAdminHandlerProvider() {",
+                "  private Provider<Handler> getProvideAdminHandlerProvider() {",
                 "    Object local = provideAdminHandlerProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(1);",
@@ -554,7 +554,7 @@
                 "    return (Provider<Handler>) local;",
                 "  }",
                 "",
-                "  private Provider<Handler> provideLoginHandlerProvider() {",
+                "  private Provider<Handler> getProvideLoginHandlerProvider() {",
                 "    Object local = provideLoginHandlerProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(2);",
@@ -564,10 +564,10 @@
                 "  }",
                 "",
                 "  private Map<String, Provider<Handler>>",
-                "        mapOfStringAndProviderOfHandler() {",
+                "        getMapOfStringAndProviderOfHandler() {",
                 "    return ImmutableMap.<String, Provider<Handler>>of(",
-                "        \"Admin\", provideAdminHandlerProvider(),",
-                "        \"Login\", provideLoginHandlerProvider());",
+                "        \"Admin\", getProvideAdminHandlerProvider(),",
+                "        \"Login\", getProvideLoginHandlerProvider());",
                 "  }",
                 "",
                 "  @Override",
@@ -594,7 +594,7 @@
                 "      switch (id) {",
                 "        case 0:",
                 "            return (T) DaggerTestComponent.this",
-                "                 .mapOfStringAndProviderOfHandler();",
+                "                 .getMapOfStringAndProviderOfHandler();",
                 "        case 1:",
                 "            return (T) MapModuleOne_ProvideAdminHandlerFactory",
                 "                .provideAdminHandler(DaggerTestComponent.this.mapModuleOne);",
@@ -613,7 +613,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private Provider<Handler> provideAdminHandlerProvider;",
                 "  private Provider<Handler> provideLoginHandlerProvider;",
@@ -642,7 +642,8 @@
                 "}");
     }
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 mapModuleOneFile,
                 mapModuleTwoFile,
@@ -736,7 +737,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final MapModuleOne mapModuleOne;",
                 "  private final MapModuleTwo mapModuleTwo;",
@@ -752,7 +753,7 @@
                 "    this.mapModuleTwo = mapModuleTwoParam;",
                 "  }",
                 "",
-                "  private Provider<Handler> provideAdminHandlerProvider() {",
+                "  private Provider<Handler> getProvideAdminHandlerProvider() {",
                 "    Object local = provideAdminHandlerProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(1);",
@@ -761,7 +762,7 @@
                 "    return (Provider<Handler>) local;",
                 "  }",
                 "",
-                "  private Provider<Handler> provideLoginHandlerProvider() {",
+                "  private Provider<Handler> getProvideLoginHandlerProvider() {",
                 "    Object local = provideLoginHandlerProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(2);",
@@ -771,12 +772,12 @@
                 "  }",
                 "",
                 "  private Map<WrappedClassKey, Provider<Handler>>",
-                "      mapOfWrappedClassKeyAndProviderOfHandler() {",
+                "      getMapOfWrappedClassKeyAndProviderOfHandler() {",
                 "    return ImmutableMap.<WrappedClassKey, Provider<Handler>>of(",
                 "        WrappedClassKeyCreator.createWrappedClassKey(Integer.class),",
-                "        provideAdminHandlerProvider(),",
+                "        getProvideAdminHandlerProvider(),",
                 "        WrappedClassKeyCreator.createWrappedClassKey(Long.class),",
-                "        provideLoginHandlerProvider());",
+                "        getProvideLoginHandlerProvider());",
                 "  }",
                 "",
                 "  @Override",
@@ -803,7 +804,7 @@
                 "      switch (id) {",
                 "        case 0:",
                 "            return (T) DaggerTestComponent.this",
-                "                 .mapOfWrappedClassKeyAndProviderOfHandler();",
+                "                 .getMapOfWrappedClassKeyAndProviderOfHandler();",
                 "        case 1:",
                 "            return (T) MapModuleOne_ProvideAdminHandlerFactory",
                 "                .provideAdminHandler(DaggerTestComponent.this.mapModuleOne);",
@@ -822,7 +823,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private Provider<Handler> provideAdminHandlerProvider;",
                 "  private Provider<Handler> provideLoginHandlerProvider;",
@@ -853,7 +854,8 @@
                 "}");
     }
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 mapModuleOneFile,
                 mapModuleTwoFile,
@@ -949,14 +951,14 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final MapModuleOne mapModuleOne;",
                 "  private final MapModuleTwo mapModuleTwo;",
                 "  private volatile Provider<Map<PathEnum, Handler>>",
                 "      mapOfPathEnumAndHandlerProvider;",
                 "",
-                "  private Map<PathEnum, Handler> mapOfPathEnumAndHandler() {",
+                "  private Map<PathEnum, Handler> getMapOfPathEnumAndHandler() {",
                 "    return ImmutableMap.<PathEnum, Handler>of(",
                 "        PathEnum.ADMIN,",
                 "        MapModuleOne_ProvideAdminHandlerFactory.provideAdminHandler(",
@@ -987,7 +989,7 @@
                 "    @Override",
                 "    public T get() {",
                 "      switch (id) {",
-                "        case 0: return (T) DaggerTestComponent.this.mapOfPathEnumAndHandler();",
+                "        case 0: return (T) DaggerTestComponent.this.getMapOfPathEnumAndHandler();",
                 "        default: throw new AssertionError(id);",
                 "      }",
                 "    }",
@@ -1000,7 +1002,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private Provider<Handler> provideAdminHandlerProvider;",
                 "  private Provider<Handler> provideLoginHandlerProvider;",
@@ -1028,7 +1030,8 @@
                 "}");
     }
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 mapModuleOneFile,
                 mapModuleTwoFile,
@@ -1077,7 +1080,7 @@
             "test.DaggerTestComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  private final MapModule mapModule;",
             "",
@@ -1087,7 +1090,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(mapModuleFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/MapBindingExpressionTest.java b/javatests/dagger/internal/codegen/MapBindingExpressionTest.java
index 3f33bd5..11f6bc1 100644
--- a/javatests/dagger/internal/codegen/MapBindingExpressionTest.java
+++ b/javatests/dagger/internal/codegen/MapBindingExpressionTest.java
@@ -20,8 +20,8 @@
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
 import static dagger.internal.codegen.Compilers.CLASS_PATH_WITHOUT_GUAVA_OPTION;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.Compiler;
@@ -92,7 +92,7 @@
                 "",
                 "import dagger.internal.MapBuilder;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {")
             .addLinesIn(
                 FAST_INIT_MODE,
@@ -101,7 +101,7 @@
                 "  private volatile Provider<Long> provideLong1Provider;",
                 "  private volatile Provider<Long> provideLong2Provider;",
                 "",
-                "  private Provider<Integer> provideIntProvider() {",
+                "  private Provider<Integer> getProvideIntProvider() {",
                 "    Object local = provideIntProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(0);",
@@ -110,7 +110,7 @@
                 "    return (Provider<Integer>) local;",
                 "  }",
                 "",
-                "  private Provider<Long> provideLong0Provider() {",
+                "  private Provider<Long> getProvideLong0Provider() {",
                 "    Object local = provideLong0Provider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(1);",
@@ -119,7 +119,7 @@
                 "    return (Provider<Long>) local;",
                 "  }",
                 "",
-                "  private Provider<Long> provideLong1Provider() {",
+                "  private Provider<Long> getProvideLong1Provider() {",
                 "    Object local = provideLong1Provider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(2);",
@@ -128,7 +128,7 @@
                 "    return (Provider<Long>) local;",
                 "  }",
                 "",
-                "  private Provider<Long> provideLong2Provider() {",
+                "  private Provider<Long> getProvideLong2Provider() {",
                 "    Object local = provideLong2Provider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(3);",
@@ -160,7 +160,7 @@
                 "        0, MapModule_ProvideIntFactory.create());")
             .addLinesIn(
                 FAST_INIT_MODE,
-                "        0, provideIntProvider());")
+                "        0, getProvideIntProvider());")
             .addLines(
                 "  }",
                 "",
@@ -183,9 +183,9 @@
                 "        .put(2L, MapModule_ProvideLong2Factory.create())")
             .addLinesIn(
                 FAST_INIT_MODE,
-                "        .put(0L, provideLong0Provider())",
-                "        .put(1L, provideLong1Provider())",
-                "        .put(2L, provideLong2Provider())")
+                "        .put(0L, getProvideLong0Provider())",
+                "        .put(1L, getProvideLong1Provider())",
+                "        .put(2L, getProvideLong2Provider())")
             .addLines( //
                 "        .build();", "  }")
             .addLinesIn(
@@ -274,7 +274,7 @@
             "import other.UsesInaccessible;",
             "import other.UsesInaccessible_Factory;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  @Override",
             "  public UsesInaccessible usesInaccessible() {",
@@ -337,7 +337,7 @@
             "test.DaggerParent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParent implements Parent {",
             "  private final ParentModule parentModule;",
             "",
@@ -360,7 +360,7 @@
   }
 
   private Compiler daggerCompilerWithoutGuava() {
-    return compilerWithOptions(compilerMode.javacopts())
-        .withClasspath(CLASS_PATH_WITHOUT_GUAVA_OPTION);
+    return daggerCompiler()
+        .withOptions(compilerMode.javacopts().append(CLASS_PATH_WITHOUT_GUAVA_OPTION));
   }
 }
diff --git a/javatests/dagger/internal/codegen/MapBindingExpressionWithGuavaTest.java b/javatests/dagger/internal/codegen/MapBindingExpressionWithGuavaTest.java
index 69ab5a7..aa1a715 100644
--- a/javatests/dagger/internal/codegen/MapBindingExpressionWithGuavaTest.java
+++ b/javatests/dagger/internal/codegen/MapBindingExpressionWithGuavaTest.java
@@ -20,7 +20,8 @@
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
 import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
@@ -127,7 +128,7 @@
             .addLines(
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {")
             .addLinesIn(
                 FAST_INIT_MODE,
@@ -136,7 +137,7 @@
                 "  private volatile Provider<Long> provideLong1Provider;",
                 "  private volatile Provider<Long> provideLong2Provider;",
                 "",
-                "  private Provider<Integer> provideIntProvider() {",
+                "  private Provider<Integer> getProvideIntProvider() {",
                 "    Object local = provideIntProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(0);",
@@ -145,7 +146,7 @@
                 "    return (Provider<Integer>) local;",
                 "  }",
                 "",
-                "  private Provider<Long> provideLong0Provider() {",
+                "  private Provider<Long> getProvideLong0Provider() {",
                 "    Object local = provideLong0Provider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(1);",
@@ -154,7 +155,7 @@
                 "    return (Provider<Long>) local;",
                 "  }",
                 "",
-                "  private Provider<Long> provideLong1Provider() {",
+                "  private Provider<Long> getProvideLong1Provider() {",
                 "    Object local = provideLong1Provider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(2);",
@@ -163,7 +164,7 @@
                 "    return (Provider<Long>) local;",
                 "  }",
                 "",
-                "  private Provider<Long> provideLong2Provider() {",
+                "  private Provider<Long> getProvideLong2Provider() {",
                 "    Object local = provideLong2Provider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(3);",
@@ -195,7 +196,7 @@
                 "        0, MapModule_ProvideIntFactory.create());")
             .addLinesIn(
                 FAST_INIT_MODE, //
-                "        0, provideIntProvider());")
+                "        0, getProvideIntProvider());")
             .addLines(
                 "  }",
                 "",
@@ -217,9 +218,9 @@
                 "      2L, MapModule_ProvideLong2Factory.create());")
             .addLinesIn(
                 FAST_INIT_MODE,
-                "      0L, provideLong0Provider(),",
-                "      1L, provideLong1Provider(),",
-                "      2L, provideLong2Provider());")
+                "      0L, getProvideLong0Provider(),",
+                "      1L, getProvideLong1Provider(),",
+                "      2L, getProvideLong2Provider());")
             .addLines(
                 "  }",
                 "",
@@ -236,7 +237,7 @@
                 "    private volatile Provider<Long> provideLong5Provider;",
                 "    private SubImpl() {}",
                 "",
-                "    private Provider<Long> provideLong3Provider() {",
+                "    private Provider<Long> getProvideLong3Provider() {",
                 "      Object local = provideLong3Provider;",
                 "      if (local == null) {",
                 "        local = new SwitchingProvider<>(0);",
@@ -245,7 +246,7 @@
                 "      return (Provider<Long>) local;",
                 "    }",
                 "",
-                "    private Provider<Long> provideLong4Provider() {",
+                "    private Provider<Long> getProvideLong4Provider() {",
                 "      Object local = provideLong4Provider;",
                 "      if (local == null) {",
                 "        local = new SwitchingProvider<>(1);",
@@ -254,7 +255,7 @@
                 "      return (Provider<Long>) local;",
                 "    }",
                 "",
-                "    private Provider<Long> provideLong5Provider() {",
+                "    private Provider<Long> getProvideLong5Provider() {",
                 "      Object local = provideLong5Provider;",
                 "      if (local == null) {",
                 "        local = new SwitchingProvider<>(2);",
@@ -288,12 +289,12 @@
                 "          .put(5L, SubcomponentMapModule_ProvideLong5Factory.create())")
             .addLinesIn(
                 FAST_INIT_MODE,
-                "          .put(0L, DaggerTestComponent.this.provideLong0Provider())",
-                "          .put(1L, DaggerTestComponent.this.provideLong1Provider())",
-                "          .put(2L, DaggerTestComponent.this.provideLong2Provider())",
-                "          .put(3L, provideLong3Provider())",
-                "          .put(4L, provideLong4Provider())",
-                "          .put(5L, provideLong5Provider())")
+                "          .put(0L, DaggerTestComponent.this.getProvideLong0Provider())",
+                "          .put(1L, DaggerTestComponent.this.getProvideLong1Provider())",
+                "          .put(2L, DaggerTestComponent.this.getProvideLong2Provider())",
+                "          .put(3L, getProvideLong3Provider())",
+                "          .put(4L, getProvideLong4Provider())",
+                "          .put(5L, getProvideLong5Provider())")
             .addLines( //
                 "          .build();", "    }")
             .addLinesIn(
@@ -340,7 +341,8 @@
                 "}")
             .build();
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(mapModuleFile, componentFile, subcomponentModuleFile, subcomponent);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -401,7 +403,7 @@
             "import other.UsesInaccessible;",
             "import other.UsesInaccessible_Factory;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  @Override",
             "  public UsesInaccessible usesInaccessible() {",
@@ -409,7 +411,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(module, inaccessible, usesInaccessible, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -463,7 +466,7 @@
             "test.DaggerParent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParent implements Parent {",
             "  private final ParentModule parentModule;",
             "",
@@ -479,7 +482,7 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(parent, parentModule, child);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(parent, parentModule, child);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerParent")
@@ -519,7 +522,7 @@
             "",
             "import dagger.producers.internal.CancellationListener;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent, "
                 + "CancellationListener {",
             "  @Override",
diff --git a/javatests/dagger/internal/codegen/MapKeyProcessorTest.java b/javatests/dagger/internal/codegen/MapKeyProcessorTest.java
index ffdb2bc..746c60d 100644
--- a/javatests/dagger/internal/codegen/MapKeyProcessorTest.java
+++ b/javatests/dagger/internal/codegen/MapKeyProcessorTest.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.truth.Truth.assertAbout;
 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
 
 import com.google.auto.value.processor.AutoAnnotationProcessor;
@@ -73,7 +73,7 @@
             "import com.google.auto.value.AutoAnnotation;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class PathKeyCreator {",
             "  private PathKeyCreator() {}",
             "",
@@ -122,7 +122,7 @@
             "import com.google.auto.value.AutoAnnotation;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class Container_PathKeyCreator {",
             "  private Container_PathKeyCreator() {}",
             "",
diff --git a/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java b/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java
index 753fb53..04b0986 100644
--- a/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java
+++ b/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java
@@ -17,9 +17,7 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.TestUtils.message;
 
 import com.google.common.collect.ImmutableList;
 import com.google.testing.compile.Compilation;
@@ -32,7 +30,7 @@
 @RunWith(JUnit4.class)
 public class MapMultibindingValidationTest {
   @Test
-  public void duplicateMapKeys_UnwrappedMapKey() {
+  public void duplicateMapKeys() {
     JavaFileObject module =
         JavaFileObjects.forSourceLines(
             "test.MapModule",
@@ -67,19 +65,18 @@
     assertThat(compilation)
         .hadErrorContaining(
             "The same map key is bound more than once for "
-                + "Map<String,Object>");
+                + "java.util.Map<java.lang.String,java.lang.Object>");
     assertThat(compilation).hadErrorContaining("provideObjectForAKey()");
     assertThat(compilation).hadErrorContaining("provideObjectForAKeyAgain()");
     assertThat(compilation).hadErrorCount(1);
 
     compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
-            .compile(module);
+        daggerCompiler().withOptions("-Adagger.fullBindingGraphValidation=ERROR").compile(module);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
             "The same map key is bound more than once for "
-                + "Map<String,Provider<Object>>")
+                + "java.util.Map<java.lang.String,javax.inject.Provider<java.lang.Object>>")
         .inFile(module)
         .onLineContaining("class MapModule");
     assertThat(compilation).hadErrorContaining("provideObjectForAKey()");
@@ -98,7 +95,7 @@
     assertThat(compilation)
         .hadErrorContaining(
             "The same map key is bound more than once for "
-                + "Map<String,Object>");
+                + "java.util.Map<java.lang.String,java.lang.Object>");
     assertThat(compilation).hadErrorCount(1);
 
     // If there's Map<K, V> and Map<K, Producer<V>>, report only Map<K, V>.
@@ -113,7 +110,7 @@
     assertThat(compilation)
         .hadErrorContaining(
             "The same map key is bound more than once for "
-                + "Map<String,Object>");
+                + "java.util.Map<java.lang.String,java.lang.Object>");
     assertThat(compilation).hadErrorCount(1);
 
     // If there's Map<K, Provider<V>> and Map<K, Producer<V>>, report only Map<K, Provider<V>>.
@@ -128,7 +125,7 @@
     assertThat(compilation)
         .hadErrorContaining(
             "The same map key is bound more than once for "
-                + "Map<String,Provider<Object>>");
+                + "java.util.Map<java.lang.String,javax.inject.Provider<java.lang.Object>>");
     assertThat(compilation).hadErrorCount(1);
 
     compilation = daggerCompiler().compile(module, component("Map<String, Object> objects();"));
@@ -136,7 +133,7 @@
     assertThat(compilation)
         .hadErrorContaining(
             "The same map key is bound more than once for "
-                + "Map<String,Object>");
+                + "java.util.Map<java.lang.String,java.lang.Object>");
     assertThat(compilation).hadErrorCount(1);
 
     compilation =
@@ -146,7 +143,7 @@
     assertThat(compilation)
         .hadErrorContaining(
             "The same map key is bound more than once for "
-                + "Map<String,Provider<Object>>");
+                + "java.util.Map<java.lang.String,javax.inject.Provider<java.lang.Object>>");
     assertThat(compilation).hadErrorCount(1);
 
     compilation =
@@ -157,59 +154,11 @@
     assertThat(compilation)
         .hadErrorContaining(
             "The same map key is bound more than once for "
-                + "Map<String,Producer<Object>>");
+                + "java.util.Map<java.lang.String,dagger.producers.Producer<java.lang.Object>>");
     assertThat(compilation).hadErrorCount(1);
   }
 
   @Test
-  public void duplicateMapKeys_WrappedMapKey() {
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
-            "test.MapModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "import dagger.multibindings.IntoMap;",
-            "import dagger.MapKey;",
-            "",
-            "@Module",
-            "abstract class MapModule {",
-            "",
-            "  @MapKey(unwrapValue = false)",
-            "  @interface WrappedMapKey {",
-            "    String value();",
-            "  }",
-            "",
-            "  @Provides",
-            "  @IntoMap",
-            "  @WrappedMapKey(\"foo\")",
-            "  static String stringMapEntry1() { return \"\"; }",
-            "",
-            "  @Provides",
-            "  @IntoMap",
-            "  @WrappedMapKey(\"foo\")",
-            "  static String stringMapEntry2() { return \"\"; }",
-            "}");
-
-    JavaFileObject component = component("Map<test.MapModule.WrappedMapKey, String> objects();");
-
-    Compilation compilation = daggerCompiler().compile(component, module);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            message(
-                "\033[1;31m[Dagger/MapKeys]\033[0m The same map key is bound more than once for "
-                    + "Map<MapModule.WrappedMapKey,String>",
-                "    @Provides @IntoMap @MapModule.WrappedMapKey(\"foo\") String "
-                    + "MapModule.stringMapEntry1()",
-                "    @Provides @IntoMap @MapModule.WrappedMapKey(\"foo\") String "
-                    + "MapModule.stringMapEntry2()"))
-        .inFile(component)
-        .onLineContaining("interface TestComponent");
-  }
-
-  @Test
   public void inconsistentMapKeyAnnotations() {
     JavaFileObject module =
         JavaFileObjects.forSourceLines(
@@ -256,19 +205,20 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,Object>"
+            "java.util.Map<java.lang.String,java.lang.Object>"
                 + " uses more than one @MapKey annotation type");
     assertThat(compilation).hadErrorContaining("provideObjectForAKey()");
     assertThat(compilation).hadErrorContaining("provideObjectForBKey()");
     assertThat(compilation).hadErrorCount(1);
 
     compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(module, stringKeyTwoFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,Provider<Object>>"
+            "java.util.Map<java.lang.String,javax.inject.Provider<java.lang.Object>>"
                 + " uses more than one @MapKey annotation type")
         .inFile(module)
         .onLineContaining("class MapModule");
@@ -288,7 +238,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,Object>"
+            "java.util.Map<java.lang.String,java.lang.Object>"
                 + " uses more than one @MapKey annotation type");
     assertThat(compilation).hadErrorCount(1);
 
@@ -304,7 +254,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,Object>"
+            "java.util.Map<java.lang.String,java.lang.Object>"
                 + " uses more than one @MapKey annotation type");
     assertThat(compilation).hadErrorCount(1);
 
@@ -320,7 +270,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,Provider<Object>>"
+            "java.util.Map<java.lang.String,javax.inject.Provider<java.lang.Object>>"
                 + " uses more than one @MapKey annotation type");
     assertThat(compilation).hadErrorCount(1);
 
@@ -330,7 +280,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,Object>"
+            "java.util.Map<java.lang.String,java.lang.Object>"
                 + " uses more than one @MapKey annotation type");
     assertThat(compilation).hadErrorCount(1);
 
@@ -343,7 +293,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,Provider<Object>>"
+            "java.util.Map<java.lang.String,javax.inject.Provider<java.lang.Object>>"
                 + " uses more than one @MapKey annotation type");
     assertThat(compilation).hadErrorCount(1);
 
@@ -356,7 +306,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,Producer<Object>>"
+            "java.util.Map<java.lang.String,dagger.producers.Producer<java.lang.Object>>"
                 + " uses more than one @MapKey annotation type");
     assertThat(compilation).hadErrorCount(1);
   }
diff --git a/javatests/dagger/internal/codegen/MembersInjectionTest.java b/javatests/dagger/internal/codegen/MembersInjectionTest.java
index ef69c71..edaedaf 100644
--- a/javatests/dagger/internal/codegen/MembersInjectionTest.java
+++ b/javatests/dagger/internal/codegen/MembersInjectionTest.java
@@ -22,8 +22,8 @@
 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
 import static javax.tools.StandardLocation.CLASS_OUTPUT;
 
@@ -87,7 +87,7 @@
             "test.DaggerTestComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  @Override",
             "  public Child child() {",
@@ -95,7 +95,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(childFile, parentFile, componentFile);
 
     assertThat(compilation).succeeded();
@@ -146,7 +147,7 @@
             "",
             "import com.google.errorprone.annotations.CanIgnoreReturnValue;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  @Override",
             "  public Child child() {",
@@ -160,7 +161,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(childFile, parentFile, depFile, componentFile);
 
     assertThat(compilation).succeeded();
@@ -182,47 +184,44 @@
         "",
         " @Inject void register(B b) {}",
         "}");
-    JavaFileObject expected =
-        JavaFileObjects.forSourceLines(
-            "test.GenericClass_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class GenericClass_MembersInjector<A, B>",
-            "    implements MembersInjector<GenericClass<A, B>> {",
-            "  private final Provider<A> aProvider;",
-            "  private final Provider<B> bProvider;",
-            "",
-            "  public GenericClass_MembersInjector(Provider<A> aProvider, Provider<B> bProvider) {",
-            "    this.aProvider = aProvider;",
-            "    this.bProvider = bProvider;",
-            "  }",
-            "",
-            "  public static <A, B> MembersInjector<GenericClass<A, B>> create(",
-            "      Provider<A> aProvider, Provider<B> bProvider) {",
-            "    return new GenericClass_MembersInjector<A, B>(aProvider, bProvider);",
-            "  }",
-            "",
-            "  @Override",
-            "  public void injectMembers(GenericClass<A, B> instance) {",
-            "    injectA(instance, aProvider.get());",
-            "    injectRegister(instance, bProvider.get());",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.GenericClass.a\")",
-            "  public static <A, B> void injectA(Object instance, A a) {",
-            "    ((GenericClass<A, B>) instance).a = a;",
-            "  }",
-            "",
-            "  public static <A, B> void injectRegister(Object instance, B b) {",
-            "    ((GenericClass<A, B>) instance).register(b);",
-            "  }",
-            "}");
+    JavaFileObject expected = JavaFileObjects.forSourceLines(
+        "test.GenericClass_MembersInjector",
+        "package test;",
+        "",
+        "import dagger.MembersInjector;",
+        IMPORT_GENERATED_ANNOTATION,
+        "import javax.inject.Provider;",
+        "",
+        GENERATED_ANNOTATION,
+        "public final class GenericClass_MembersInjector<A, B>",
+        "    implements MembersInjector<GenericClass<A, B>> {",
+        "  private final Provider<A> aProvider;",
+        "  private final Provider<B> bProvider;",
+        "",
+        "  public GenericClass_MembersInjector(Provider<A> aProvider, Provider<B> bProvider) {",
+        "    this.aProvider = aProvider;",
+        "    this.bProvider = bProvider;",
+        "  }",
+        "",
+        "  public static <A, B> MembersInjector<GenericClass<A, B>> create(",
+        "      Provider<A> aProvider, Provider<B> bProvider) {",
+        "    return new GenericClass_MembersInjector<A, B>(aProvider, bProvider);",
+        "  }",
+        "",
+        "  @Override",
+        "  public void injectMembers(GenericClass<A, B> instance) {",
+        "    injectA(instance, aProvider.get());",
+        "    injectRegister(instance, bProvider.get());",
+        "  }",
+        "",
+        "  public static <A, B> void injectA(Object instance, A a) {",
+        "    ((GenericClass<A, B>) instance).a = a;",
+        "  }",
+        "",
+        "  public static <A, B> void injectRegister(Object instance, B b) {",
+        "    ((GenericClass<A, B>) instance).register(b);",
+        "  }",
+        "}");
     assertAbout(javaSource())
         .that(file)
         .withCompilerOptions(compilerMode.javacopts())
@@ -272,67 +271,50 @@
         "",
         "  @Inject Child() {}",
         "}");
-    JavaFileObject expected =
-        JavaFileObjects.forSourceLines(
-            "test.Child_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class Child_MembersInjector<T>",
-            "    implements MembersInjector<Child<T>> {",
-            "  private final Provider<T> xProvider;",
-            "  private final Provider<A> yProvider;",
-            "  private final Provider<A2> a2Provider;",
-            "  private final Provider<A> aProvider;",
-            "  private final Provider<T> tProvider;",
-            "",
-            "  public Child_MembersInjector(",
-            "      Provider<T> xProvider,",
-            "      Provider<A> yProvider,",
-            "      Provider<A2> a2Provider,",
-            "      Provider<A> aProvider,",
-            "      Provider<T> tProvider) {",
-            "    this.xProvider = xProvider;",
-            "    this.yProvider = yProvider;",
-            "    this.a2Provider = a2Provider;",
-            "    this.aProvider = aProvider;",
-            "    this.tProvider = tProvider;",
-            "  }",
-            "",
-            "  public static <T> MembersInjector<Child<T>> create(",
-            "      Provider<T> xProvider,",
-            "      Provider<A> yProvider,",
-            "      Provider<A2> a2Provider,",
-            "      Provider<A> aProvider,",
-            "      Provider<T> tProvider) {",
-            "    return new Child_MembersInjector<T>(xProvider, yProvider, a2Provider, aProvider,"
-                + " tProvider);",
-            "}",
-            "",
-            "  @Override",
-            "  public void injectMembers(Child<T> instance) {",
-            "    Parent_MembersInjector.injectX(instance, xProvider.get());",
-            "    Parent_MembersInjector.injectY(instance, yProvider.get());",
-            "    Parent_MembersInjector.injectA2(instance, a2Provider.get());",
-            "    injectA(instance, aProvider.get());",
-            "    injectT(instance, tProvider.get());",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.Child.a\")",
-            "  public static <T> void injectA(Object instance, Object a) {",
-            "    ((Child<T>) instance).a = (A) a;",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.Child.t\")",
-            "  public static <T> void injectT(Object instance, T t) {",
-            "    ((Child<T>) instance).t = t;",
-            "  }",
-            "}");
+    JavaFileObject expected = JavaFileObjects.forSourceLines(
+        "test.Child_MembersInjector",
+        "package test;",
+        "",
+        "import dagger.MembersInjector;",
+        IMPORT_GENERATED_ANNOTATION,
+        "import javax.inject.Provider;",
+        "",
+        GENERATED_ANNOTATION,
+        "public final class Child_MembersInjector<T>",
+        "    implements MembersInjector<Child<T>> {",
+        "  private final Provider<T> tAndXProvider;",
+        "  private final Provider<A> aAndYProvider;",
+        "  private final Provider<A2> a2Provider;",
+        "",
+        "  public Child_MembersInjector(",
+        "      Provider<T> tAndXProvider, Provider<A> aAndYProvider, Provider<A2> a2Provider) {",
+        "    this.tAndXProvider = tAndXProvider;",
+        "    this.aAndYProvider = aAndYProvider;",
+        "    this.a2Provider = a2Provider;",
+        "  }",
+        "",
+        "  public static <T> MembersInjector<Child<T>> create(",
+        "      Provider<T> tAndXProvider, Provider<A> aAndYProvider, Provider<A2> a2Provider) {",
+        "    return new Child_MembersInjector<T>(tAndXProvider, aAndYProvider, a2Provider);",
+        "  }",
+        "",
+        "  @Override",
+        "  public void injectMembers(Child<T> instance) {",
+        "    Parent_MembersInjector.injectX(instance, tAndXProvider.get());",
+        "    Parent_MembersInjector.injectY(instance, aAndYProvider.get());",
+        "    Parent_MembersInjector.injectA2(instance, a2Provider.get());",
+        "    injectA(instance, aAndYProvider.get());",
+        "    injectT(instance, tAndXProvider.get());",
+        "  }",
+        "",
+        "  public static <T> void injectA(Object instance, Object a) {",
+        "    ((Child<T>) instance).a = (A) a;",
+        "  }",
+        "",
+        "  public static <T> void injectT(Object instance, T t) {",
+        "    ((Child<T>) instance).t = t;",
+        "  }",
+        "}");
     assertAbout(javaSources())
         .that(ImmutableList.of(a, a2, parent, child))
         .withCompilerOptions(compilerMode.javacopts())
@@ -363,50 +345,38 @@
             "import dagger.Lazy;",
             "import dagger.MembersInjector;",
             "import dagger.internal.DoubleCheck;",
-            "import dagger.internal.InjectedFieldSignature;",
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class FieldInjection_MembersInjector",
             "    implements MembersInjector<FieldInjection> {",
             "  private final Provider<String> stringProvider;",
-            "  private final Provider<String> stringProvider2;",
-            "  private final Provider<String> stringProvider3;",
             "",
-            "  public FieldInjection_MembersInjector(Provider<String> stringProvider,",
-            "      Provider<String> stringProvider2, Provider<String> stringProvider3) {",
+            "  public FieldInjection_MembersInjector(Provider<String> stringProvider) {",
             "    this.stringProvider = stringProvider;",
-            "    this.stringProvider2 = stringProvider2;",
-            "    this.stringProvider3 = stringProvider3;",
             "  }",
             "",
             "  public static MembersInjector<FieldInjection> create(",
-            "      Provider<String> stringProvider,",
-            "      Provider<String> stringProvider2,",
-            "      Provider<String> stringProvider3) {",
-            "    return new FieldInjection_MembersInjector(",
-            "        stringProvider, stringProvider2, stringProvider3);",
+            "      Provider<String> stringProvider) {",
+            "    return new FieldInjection_MembersInjector(stringProvider);",
             "  }",
             "",
             "  @Override",
             "  public void injectMembers(FieldInjection instance) {",
             "    injectString(instance, stringProvider.get());",
-            "    injectLazyString(instance, DoubleCheck.lazy(stringProvider2));",
-            "    injectStringProvider(instance, stringProvider3);",
+            "    injectLazyString(instance, DoubleCheck.lazy(stringProvider));",
+            "    injectStringProvider(instance, stringProvider);",
             "  }",
             "",
-            "  @InjectedFieldSignature(\"test.FieldInjection.string\")",
             "  public static void injectString(Object instance, String string) {",
             "    ((FieldInjection) instance).string = string;",
             "  }",
             "",
-            "  @InjectedFieldSignature(\"test.FieldInjection.lazyString\")",
             "  public static void injectLazyString(Object instance, Lazy<String> lazyString) {",
             "    ((FieldInjection) instance).lazyString = lazyString;",
             "  }",
             "",
-            "  @InjectedFieldSignature(\"test.FieldInjection.stringProvider\")",
             "  public static void injectStringProvider(",
             "      Object instance, Provider<String> stringProvider) {",
             "    ((FieldInjection) instance).stringProvider = stringProvider;",
@@ -421,77 +391,6 @@
         .generatesSources(expected);
   }
 
-  @Test
-  public void fieldInjectionWithQualifier() {
-    JavaFileObject file =
-        JavaFileObjects.forSourceLines(
-            "test.FieldInjectionWithQualifier",
-            "package test;",
-            "",
-            "import dagger.Lazy;",
-            "import javax.inject.Inject;",
-            "import javax.inject.Named;",
-            "import javax.inject.Provider;",
-            "",
-            "class FieldInjectionWithQualifier {",
-            "  @Inject @Named(\"A\") String a;",
-            "  @Inject @Named(\"B\") String b;",
-            "}");
-    JavaFileObject expected =
-        JavaFileObjects.forSourceLines(
-            "test.FieldInjectionWithQualifier_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Named;",
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class FieldInjectionWithQualifier_MembersInjector",
-            "    implements MembersInjector<FieldInjectionWithQualifier> {",
-            "  private final Provider<String> aProvider;",
-            "  private final Provider<String> bProvider;",
-            "",
-            "  public FieldInjectionWithQualifier_MembersInjector(Provider<String> aProvider,",
-            "      Provider<String> bProvider) {",
-            "    this.aProvider = aProvider;",
-            "    this.bProvider = bProvider;",
-            "  }",
-            "",
-            "  public static MembersInjector<FieldInjectionWithQualifier> create(",
-            "    Provider<String> aProvider, Provider<String> bProvider) {",
-            "    return new FieldInjectionWithQualifier_MembersInjector(aProvider, bProvider);",
-            "  }",
-            "",
-            "@Override",
-            "  public void injectMembers(FieldInjectionWithQualifier instance) {",
-            "    injectA(instance, aProvider.get());",
-            "    injectB(instance, bProvider.get());",
-            "}",
-            "",
-            "  @InjectedFieldSignature(\"test.FieldInjectionWithQualifier.a\")",
-            "  @Named(\"A\")",
-            "  public static void injectA(Object instance, String a) {",
-            "    ((FieldInjectionWithQualifier) instance).a = a;",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.FieldInjectionWithQualifier.b\")",
-            "  @Named(\"B\")",
-            "  public static void injectB(Object instance, String b) {",
-            "    ((FieldInjectionWithQualifier) instance).b = b;",
-            "  }",
-            "}");
-    assertAbout(javaSource())
-        .that(file)
-        .withCompilerOptions(compilerMode.javacopts())
-        .processedWith(new ComponentProcessor())
-        .compilesWithoutError()
-        .and()
-        .generatesSources(expected);
-  }
-
   @Test public void methodInjection() {
     JavaFileObject file = JavaFileObjects.forSourceLines("test.MethodInjection",
         "package test;",
@@ -517,32 +416,20 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class MethodInjection_MembersInjector",
             "     implements MembersInjector<MethodInjection> {",
-            "  private final Provider<String> stringProvider;",
-            "  private final Provider<String> stringProvider2;",
-            "  private final Provider<String> stringProvider3;",
-            "  private final Provider<String> stringProvider4;",
             "",
-            "  public MethodInjection_MembersInjector(",
-            "      Provider<String> stringProvider,",
-            "      Provider<String> stringProvider2,",
-            "      Provider<String> stringProvider3,",
-            "      Provider<String> stringProvider4) {",
+            "  private final Provider<String> stringProvider;",
+            "",
+            "  public MethodInjection_MembersInjector(Provider<String> stringProvider) {",
             "    this.stringProvider = stringProvider;",
-            "    this.stringProvider2 = stringProvider2;",
-            "    this.stringProvider3 = stringProvider3;",
-            "    this.stringProvider4 = stringProvider4;",
             "  }",
             "",
             "  public static MembersInjector<MethodInjection> create(",
-            "      Provider<String> stringProvider,",
-            "      Provider<String> stringProvider2,",
-            "      Provider<String> stringProvider3,",
-            "      Provider<String> stringProvider4) {",
-            "    return new MethodInjection_MembersInjector(",
-            "        stringProvider, stringProvider2, stringProvider3, stringProvider4);}",
+            "      Provider<String> stringProvider) {",
+            "    return new MethodInjection_MembersInjector(stringProvider);",
+            "  }",
             "",
             "  @Override",
             "  public void injectMembers(MethodInjection instance) {",
@@ -550,9 +437,9 @@
             "    injectOneArg(instance, stringProvider.get());",
             "    injectManyArgs(",
             "        instance,",
-            "        stringProvider2.get(),",
-            "        DoubleCheck.lazy(stringProvider3),",
-            "        stringProvider4);",
+            "        stringProvider.get(),",
+            "        DoubleCheck.lazy(stringProvider),",
+            "        stringProvider);",
             "  }",
             "",
             "  public static void injectNoArgs(Object instance) {",
@@ -596,69 +483,59 @@
         "  @Inject Object object;",
         "  @Inject void setObject(Object o) {}",
         "}");
-    JavaFileObject expected =
-        JavaFileObjects.forSourceLines(
-            "test.MixedMemberInjection_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class MixedMemberInjection_MembersInjector",
-            "    implements MembersInjector<MixedMemberInjection> {",
-            "  private final Provider<String> stringProvider;",
-            "  private final Provider<Object> objectProvider;",
-            "  private final Provider<String> sProvider;",
-            "  private final Provider<Object> oProvider;",
-            "",
-            "  public MixedMemberInjection_MembersInjector(",
-            "      Provider<String> stringProvider,",
-            "      Provider<Object> objectProvider,",
-            "      Provider<String> sProvider,",
-            "      Provider<Object> oProvider) {",
-            "    this.stringProvider = stringProvider;",
-            "    this.objectProvider = objectProvider;",
-            "    this.sProvider = sProvider;",
-            "    this.oProvider = oProvider;",
-            "  }",
-            "",
-            "  public static MembersInjector<MixedMemberInjection> create(",
-            "      Provider<String> stringProvider,",
-            "      Provider<Object> objectProvider,",
-            "      Provider<String> sProvider,",
-            "      Provider<Object> oProvider) {",
-            "    return new MixedMemberInjection_MembersInjector(",
-            "        stringProvider, objectProvider, sProvider, oProvider);}",
-            "",
-            "  @Override",
-            "  public void injectMembers(MixedMemberInjection instance) {",
-            "    injectString(instance, stringProvider.get());",
-            "    injectObject(instance, objectProvider.get());",
-            "    injectSetString(instance, sProvider.get());",
-            "    injectSetObject(instance, oProvider.get());",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.MixedMemberInjection.string\")",
-            "  public static void injectString(Object instance, String string) {",
-            "    ((MixedMemberInjection) instance).string = string;",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.MixedMemberInjection.object\")",
-            "  public static void injectObject(Object instance, Object object) {",
-            "    ((MixedMemberInjection) instance).object = object;",
-            "  }",
-            "",
-            "  public static void injectSetString(Object instance, String s) {",
-            "    ((MixedMemberInjection) instance).setString(s);",
-            "  }",
-            "",
-            "  public static void injectSetObject(Object instance, Object o) {",
-            "    ((MixedMemberInjection) instance).setObject(o);",
-            "  }",
-            "}");
+    JavaFileObject expected = JavaFileObjects.forSourceLines(
+        "test.MixedMemberInjection_MembersInjector",
+        "package test;",
+        "",
+        "import dagger.MembersInjector;",
+        IMPORT_GENERATED_ANNOTATION,
+        "import javax.inject.Provider;",
+        "",
+        GENERATED_ANNOTATION,
+        "public final class MixedMemberInjection_MembersInjector",
+        "    implements MembersInjector<MixedMemberInjection> {",
+        "",
+        "  private final Provider<String> stringAndSProvider;",
+        "  private final Provider<Object> objectAndOProvider;",
+        "",
+        "  public MixedMemberInjection_MembersInjector(",
+        "      Provider<String> stringAndSProvider,",
+        "      Provider<Object> objectAndOProvider) {",
+        "    this.stringAndSProvider = stringAndSProvider;",
+        "    this.objectAndOProvider = objectAndOProvider;",
+        "  }",
+        "",
+        "  public static MembersInjector<MixedMemberInjection> create(",
+        "      Provider<String> stringAndSProvider,",
+        "      Provider<Object> objectAndOProvider) {",
+        "    return new MixedMemberInjection_MembersInjector(",
+        "        stringAndSProvider, objectAndOProvider);",
+        "  }",
+        "",
+        "  @Override",
+        "  public void injectMembers(MixedMemberInjection instance) {",
+        "    injectString(instance, stringAndSProvider.get());",
+        "    injectObject(instance, objectAndOProvider.get());",
+        "    injectSetString(instance, stringAndSProvider.get());",
+        "    injectSetObject(instance, objectAndOProvider.get());",
+        "  }",
+        "",
+        "  public static void injectString(Object instance, String string) {",
+        "    ((MixedMemberInjection) instance).string = string;",
+        "  }",
+        "",
+        "  public static void injectObject(Object instance, Object object) {",
+        "    ((MixedMemberInjection) instance).object = object;",
+        "  }",
+        "",
+        "  public static void injectSetString(Object instance, String s) {",
+        "    ((MixedMemberInjection) instance).setString(s);",
+        "  }",
+        "",
+        "  public static void injectSetObject(Object instance, Object o) {",
+        "    ((MixedMemberInjection) instance).setObject(o);",
+        "  }",
+        "}");
     assertAbout(javaSource())
         .that(file)
         .withCompilerOptions(compilerMode.javacopts())
@@ -679,51 +556,45 @@
         "  @Inject AllInjections(String s) {}",
         "  @Inject void s(String s) {}",
         "}");
-    JavaFileObject expectedMembersInjector =
-        JavaFileObjects.forSourceLines(
-            "test.AllInjections_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class AllInjections_MembersInjector ",
-            "    implements MembersInjector<AllInjections> {",
-            "  private final Provider<String> sProvider;",
-            "  private final Provider<String> sProvider2;",
-            "",
-            "  public AllInjections_MembersInjector(",
-            "      Provider<String> sProvider, Provider<String> sProvider2) {",
-            "    this.sProvider = sProvider;",
-            "    this.sProvider2 = sProvider2;",
-            "  }",
-            "",
-            "  public static MembersInjector<AllInjections> create(",
-            "      Provider<String> sProvider, Provider<String> sProvider2) {",
-            "    return new AllInjections_MembersInjector(sProvider, sProvider2);}",
-            "",
-            "  @Override",
-            "  public void injectMembers(AllInjections instance) {",
-            "    injectS(instance, sProvider.get());",
-            "    injectS2(instance, sProvider2.get());",
-            "  }",
-            "",
-            // TODO(b/64477506): now that these all take "object", it would be nice to rename
-            // "instance"
-            // to the type name
-            "  @InjectedFieldSignature(\"test.AllInjections.s\")",
-            "  public static void injectS(Object instance, String s) {",
-            "    ((AllInjections) instance).s = s;",
-            "  }",
-            "",
-            "  public static void injectS2(Object instance, String s) {",
-            "    ((AllInjections) instance).s(s);",
-            "  }",
-            "",
-            "}");
+    JavaFileObject expectedMembersInjector = JavaFileObjects.forSourceLines(
+        "test.AllInjections_MembersInjector",
+        "package test;",
+        "",
+        "import dagger.MembersInjector;",
+        IMPORT_GENERATED_ANNOTATION,
+        "import javax.inject.Provider;",
+        "",
+        GENERATED_ANNOTATION,
+        "public final class AllInjections_MembersInjector ",
+        "    implements MembersInjector<AllInjections> {",
+        "",
+        "  private final Provider<String> sProvider;",
+        "",
+        "  public AllInjections_MembersInjector(Provider<String> sProvider) {",
+        "    this.sProvider = sProvider;",
+        "  }",
+        "",
+        "  public static MembersInjector<AllInjections> create(Provider<String> sProvider) {",
+        "      return new AllInjections_MembersInjector(sProvider);",
+        "  }",
+        "",
+        "  @Override",
+        "  public void injectMembers(AllInjections instance) {",
+        "    injectS(instance, sProvider.get());",
+        "    injectS2(instance, sProvider.get());",
+        "  }",
+        "",
+        // TODO(b/64477506): now that these all take "object", it would be nice to rename "instance"
+        // to the type name
+        "  public static void injectS(Object instance, String s) {",
+        "    ((AllInjections) instance).s = s;",
+        "  }",
+        "",
+        "  public static void injectS2(Object instance, String s) {",
+        "    ((AllInjections) instance).s(s);",
+        "  }",
+        "",
+        "}");
     assertAbout(javaSource())
         .that(file)
         .withCompilerOptions(compilerMode.javacopts())
@@ -746,38 +617,35 @@
         "class B extends A {",
         "  @Inject String s;",
         "}");
-    JavaFileObject expectedMembersInjector =
-        JavaFileObjects.forSourceLines(
-            "test.AllInjections_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class B_MembersInjector implements MembersInjector<B> {",
-            "  private final Provider<String> sProvider;",
-            "",
-            "  public B_MembersInjector(Provider<String> sProvider) {",
-            "    this.sProvider = sProvider;",
-            "  }",
-            "",
-            "  public static MembersInjector<B> create(Provider<String> sProvider) {",
-            "      return new B_MembersInjector(sProvider);",
-            "  }",
-            "",
-            "  @Override",
-            "  public void injectMembers(B instance) {",
-            "    injectS(instance, sProvider.get());",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.B.s\")",
-            "  public static void injectS(Object instance, String s) {",
-            "    ((B) instance).s = s;",
-            "  }",
-            "}");
+    JavaFileObject expectedMembersInjector = JavaFileObjects.forSourceLines(
+        "test.AllInjections_MembersInjector",
+        "package test;",
+        "",
+        "import dagger.MembersInjector;",
+        IMPORT_GENERATED_ANNOTATION,
+        "import javax.inject.Provider;",
+        "",
+        GENERATED_ANNOTATION,
+        "public final class B_MembersInjector implements MembersInjector<B> {",
+        "  private final Provider<String> sProvider;",
+        "",
+        "  public B_MembersInjector(Provider<String> sProvider) {",
+        "    this.sProvider = sProvider;",
+        "  }",
+        "",
+        "  public static MembersInjector<B> create(Provider<String> sProvider) {",
+        "      return new B_MembersInjector(sProvider);",
+        "  }",
+        "",
+        "  @Override",
+        "  public void injectMembers(B instance) {",
+        "    injectS(instance, sProvider.get());",
+        "  }",
+        "",
+        "  public static void injectS(Object instance, String s) {",
+        "    ((B) instance).s = s;",
+        "  }",
+        "}");
     assertAbout(javaSources())
         .that(ImmutableList.of(aFile, bFile))
         .withCompilerOptions(compilerMode.javacopts())
@@ -808,40 +676,36 @@
           "    void inject(B b);",
           "  }",
           "}");
-    JavaFileObject bMembersInjector =
-        JavaFileObjects.forSourceLines(
-            "test.OuterType_B_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class OuterType_B_MembersInjector",
-            "    implements MembersInjector<OuterType.B> {",
-            "  private final Provider<OuterType.A> aProvider;",
-            "",
-            "  public OuterType_B_MembersInjector(Provider<OuterType.A> aProvider) {",
-            "    this.aProvider = aProvider;",
-            "  }",
-            "",
-            "  public static MembersInjector<OuterType.B> create(",
-            "    Provider<OuterType.A> aProvider) {",
-            "    return new OuterType_B_MembersInjector(aProvider);",
-            "  }",
-            "",
-            "  @Override",
-            "  public void injectMembers(OuterType.B instance) {",
-            "    injectA(instance, aProvider.get());",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.OuterType.B.a\")",
-            "  public static void injectA(Object instance, Object a) {",
-            "    ((OuterType.B) instance).a = (OuterType.A) a;",
-            "  }",
-            "}");
+    JavaFileObject bMembersInjector = JavaFileObjects.forSourceLines(
+          "test.OuterType_B_MembersInjector",
+          "package test;",
+          "",
+          "import dagger.MembersInjector;",
+          IMPORT_GENERATED_ANNOTATION,
+          "import javax.inject.Provider;",
+          "",
+          GENERATED_ANNOTATION,
+          "public final class OuterType_B_MembersInjector",
+          "    implements MembersInjector<OuterType.B> {",
+          "  private final Provider<OuterType.A> aProvider;",
+          "",
+          "  public OuterType_B_MembersInjector(Provider<OuterType.A> aProvider) {",
+          "    this.aProvider = aProvider;",
+          "  }",
+          "",
+          "  public static MembersInjector<OuterType.B> create(Provider<OuterType.A> aProvider) {",
+          "    return new OuterType_B_MembersInjector(aProvider);",
+          "  }",
+          "",
+          "  @Override",
+          "  public void injectMembers(OuterType.B instance) {",
+          "    injectA(instance, aProvider.get());",
+          "  }",
+          "",
+          "  public static void injectA(Object instance, Object a) {",
+          "    ((OuterType.B) instance).a = (OuterType.A) a;",
+          "  }",
+          "}");
     assertAbout(javaSources())
         .that(ImmutableList.of(nestedTypesFile))
         .withCompilerOptions(compilerMode.javacopts())
@@ -880,11 +744,10 @@
             "package test;",
             "",
             "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class OuterType_B_MembersInjector",
             "    implements MembersInjector<OuterType.B> {",
             "  private final Provider<OuterType.A> aProvider;",
@@ -903,7 +766,6 @@
             "    injectA(instance, aProvider.get());",
             "  }",
             "",
-            "  @InjectedFieldSignature(\"test.OuterType.B.a\")",
             "  public static void injectA(Object instance, Object a) {",
             "    ((OuterType.B) instance).a = (OuterType.A) a;",
             "  }",
@@ -990,7 +852,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(foo, fooModule, fooComponent);
     assertThat(compilation).succeeded();
     assertThat(compilation).generatedFile(CLASS_OUTPUT, "test", "foo_MembersInjector.class");
@@ -1056,11 +919,10 @@
             "package test;",
             "",
             "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class Child_MembersInjector implements MembersInjector<Child> {",
             "  private final Provider<Foo> objectProvider;",
             "  private final Provider<Bar> objectProvider2;",
@@ -1082,7 +944,6 @@
             "    injectObject(instance, objectProvider2.get());",
             "  }",
             "",
-            "  @InjectedFieldSignature(\"test.Child.object\")",
             "  public static void injectObject(Object instance, Object object) {",
             "    ((Child) instance).object = (Bar) object;",
             "  }",
@@ -1108,7 +969,7 @@
         "    @Inject int field;",
         "  }",
         "}");
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
+    Compilation compilation = daggerCompiler().withOptions(compilerMode.javacopts()).compile(file);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining("Dagger does not support injection into private classes")
@@ -1128,7 +989,8 @@
         "  }",
         "}");
     Compilation compilation =
-        compilerWithOptions(
+        daggerCompiler()
+            .withOptions(
                 compilerMode.javacopts().append("-Adagger.privateMemberValidation=WARNING"))
             .compile(file);
     assertThat(compilation).succeeded();
@@ -1151,7 +1013,7 @@
         "    @Inject int field;",
         "  }",
         "}");
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
+    Compilation compilation = daggerCompiler().withOptions(compilerMode.javacopts()).compile(file);
     assertThat(compilation).succeeded();
   }
 
@@ -1175,37 +1037,15 @@
             "  void inject(RawProviderField rawProviderField);",
             "}");
 
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
+    Compilation compilation = daggerCompiler().withOptions(compilerMode.javacopts()).compile(file);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("Provider cannot be provided")
+        .hadErrorContaining("javax.inject.Provider cannot be provided")
         .inFile(file)
         .onLineContaining("interface C");
   }
 
   @Test
-  public void throwExceptionInjectedMethod() {
-    JavaFileObject file =
-        JavaFileObjects.forSourceLines(
-            "test.",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import javax.inject.Inject;",
-            "class SomeClass {",
-            "@Inject void inject() throws Exception {}",
-            "}");
-
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Methods with @Inject may not throw checked exceptions. "
-          + "Please wrap your exceptions in a RuntimeException instead.")
-        .inFile(file)
-        .onLineContaining("throws Exception");
-  }
-
-  @Test
   public void rawFrameworkTypeParameter() {
     JavaFileObject file =
         JavaFileObjects.forSourceLines(
@@ -1225,10 +1065,10 @@
             "  void inject(RawProviderParameter rawProviderParameter);",
             "}");
 
-    Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
+    Compilation compilation = daggerCompiler().withOptions(compilerMode.javacopts()).compile(file);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("Provider cannot be provided")
+        .hadErrorContaining("javax.inject.Provider cannot be provided")
         .inFile(file)
         .onLineContaining("interface C");
   }
@@ -1254,38 +1094,34 @@
             "package test;",
             "",
             "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class InjectedType_MembersInjector ",
             "    implements MembersInjector<InjectedType> {",
-            "  private final Provider<Integer> primitiveIntProvider;",
-            "  private final Provider<Integer> boxedIntProvider;",
+            "  private final Provider<Integer> boxedIntAndPrimitiveIntProvider;",
             "",
             "  public InjectedType_MembersInjector(",
-            "      Provider<Integer> primitiveIntProvider, Provider<Integer> boxedIntProvider) {",
-            "    this.primitiveIntProvider = primitiveIntProvider;",
-            "    this.boxedIntProvider = boxedIntProvider;",
+            "      Provider<Integer> boxedIntAndPrimitiveIntProvider) {",
+            "    this.boxedIntAndPrimitiveIntProvider = boxedIntAndPrimitiveIntProvider;",
             "  }",
             "",
             "  public static MembersInjector<InjectedType> create(",
-            "      Provider<Integer> primitiveIntProvider, Provider<Integer> boxedIntProvider) {",
-            "    return new InjectedType_MembersInjector(primitiveIntProvider, boxedIntProvider);}",
+            "      Provider<Integer> boxedIntAndPrimitiveIntProvider) {",
+            "    return new InjectedType_MembersInjector(boxedIntAndPrimitiveIntProvider);",
+            "  }",
             "",
             "  @Override",
             "  public void injectMembers(InjectedType instance) {",
-            "    injectPrimitiveInt(instance, primitiveIntProvider.get());",
-            "    injectBoxedInt(instance, boxedIntProvider.get());",
+            "    injectPrimitiveInt(instance, boxedIntAndPrimitiveIntProvider.get());",
+            "    injectBoxedInt(instance, boxedIntAndPrimitiveIntProvider.get());",
             "  }",
             "",
-            "  @InjectedFieldSignature(\"test.InjectedType.primitiveInt\")",
             "  public static void injectPrimitiveInt(Object instance, int primitiveInt) {",
             "    ((InjectedType) instance).primitiveInt = primitiveInt;",
             "  }",
             "",
-            "  @InjectedFieldSignature(\"test.InjectedType.boxedInt\")",
             "  public static void injectBoxedInt(Object instance, Integer boxedInt) {",
             "    ((InjectedType) instance).boxedInt = boxedInt;",
             "  }",
@@ -1299,30 +1135,27 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class InjectedType_Factory implements Factory<InjectedType> {",
-            "  private final Provider<Integer> primitiveIntProvider;",
+            "  private final Provider<Integer> boxedIntAndPrimitiveIntProvider;",
             "",
-            "  private final Provider<Integer> boxedIntProvider;",
-            "",
-            "  public InjectedType_Factory(",
-            "      Provider<Integer> primitiveIntProvider, Provider<Integer> boxedIntProvider) {",
-            "    this.primitiveIntProvider = primitiveIntProvider;",
-            "    this.boxedIntProvider = boxedIntProvider;",
+            "  public InjectedType_Factory(Provider<Integer> boxedIntAndPrimitiveIntProvider) {",
+            "    this.boxedIntAndPrimitiveIntProvider = boxedIntAndPrimitiveIntProvider;",
             "  }",
             "",
             "  @Override",
             "  public InjectedType get() {",
-            "    InjectedType instance = newInstance();",
+            "    InjectedType instance = new InjectedType();",
             "    InjectedType_MembersInjector.injectPrimitiveInt(",
-            "        instance, primitiveIntProvider.get());",
-            "    InjectedType_MembersInjector.injectBoxedInt(instance, boxedIntProvider.get());",
+            "        instance, boxedIntAndPrimitiveIntProvider.get());",
+            "    InjectedType_MembersInjector.injectBoxedInt(",
+            "        instance, boxedIntAndPrimitiveIntProvider.get());",
             "    return instance;",
             "  }",
             "",
             "  public static InjectedType_Factory create(",
-            "      Provider<Integer> primitiveIntProvider, Provider<Integer> boxedIntProvider) {",
-            "    return new InjectedType_Factory(primitiveIntProvider, boxedIntProvider);",
+            "      Provider<Integer> boxedIntAndPrimitiveIntProvider) {",
+            "    return new InjectedType_Factory(boxedIntAndPrimitiveIntProvider);",
             "  }",
             "",
             "  public static InjectedType newInstance() {",
@@ -1330,7 +1163,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(injectedType);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(injectedType);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.InjectedType_MembersInjector")
@@ -1388,7 +1221,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(foo, inaccessible, usesInaccessible, component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -1399,33 +1233,28 @@
                 "package other;",
                 "",
                 "import dagger.MembersInjector;",
-                "import dagger.internal.InjectedFieldSignature;",
                 IMPORT_GENERATED_ANNOTATION,
                 "import javax.inject.Provider;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "public final class Inaccessible_MembersInjector",
                 "    implements MembersInjector<Inaccessible> {",
                 "  private final Provider<Foo> fooProvider;",
-                "  private final Provider<Foo> fooProvider2;",
                 "",
-                "  public Inaccessible_MembersInjector(",
-                "      Provider<Foo> fooProvider, Provider<Foo> fooProvider2) {",
+                "  public Inaccessible_MembersInjector(Provider<Foo> fooProvider) {",
                 "    this.fooProvider = fooProvider;",
-                "    this.fooProvider2 = fooProvider2;",
                 "  }",
                 "",
-                "  public static MembersInjector<Inaccessible> create(",
-                "      Provider<Foo> fooProvider, Provider<Foo> fooProvider2) {",
-                "    return new Inaccessible_MembersInjector(fooProvider, fooProvider2);}",
+                "  public static MembersInjector<Inaccessible> create(Provider<Foo> fooProvider) {",
+                "    return new Inaccessible_MembersInjector(fooProvider);",
+                "  }",
                 "",
                 "  @Override",
                 "  public void injectMembers(Inaccessible instance) {",
                 "    injectFoo(instance, fooProvider.get());",
-                "    injectMethod(instance, fooProvider2.get());",
+                "    injectMethod(instance, fooProvider.get());",
                 "  }",
                 "",
-                "  @InjectedFieldSignature(\"other.Inaccessible.foo\")",
                 "  public static void injectFoo(Object instance, Object foo) {",
                 "    ((Inaccessible) instance).foo = (Foo) foo;",
                 "  }",
@@ -1447,16 +1276,16 @@
             "import other.UsesInaccessible;",
             "import other.UsesInaccessible_Factory;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
-            "  private Object inaccessible() {",
+            "  private Object getInaccessible() {",
             "    return injectInaccessible(Inaccessible_Factory.newInstance());",
             "  }",
             "",
             "  @Override",
             "  public UsesInaccessible usesInaccessible() {",
             "    return UsesInaccessible_Factory.newInstance(",
-            "        inaccessible());",
+            "        getInaccessible());",
             "  }",
             "",
             // TODO(ronshapiro): if possible, it would be great to rename "instance", but we
@@ -1529,7 +1358,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(inaccessible, inaccessiblesModule, usesInaccessibles, component);
     assertThat(compilation).succeeded();
     JavaFileObject generatedComponent =
@@ -1545,13 +1375,13 @@
                 "import other.UsesInaccessibles_Factory;",
                 "import other.UsesInaccessibles_MembersInjector;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {")
             .addLinesIn(
                 FAST_INIT_MODE,
                 "  private volatile Object listOfInaccessible = new MemoizedSentinel();",
                 "",
-                "  private List listOfInaccessible() {",
+                "  private List getListOfInaccessible() {",
                 "    Object local = listOfInaccessible;",
                 "    if (local instanceof MemoizedSentinel) {",
                 "      synchronized (local) {",
@@ -1589,7 +1419,7 @@
                 "    UsesInaccessibles_MembersInjector.injectInaccessibles(")
             .addLinesIn(
                 FAST_INIT_MODE,
-                "        instance, (List) listOfInaccessible());")
+                "        instance, (List) getListOfInaccessible());")
             .addLinesIn(
                 DEFAULT_MODE,
                 "        instance, (List) inaccessiblesProvider.get());")
@@ -1658,7 +1488,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(foo, supertype, subtype, injectsSubtype, component);
     assertThat(compilation).succeeded();
     JavaFileObject generatedComponent =
@@ -1674,15 +1505,15 @@
             "import other.Supertype;",
             "import other.Supertype_MembersInjector;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
-            "  private Object subtype() {",
+            "  private Object getSubtype() {",
             "    return injectSubtype(Subtype_Factory.newInstance());",
             "  }",
             "",
             "  @Override",
             "  public InjectsSubtype injectsSubtype() {",
-            "    return InjectsSubtype_Factory.newInstance(subtype());",
+            "    return InjectsSubtype_Factory.newInstance(getSubtype());",
             "  }",
             "",
             "  @CanIgnoreReturnValue",
@@ -1697,227 +1528,4 @@
         .generatedSourceFile("test.DaggerTestComponent")
         .containsElementsIn(generatedComponent);
   }
-
-  // Shows that we shouldn't create a members injector for a type that doesn't have
-  // @Inject fields or @Inject constructor even if it extends and is extended by types that do.
-  @Test
-  public void middleClassNoFieldInjection() {
-    JavaFileObject classA =
-        JavaFileObjects.forSourceLines(
-            "test.A",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class A extends B {",
-            "  @Inject String valueA;",
-            "}");
-    JavaFileObject classB =
-        JavaFileObjects.forSourceLines(
-            "test.B",
-            "package test;",
-            "",
-            "class B extends C {",
-            "}");
-    JavaFileObject classC =
-        JavaFileObjects.forSourceLines(
-            "test.C",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class C { ",
-            "  @Inject String valueC;",
-            "}");
-    JavaFileObject expectedAMembersInjector =
-        JavaFileObjects.forSourceLines(
-            "test.A_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class A_MembersInjector implements MembersInjector<A> {",
-            "  private final Provider<String> valueCProvider;",
-            "  private final Provider<String> valueAProvider;",
-            "",
-            "  public A_MembersInjector(",
-            "        Provider<String> valueCProvider, Provider<String> valueAProvider) {",
-            "    this.valueCProvider = valueCProvider;",
-            "    this.valueAProvider = valueAProvider;",
-            "  }",
-            "",
-            "  public static MembersInjector<A> create(",
-            "      Provider<String> valueCProvider, Provider<String> valueAProvider) {",
-            "    return new A_MembersInjector(valueCProvider, valueAProvider);",
-            "  }",
-            "",
-            "  @Override",
-            "  public void injectMembers(A instance) {",
-            "    C_MembersInjector.injectValueC(instance, valueCProvider.get());",
-            "    injectValueA(instance, valueAProvider.get());",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.A.valueA\")",
-            "  public static void injectValueA(Object instance, String valueA) {",
-            "    ((A) instance).valueA = valueA;",
-            "  }",
-            "}");
-
-    JavaFileObject expectedCMembersInjector =
-        JavaFileObjects.forSourceLines(
-            "test.C_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class C_MembersInjector implements MembersInjector<C> {",
-            "  private final Provider<String> valueCProvider;",
-            "",
-            "  public C_MembersInjector(Provider<String> valueCProvider) {",
-            "    this.valueCProvider = valueCProvider;",
-            "  }",
-            "",
-            "  public static MembersInjector<C> create(",
-            "      Provider<String> valueCProvider) {",
-            "    return new C_MembersInjector(valueCProvider);",
-            "  }",
-            "",
-            "  @Override",
-            "  public void injectMembers(C instance) {",
-            "    injectValueC(instance, valueCProvider.get());",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.C.valueC\")",
-            "  public static void injectValueC(Object instance, String valueC) {",
-            "    ((C) instance).valueC = valueC;",
-            "  }",
-            "}");
-
-
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
-            .compile(classA, classB, classC);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test.A_MembersInjector")
-        .hasSourceEquivalentTo(expectedAMembersInjector);
-    assertThat(compilation)
-        .generatedSourceFile("test.C_MembersInjector")
-        .hasSourceEquivalentTo(expectedCMembersInjector);
-
-    try {
-      assertThat(compilation).generatedSourceFile("test.B_MembersInjector");
-      // Can't throw an assertion error since it would be caught.
-      throw new IllegalStateException("Test generated a B_MembersInjector");
-    } catch (AssertionError expected) {
-    }
-  }
-
-  // Shows that we do generate a MembersInjector for a type that has an @Inject
-  // constructor and that extends a type with @Inject fields, even if it has no local field
-  // injection sites
-  // TODO(erichang): Are these even used anymore?
-  @Test
-  public void testConstructorInjectedFieldInjection() {
-    JavaFileObject classA =
-        JavaFileObjects.forSourceLines(
-            "test.A",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class A extends B {",
-            "  @Inject A() {}",
-            "}");
-    JavaFileObject classB =
-        JavaFileObjects.forSourceLines(
-            "test.B",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class B { ",
-            "  @Inject String valueB;",
-            "}");
-    JavaFileObject expectedAMembersInjector =
-        JavaFileObjects.forSourceLines(
-            "test.A_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class A_MembersInjector implements MembersInjector<A> {",
-            "  private final Provider<String> valueBProvider;",
-            "",
-            "  public A_MembersInjector(Provider<String> valueBProvider) {",
-            "    this.valueBProvider = valueBProvider;",
-            "  }",
-            "",
-            "  public static MembersInjector<A> create(Provider<String> valueBProvider) {",
-            "    return new A_MembersInjector(valueBProvider);",
-            "  }",
-            "",
-            "  @Override",
-            "  public void injectMembers(A instance) {",
-            "    B_MembersInjector.injectValueB(instance, valueBProvider.get());",
-            "  }",
-            "}");
-
-    JavaFileObject expectedBMembersInjector =
-        JavaFileObjects.forSourceLines(
-            "test.B_MembersInjector",
-            "package test;",
-            "",
-            "import dagger.MembersInjector;",
-            "import dagger.internal.InjectedFieldSignature;",
-            IMPORT_GENERATED_ANNOTATION,
-            "import javax.inject.Provider;",
-            "",
-            GENERATED_CODE_ANNOTATIONS,
-            "public final class B_MembersInjector implements MembersInjector<B> {",
-            "  private final Provider<String> valueBProvider;",
-            "",
-            "  public B_MembersInjector(Provider<String> valueBProvider) {",
-            "    this.valueBProvider = valueBProvider;",
-            "  }",
-            "",
-            "  public static MembersInjector<B> create(",
-            "      Provider<String> valueBProvider) {",
-            "    return new B_MembersInjector(valueBProvider);",
-            "  }",
-            "",
-            "  @Override",
-            "  public void injectMembers(B instance) {",
-            "    injectValueB(instance, valueBProvider.get());",
-            "  }",
-            "",
-            "  @InjectedFieldSignature(\"test.B.valueB\")",
-            "  public static void injectValueB(Object instance, String valueB) {",
-            "    ((B) instance).valueB = valueB;",
-            "  }",
-            "}");
-
-
-    Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
-            .compile(classA, classB);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test.A_MembersInjector")
-        .hasSourceEquivalentTo(expectedAMembersInjector);
-    assertThat(compilation)
-        .generatedSourceFile("test.B_MembersInjector")
-        .hasSourceEquivalentTo(expectedBMembersInjector);
-  }
 }
diff --git a/javatests/dagger/internal/codegen/MembersInjectionValidationTest.java b/javatests/dagger/internal/codegen/MembersInjectionValidationTest.java
index d8cd6d9..68d5daa 100644
--- a/javatests/dagger/internal/codegen/MembersInjectionValidationTest.java
+++ b/javatests/dagger/internal/codegen/MembersInjectionValidationTest.java
@@ -236,177 +236,4 @@
     assertThat(compilation).failed();
     assertThat(compilation).hadErrorContaining("static fields").inFile(injected).onLine(6);
   }
-
-  @Test
-  public void missingMembersInjectorForKotlinProperty() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.internal.codegen.KotlinInjectedQualifier;",
-            "",
-            "@Component(modules = TestModule.class)",
-            "interface TestComponent {",
-            "  void inject(KotlinInjectedQualifier injected);",
-            "}");
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
-            "test.TestModule",
-            "package test;",
-            "",
-            "import dagger.Module;",
-            "import dagger.Provides;",
-            "import javax.inject.Named;",
-            "",
-            "@Module",
-            "class TestModule {",
-            "  @Provides",
-            "  @Named(\"TheString\")",
-            "  String theString() { return \"\"; }",
-            "}");
-    Compilation compilation = daggerCompiler().compile(component, module);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Unable to read annotations on an injected Kotlin property.");
-  }
-
-  @Test
-  public void memberInjectionForKotlinObjectFails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.internal.codegen.KotlinObjectWithMemberInjection;",
-            "",
-            "@Component(modules = TestModule.class)",
-            "interface TestComponent {",
-            "  void inject(KotlinObjectWithMemberInjection injected);",
-            "}");
-    Compilation compilation = daggerCompiler().compile(component, testModule);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Dagger does not support injection into Kotlin objects");
-  }
-
-  @Test
-  public void setterMemberInjectionForKotlinObjectFails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.internal.codegen.KotlinObjectWithSetterMemberInjection;",
-            "",
-            "@Component(modules = TestModule.class)",
-            "interface TestComponent {",
-            "  void inject(KotlinObjectWithSetterMemberInjection injected);",
-            "}");
-    Compilation compilation = daggerCompiler().compile(component, testModule);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Dagger does not support injection into Kotlin objects");
-  }
-
-  @Test
-  public void memberInjectionForKotlinClassWithCompanionObjectFails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.internal.codegen.KotlinClassWithMemberInjectedCompanion;",
-            "",
-            "@Component(modules = TestModule.class)",
-            "interface TestComponent {",
-            "  void inject(KotlinClassWithMemberInjectedCompanion injected);",
-            "  void injectCompanion(KotlinClassWithMemberInjectedCompanion.Companion injected);",
-            "}");
-    Compilation compilation = daggerCompiler().compile(component, testModule);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Dagger does not support injection into static fields");
-  }
-
-  @Test
-  public void setterMemberInjectionForKotlinClassWithCompanionObjectFails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.internal.codegen.KotlinClassWithSetterMemberInjectedCompanion;",
-            "",
-            "@Component(modules = TestModule.class)",
-            "interface TestComponent {",
-            "  void inject(KotlinClassWithSetterMemberInjectedCompanion.Companion injected);",
-            "}");
-    Compilation compilation = daggerCompiler().compile(component, testModule);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Dagger does not support injection into Kotlin objects");
-  }
-
-  @Test
-  public void memberInjectionForKotlinClassWithNamedCompanionObjectFails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.internal.codegen.KotlinClassWithMemberInjectedNamedCompanion;",
-            "",
-            "@Component(modules = TestModule.class)",
-            "interface TestComponent {",
-            "  void inject(KotlinClassWithMemberInjectedNamedCompanion injected);",
-            "  void injectCompanion(KotlinClassWithMemberInjectedNamedCompanion.TheCompanion"
-                + " injected);",
-            "}");
-    Compilation compilation = daggerCompiler().compile(component, testModule);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Dagger does not support injection into static fields");
-  }
-
-  @Test
-  public void setterMemberInjectionForKotlinClassWithNamedCompanionObjectFails() {
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
-            "test.TestComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "import dagger.internal.codegen.KotlinClassWithSetterMemberInjectedNamedCompanion;",
-            "",
-            "@Component(modules = TestModule.class)",
-            "interface TestComponent {",
-            "  void inject(",
-            "      KotlinClassWithSetterMemberInjectedNamedCompanion.TheCompanion injected);",
-            "}");
-    Compilation compilation = daggerCompiler().compile(component, testModule);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Dagger does not support injection into Kotlin objects");
-  }
-
-  private final JavaFileObject testModule =
-      JavaFileObjects.forSourceLines(
-          "test.TestModule",
-          "package test;",
-          "",
-          "import dagger.Module;",
-          "import dagger.Provides;",
-          "",
-          "@Module",
-          "class TestModule {",
-          "  @Provides",
-          "  String theString() { return \"\"; }",
-          "}");
 }
diff --git a/javatests/dagger/internal/codegen/MethodSignatureFormatterTest.java b/javatests/dagger/internal/codegen/MethodSignatureFormatterTest.java
index 6d2f989..687c29a 100644
--- a/javatests/dagger/internal/codegen/MethodSignatureFormatterTest.java
+++ b/javatests/dagger/internal/codegen/MethodSignatureFormatterTest.java
@@ -22,20 +22,12 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.testing.compile.CompilationRule;
-import dagger.BindsInstance;
-import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
 import dagger.internal.codegen.MethodSignatureFormatterTest.OuterClass.InnerClass;
-import dagger.internal.codegen.binding.InjectionAnnotations;
-import dagger.internal.codegen.binding.MethodSignatureFormatter;
 import dagger.internal.codegen.langmodel.DaggerElements;
 import dagger.internal.codegen.langmodel.DaggerTypes;
-import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -45,10 +37,6 @@
 public class MethodSignatureFormatterTest {
   @Rule public CompilationRule compilationRule = new CompilationRule();
 
-  @Inject DaggerElements elements;
-  @Inject DaggerTypes types;
-  @Inject InjectionAnnotations injectionAnnotations;
-
   static class OuterClass {
     @interface Foo {
        Class<?> bar();
@@ -65,15 +53,13 @@
     }
   }
 
-  @Before
-  public void setUp() {
-    DaggerMethodSignatureFormatterTest_TestComponent.factory().create(compilationRule).inject(this);
-  }
-
   @Test public void methodSignatureTest() {
+    DaggerElements elements =
+        new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
+    DaggerTypes types = new DaggerTypes(compilationRule.getTypes(), elements);
     TypeElement inner = elements.getTypeElement(InnerClass.class);
     ExecutableElement method = Iterables.getOnlyElement(methodsIn(inner.getEnclosedElements()));
-    String formatted = new MethodSignatureFormatter(types, injectionAnnotations).format(method);
+    String formatted = new MethodSignatureFormatter(types).format(method);
     // This is gross, but it turns out that annotation order is not guaranteed when getting
     // all the AnnotationMirrors from an Element, so I have to test this chopped-up to make it
     // less brittle.
@@ -85,28 +71,4 @@
     assertThat(formatted).contains(" String "); // return type compressed
     assertThat(formatted).contains("int, ImmutableList<Boolean>)"); // parameters compressed.
   }
-
-  @Singleton
-  @Component(modules = TestModule.class)
-  interface TestComponent {
-    void inject(MethodSignatureFormatterTest test);
-
-    @Component.Factory
-    interface Factory {
-      TestComponent create(@BindsInstance CompilationRule compilationRule);
-    }
-  }
-
-  @Module
-  static class TestModule {
-    @Provides
-    static DaggerElements elements(CompilationRule compilationRule) {
-      return new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
-    }
-
-    @Provides
-    static DaggerTypes types(CompilationRule compilationRule, DaggerElements elements) {
-      return new DaggerTypes(compilationRule.getTypes(), elements);
-    }
-  }
 }
diff --git a/javatests/dagger/internal/codegen/MissingBindingSuggestionsTest.java b/javatests/dagger/internal/codegen/MissingBindingSuggestionsTest.java
index 3c066ba..e2f9634 100644
--- a/javatests/dagger/internal/codegen/MissingBindingSuggestionsTest.java
+++ b/javatests/dagger/internal/codegen/MissingBindingSuggestionsTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.TestUtils.message;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
@@ -95,9 +94,8 @@
     Compilation compilation =
         daggerCompiler().compile(fooComponent, barComponent, topComponent, foo, bar, barModule);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
-        .hadErrorContaining("A binding with matching key exists in component: BarComponent");
+        .hadErrorContaining("A binding with matching key exists in component: test.BarComponent");
   }
 
   @Test public void suggestsBindingInNestedSubcomponent() {
@@ -156,164 +154,7 @@
         daggerCompiler()
             .compile(fooComponent, barComponent, bazComponent, topComponent, foo, baz, bazModule);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
-        .hadErrorContaining("A binding with matching key exists in component: BazComponent");
-  }
-
-  @Test
-  public void missingBindingInParentComponent() {
-    JavaFileObject parent =
-        JavaFileObjects.forSourceLines(
-            "Parent",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface Parent {",
-            "  Foo foo();",
-            "  Bar bar();",
-            "  Child child();",
-            "}");
-    JavaFileObject child =
-        JavaFileObjects.forSourceLines(
-            "Child",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent(modules=BazModule.class)",
-            "interface Child {",
-            "  Foo foo();",
-            "  Baz baz();",
-            "}");
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "Foo",
-            "import javax.inject.Inject;",
-            "",
-            "class Foo {",
-            "  @Inject Foo(Bar bar) {}",
-            "}");
-    JavaFileObject bar =
-        JavaFileObjects.forSourceLines(
-            "Bar",
-            "import javax.inject.Inject;",
-            "",
-            "class Bar {",
-            "  @Inject Bar(Baz baz) {}",
-            "}");
-    JavaFileObject baz = JavaFileObjects.forSourceLines("Baz", "class Baz {}");
-    JavaFileObject bazModule = JavaFileObjects.forSourceLines(
-        "BazModule",
-        "import dagger.Module;",
-        "import dagger.Provides;",
-        "import javax.inject.Inject;",
-        "",
-        "@Module",
-        "final class BazModule {",
-        "  @Provides Baz provideBaz() {return new Baz();}",
-        "}");
-
-    Compilation compilation = daggerCompiler().compile(parent, child, foo, bar, baz, bazModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            message(
-                "\033[1;31m[Dagger/MissingBinding]\033[0m Baz cannot be provided without an "
-                    + "@Inject constructor or an @Provides-annotated method.",
-                "A binding with matching key exists in component: Child",
-                "    Baz is injected at",
-                "        Bar(baz)",
-                "    Bar is requested at",
-                "        Parent.bar()",
-                "The following other entry points also depend on it:",
-                "    Parent.foo()",
-                "    Child.foo() [Parent → Child]"))
-        .inFile(parent)
-        .onLineContaining("interface Parent");
-  }
-
-  @Test
-  public void missingBindingInSiblingComponent() {
-    JavaFileObject parent =
-        JavaFileObjects.forSourceLines(
-            "Parent",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface Parent {",
-            "  Foo foo();",
-            "  Bar bar();",
-            "  Child1 child1();",
-            "  Child2 child2();",
-            "}");
-    JavaFileObject child1 =
-        JavaFileObjects.forSourceLines(
-            "Child1",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent",
-            "interface Child1 {",
-            "  Foo foo();",
-            "  Baz baz();",
-            "}");
-    JavaFileObject child2 =
-        JavaFileObjects.forSourceLines(
-            "Child2",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent(modules = BazModule.class)",
-            "interface Child2 {",
-            "  Foo foo();",
-            "  Baz baz();",
-            "}");
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "Foo",
-            "import javax.inject.Inject;",
-            "",
-            "class Foo {",
-            "  @Inject Foo(Bar bar) {}",
-            "}");
-    JavaFileObject bar =
-        JavaFileObjects.forSourceLines(
-            "Bar",
-            "import javax.inject.Inject;",
-            "",
-            "class Bar {",
-            "  @Inject Bar(Baz baz) {}",
-            "}");
-    JavaFileObject baz = JavaFileObjects.forSourceLines("Baz", "class Baz {}");
-    JavaFileObject bazModule = JavaFileObjects.forSourceLines(
-        "BazModule",
-        "import dagger.Module;",
-        "import dagger.Provides;",
-        "import javax.inject.Inject;",
-        "",
-        "@Module",
-        "final class BazModule {",
-        "  @Provides Baz provideBaz() {return new Baz();}",
-        "}");
-
-    Compilation compilation =
-        daggerCompiler().compile(parent, child1, child2, foo, bar, baz, bazModule);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            message(
-                "\033[1;31m[Dagger/MissingBinding]\033[0m Baz cannot be provided without an "
-                    + "@Inject constructor or an @Provides-annotated method.",
-                "A binding with matching key exists in component: Child2",
-                "    Baz is injected at",
-                "        Bar(baz)",
-                "    Bar is requested at",
-                "        Parent.bar()",
-                "The following other entry points also depend on it:",
-                "    Parent.foo()",
-                "    Child1.foo() [Parent → Child1]",
-                "    Child2.foo() [Parent → Child2]",
-                "    Child1.baz() [Parent → Child1]"))
-        .inFile(parent)
-        .onLineContaining("interface Parent");
+        .hadErrorContaining("A binding with matching key exists in component: test.BazComponent");
   }
 }
diff --git a/javatests/dagger/internal/codegen/MissingBindingValidationTest.java b/javatests/dagger/internal/codegen/MissingBindingValidationTest.java
index 1aabd48..8eaa8d5 100644
--- a/javatests/dagger/internal/codegen/MissingBindingValidationTest.java
+++ b/javatests/dagger/internal/codegen/MissingBindingValidationTest.java
@@ -56,9 +56,8 @@
         "interface Bar {}");
     Compilation compilation = daggerCompiler().compile(component, injectable, nonInjectable);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
-        .hadErrorContaining("Bar cannot be provided without an @Provides-annotated method.")
+        .hadErrorContaining("test.Bar cannot be provided without an @Provides-annotated method.")
         .inFile(component)
         .onLineContaining("interface MyComponent");
   }
@@ -82,10 +81,9 @@
             "}");
     Compilation compilation = daggerCompiler().compile(component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
-            "\033[1;31m[Dagger/MissingBinding]\033[0m TestClass.A cannot be provided "
+            "[Dagger/MissingBinding] test.TestClass.A cannot be provided "
                 + "without an @Provides-annotated method.")
         .inFile(component)
         .onLineContaining("interface AComponent");
@@ -112,10 +110,9 @@
             "}");
     Compilation compilation = daggerCompiler().compile(component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
-            "\033[1;31m[Dagger/MissingBinding]\033[0m @TestClass.Q TestClass.A cannot be provided "
+            "[Dagger/MissingBinding] @test.TestClass.Q test.TestClass.A cannot be provided "
                 + "without an @Provides-annotated method.")
         .inFile(component)
         .onLineContaining("interface AComponent");
@@ -143,10 +140,9 @@
 
     Compilation compilation = daggerCompiler().compile(component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
-            "TestClass.A cannot be provided without an @Inject constructor or an "
+            "test.TestClass.A cannot be provided without an @Inject constructor or an "
                 + "@Provides-annotated method.")
         .inFile(component)
         .onLineContaining("interface AComponent");
@@ -178,10 +174,9 @@
 
     Compilation compilation = daggerCompiler().compile(component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
-            "TestClass.B cannot be provided without an @Inject constructor or an "
+            "test.TestClass.B cannot be provided without an @Inject constructor or an "
                 + "@Provides-annotated method. This type supports members injection but cannot be "
                 + "implicitly provided.")
         .inFile(component)
@@ -215,9 +210,8 @@
 
     Compilation compilation = daggerCompiler().compile(self, component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
-        .hadErrorContaining("Self cannot be provided without an @Inject constructor")
+        .hadErrorContaining("test.Self cannot be provided without an @Inject constructor")
         .inFile(component)
         .onLineContaining("interface SelfComponent");
   }
@@ -247,10 +241,9 @@
             "}");
     Compilation compilation = daggerCompiler().compile(component, foo);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
-            "Foo<? extends Number> cannot be provided "
+            "test.Foo<? extends java.lang.Number> cannot be provided "
                 + "without an @Provides-annotated method");
   }
 
@@ -307,22 +300,21 @@
 
     Compilation compilation = daggerCompiler().compile(component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "TestClass.A cannot be provided without an @Provides-annotated method.",
-                "    TestClass.A is injected at",
-                "        TestClass.B(a)",
-                "    TestClass.B is injected at",
-                "        TestClass.C.b",
-                "    TestClass.C is injected at",
-                "        TestClass.AComponent.injectC(TestClass.C)",
+                "test.TestClass.A cannot be provided without an @Provides-annotated method.",
+                "    test.TestClass.A is injected at",
+                "        test.TestClass.B(a)",
+                "    test.TestClass.B is injected at",
+                "        test.TestClass.C.b",
+                "    test.TestClass.C is injected at",
+                "        test.TestClass.AComponent.injectC(test.TestClass.C)",
                 "The following other entry points also depend on it:",
-                "    TestClass.AComponent.getFoo()",
-                "    TestClass.AComponent.cProvider()",
-                "    TestClass.AComponent.lazyC()",
-                "    TestClass.AComponent.lazyCProvider()"))
+                "    test.TestClass.AComponent.getFoo()",
+                "    test.TestClass.AComponent.cProvider()",
+                "    test.TestClass.AComponent.lazyC()",
+                "    test.TestClass.AComponent.lazyCProvider()"))
         .inFile(component)
         .onLineContaining("interface AComponent");
   }
@@ -362,17 +354,16 @@
     Compilation compilation =
         daggerCompiler().compile(component, module, interfaceFile, implementationFile);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "String cannot be provided without an @Inject constructor or an "
+                "java.lang.String cannot be provided without an @Inject constructor or an "
                     + "@Provides-annotated method.",
-                "    String is injected at",
+                "    java.lang.String is injected at",
                 "        TestImplementation(missingBinding)",
                 "    TestImplementation is injected at",
                 "        TestModule.bindTestInterface(implementation)",
-                "    TestInterface is requested at",
+                "    TestInterface is provided at",
                 "        TestComponent.testInterface()"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
@@ -417,19 +408,18 @@
 
     Compilation compilation = daggerCompiler().compile(generic, testClass, usesTest, component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "List cannot be provided without an @Provides-annotated method.",
-                "    List is injected at",
-                "        TestClass(list)",
-                "    TestClass is injected at",
-                "        Generic(t)",
-                "    Generic<TestClass> is injected at",
-                "        UsesTest(genericTestClass)",
-                "    UsesTest is requested at",
-                "        TestComponent.usesTest()"));
+                "java.util.List cannot be provided without an @Provides-annotated method.",
+                "    java.util.List is injected at",
+                "        test.TestClass(list)",
+                "    test.TestClass is injected at",
+                "        test.Generic(t)",
+                "    test.Generic<test.TestClass> is injected at",
+                "        test.UsesTest(genericTestClass)",
+                "    test.UsesTest is provided at",
+                "        test.TestComponent.usesTest()"));
   }
 
   @Test public void resolvedVariablesInDependencyTrace() {
@@ -472,19 +462,18 @@
 
     Compilation compilation = daggerCompiler().compile(generic, testClass, usesTest, component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "List cannot be provided without an @Provides-annotated method.",
-                "    List is injected at",
-                "        TestClass(list)",
-                "    TestClass is injected at",
-                "        Generic.t",
-                "    Generic<TestClass> is injected at",
-                "        UsesTest(genericTestClass)",
-                "    UsesTest is requested at",
-                "        TestComponent.usesTest()"));
+                "java.util.List cannot be provided without an @Provides-annotated method.",
+                "    java.util.List is injected at",
+                "        test.TestClass(list)",
+                "    test.TestClass is injected at",
+                "        test.Generic.t",
+                "    test.Generic<test.TestClass> is injected at",
+                "        test.UsesTest(genericTestClass)",
+                "    test.UsesTest is provided at",
+                "        test.TestComponent.usesTest()"));
   }
 
   @Test
@@ -535,10 +524,9 @@
 
     Compilation compilation = daggerCompiler().compile(parent, parentModule, child, childModule);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContainingMatch(
-            "(?s)\\QString cannot be provided\\E.*\\QChild.needsString()\\E")
+            "(?s)\\Qjava.lang.String cannot be provided\\E.*\\QChild.needsString()\\E")
         .inFile(parent)
         .onLineContaining("interface Parent");
   }
@@ -611,10 +599,9 @@
     Compilation compilation =
         daggerCompiler().compile(parent, parentModule, child, childModule, grandchild);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContainingMatch(
-            "(?s)\\QDouble cannot be provided\\E.*"
+            "(?s)\\Qjava.lang.Double cannot be provided\\E.*"
                 + "\\QGrandchild.object() [Parent → Child → Grandchild]\\E$")
         .inFile(parent)
         .onLineContaining("interface Parent");
@@ -659,20 +646,19 @@
             "interface NotBound {}");
     Compilation compilation = daggerCompiler().compile(component, module, notBound);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "\033[1;31m[Dagger/MissingBinding]\033[0m "
-                    + "NotBound cannot be provided without an @Provides-annotated method.",
-                "    NotBound is injected at",
-                "        TestModule.object(notBound)",
-                "    Object is requested at",
-                "        TestComponent.object()",
+                "[Dagger/MissingBinding] "
+                    + "test.NotBound cannot be provided without an @Provides-annotated method.",
+                "    test.NotBound is injected at",
+                "        test.TestModule.object(notBound)",
+                "    java.lang.Object is provided at",
+                "        test.TestComponent.object()",
                 "It is also requested at:",
-                "    TestModule.string(notBound, …)",
+                "    test.TestModule.string(notBound, …)",
                 "The following other entry points also depend on it:",
-                "    TestComponent.string()"))
+                "    test.TestComponent.string()"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
     assertThat(compilation).hadErrorCount(1);
@@ -719,25 +705,24 @@
 
     Compilation compilation = daggerCompiler().compile(foo, component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "\033[1;31m[Dagger/MissingBinding]\033[0m String cannot be provided without an "
-                    + "@Inject constructor or an @Provides-annotated method.",
-                "    String is requested at",
-                "        TestComponent.string()",
+                "[Dagger/MissingBinding] java.lang.String cannot be provided without an @Inject "
+                    + "constructor or an @Provides-annotated method.",
+                "    java.lang.String is provided at",
+                "        test.TestComponent.string()",
                 "It is also requested at:",
-                "    Foo(one, …)",
-                "    Foo(…, two, …)",
-                "    Foo(…, three, …)",
-                "    Foo(…, four, …)",
-                "    Foo(…, five, …)",
-                "    Foo(…, six, …)",
-                "    Foo(…, seven, …)",
-                "    Foo(…, eight, …)",
-                "    Foo(…, nine, …)",
-                "    Foo(…, ten, …)",
+                "    test.Foo(one, …)",
+                "    test.Foo(…, two, …)",
+                "    test.Foo(…, three, …)",
+                "    test.Foo(…, four, …)",
+                "    test.Foo(…, five, …)",
+                "    test.Foo(…, six, …)",
+                "    test.Foo(…, seven, …)",
+                "    test.Foo(…, eight, …)",
+                "    test.Foo(…, nine, …)",
+                "    test.Foo(…, ten, …)",
                 "    and 3 others"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
@@ -770,162 +755,26 @@
 
     Compilation compilation = daggerCompiler().compile(component);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "\033[1;31m[Dagger/MissingBinding]\033[0m String cannot be provided without an "
-                    + "@Inject constructor or an @Provides-annotated method.",
-                "    String is requested at",
-                "        TestComponent.string1()",
+                "[Dagger/MissingBinding] java.lang.String cannot be provided without an @Inject "
+                    + "constructor or an @Provides-annotated method.",
+                "    java.lang.String is provided at",
+                "        test.TestComponent.string1()",
                 "The following other entry points also depend on it:",
-                "    TestComponent.string2()",
-                "    TestComponent.string3()",
-                "    TestComponent.string4()",
-                "    TestComponent.string5()",
-                "    TestComponent.string6()",
-                "    TestComponent.string7()",
-                "    TestComponent.string8()",
-                "    TestComponent.string9()",
-                "    TestComponent.string10()",
-                "    TestComponent.string11()",
+                "    test.TestComponent.string2()",
+                "    test.TestComponent.string3()",
+                "    test.TestComponent.string4()",
+                "    test.TestComponent.string5()",
+                "    test.TestComponent.string6()",
+                "    test.TestComponent.string7()",
+                "    test.TestComponent.string8()",
+                "    test.TestComponent.string9()",
+                "    test.TestComponent.string10()",
+                "    test.TestComponent.string11()",
                 "    and 1 other"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
   }
-
-  @Test
-  public void missingBindingInAllComponentsAndEntryPoints() {
-    JavaFileObject parent =
-        JavaFileObjects.forSourceLines(
-            "Parent",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface Parent {",
-            "  Foo foo();",
-            "  Bar bar();",
-            "  Child child();",
-            "}");
-    JavaFileObject child =
-        JavaFileObjects.forSourceLines(
-            "Child",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent",
-            "interface Child {",
-            "  Foo foo();",
-            "  Baz baz();",
-            "}");
-    JavaFileObject foo =
-        JavaFileObjects.forSourceLines(
-            "Foo",
-            "import javax.inject.Inject;",
-            "",
-            "class Foo {",
-            "  @Inject Foo(Bar bar) {}",
-            "}");
-    JavaFileObject bar =
-        JavaFileObjects.forSourceLines(
-            "Bar",
-            "import javax.inject.Inject;",
-            "",
-            "class Bar {",
-            "  @Inject Bar(Baz baz) {}",
-            "}");
-    JavaFileObject baz = JavaFileObjects.forSourceLines("Baz", "class Baz {}");
-
-    Compilation compilation = daggerCompiler().compile(parent, child, foo, bar, baz);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining(
-            message(
-                "\033[1;31m[Dagger/MissingBinding]\033[0m Baz cannot be provided without an "
-                    + "@Inject constructor or an @Provides-annotated method.",
-                "    Baz is injected at",
-                "        Bar(baz)",
-                "    Bar is requested at",
-                "        Parent.bar()",
-                "The following other entry points also depend on it:",
-                "    Parent.foo()",
-                "    Child.foo() [Parent → Child]",
-                "    Child.baz() [Parent → Child]"))
-        .inFile(parent)
-        .onLineContaining("interface Parent");
-  }
-
-  // Regression test for b/147423208 where if the same subcomponent was used
-  // in two different parts of the hierarchy and only one side had a missing binding
-  // incorrect caching during binding graph conversion might cause validation to pass
-  // incorrectly.
-  @Test
-  public void sameSubcomponentUsedInDifferentHierarchies() {
-    JavaFileObject parent = JavaFileObjects.forSourceLines("test.Parent",
-        "package test;",
-        "",
-        "import dagger.Component;",
-        "",
-        "@Component",
-        "interface Parent {",
-        "  Child1 getChild1();",
-        "  Child2 getChild2();",
-        "}");
-    JavaFileObject child1 = JavaFileObjects.forSourceLines("test.Child1",
-        "package test;",
-        "",
-        "import dagger.Subcomponent;",
-        "",
-        "@Subcomponent(modules = LongModule.class)",
-        "interface Child1 {",
-        "  RepeatedSub getSub();",
-        "}");
-    JavaFileObject child2 = JavaFileObjects.forSourceLines("test.Child2",
-        "package test;",
-        "",
-        "import dagger.Subcomponent;",
-        "",
-        "@Subcomponent",
-        "interface Child2 {",
-        "  RepeatedSub getSub();",
-        "}");
-    JavaFileObject repeatedSub = JavaFileObjects.forSourceLines("test.RepeatedSub",
-        "package test;",
-        "",
-        "import dagger.Subcomponent;",
-        "",
-        "@Subcomponent",
-        "interface RepeatedSub {",
-        "  Foo getFoo();",
-        "}");
-    JavaFileObject injectable = JavaFileObjects.forSourceLines("test.Foo",
-        "package test;",
-        "",
-        "import javax.inject.Inject;",
-        "",
-        "class Foo {",
-        "  @Inject Foo(Long value) {}",
-        "}");
-    JavaFileObject module = JavaFileObjects.forSourceLines("test.LongModule",
-        "package test;",
-        "",
-        "import dagger.Module;",
-        "import dagger.Provides;",
-        "",
-        "@Module",
-        "interface LongModule {",
-        "  @Provides static Long provideLong() {",
-        "    return 0L;",
-        "  }",
-        "}");
-    Compilation compilation = daggerCompiler().compile(
-        parent, child1, child2, repeatedSub, injectable, module);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContaining("Long cannot be provided without an @Inject constructor")
-        .inFile(parent)
-        .onLineContaining("interface Parent");
-  }
-
 }
diff --git a/javatests/dagger/internal/codegen/ModuleFactoryGeneratorTest.java b/javatests/dagger/internal/codegen/ModuleFactoryGeneratorTest.java
index cbda1b8..50c41ed 100644
--- a/javatests/dagger/internal/codegen/ModuleFactoryGeneratorTest.java
+++ b/javatests/dagger/internal/codegen/ModuleFactoryGeneratorTest.java
@@ -24,8 +24,9 @@
 import static dagger.internal.codegen.Compilers.daggerCompiler;
 import static dagger.internal.codegen.DaggerModuleMethodSubject.Factory.assertThatMethodInUnannotatedClass;
 import static dagger.internal.codegen.DaggerModuleMethodSubject.Factory.assertThatModuleMethod;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
+import static dagger.internal.codegen.GeneratedLines.NPE_FROM_PROVIDES_METHOD;
 
 import com.google.common.collect.ImmutableList;
 import com.google.testing.compile.Compilation;
@@ -228,7 +229,7 @@
             "import dagger.internal.Preconditions;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class TestModule_ProvideStringFactory implements Factory<String> {",
             "  private final TestModule module;",
             "",
@@ -245,7 +246,8 @@
             "  }",
             "",
             "  public static String provideString(TestModule instance) {",
-            "    return Preconditions.checkNotNullFromProvides(instance.provideString());",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideString(), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     assertAbout(javaSource()).that(moduleFile)
@@ -275,7 +277,7 @@
             "import dagger.internal.Factory;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class TestModule_ProvideStringFactory implements Factory<String> {",
             "  private final TestModule module;",
             "",
@@ -321,7 +323,7 @@
             "import dagger.internal.Factory;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class TestModule_ProvideStringFactory implements Factory<String> {",
             "  private final TestModule module;",
             "",
@@ -395,7 +397,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class TestModule_ProvideObjectsFactory",
             "    implements Factory<List<Object>> {",
             "  private final TestModule module;",
@@ -430,8 +432,8 @@
             "",
             "  public static List<Object> provideObjects(",
             "      TestModule instance, Object a, Object b, MembersInjector<X> xInjector) {",
-            "    return Preconditions.checkNotNullFromProvides(",
-            "        instance.provideObjects(a, b, xInjector));",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideObjects(a, b, xInjector), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     assertAbout(javaSources()).that(
@@ -465,7 +467,7 @@
             "import dagger.internal.Preconditions;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class TestModule_ProvideStringFactory implements Factory<String> {",
             "  private final TestModule module;",
             "",
@@ -482,7 +484,9 @@
             "  }",
             "",
             "  public static String provideString(TestModule instance) {",
-            "    return Preconditions.checkNotNullFromProvides(instance.provideString());",
+            "    return Preconditions.checkNotNull(instance.provideString(), "
+                + NPE_FROM_PROVIDES_METHOD
+                + ");",
             "  }",
             "}");
     assertAbout(javaSource()).that(moduleFile)
@@ -518,7 +522,7 @@
             "import java.util.List;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class TestModule_ProvideWildcardListFactory implements "
                 + "Factory<List<List<?>>> {",
             "  private final TestModule module;",
@@ -536,8 +540,8 @@
             "  }",
             "",
             "  public static List<List<?>> provideWildcardList(TestModule instance) {",
-            "    return Preconditions.checkNotNullFromProvides(",
-            "        instance.provideWildcardList());",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideWildcardList(), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     assertAbout(javaSource()).that(moduleFile)
@@ -571,7 +575,7 @@
             "import java.util.Set;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class TestModule_ProvideStringsFactory implements Factory<Set<String>> {",
             "  private final TestModule module;",
             "",
@@ -588,8 +592,8 @@
             "  }",
             "",
             "  public static Set<String> provideStrings(TestModule instance) {",
-            "    return Preconditions.checkNotNullFromProvides(",
-            "        instance.provideStrings());",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideStrings(), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     assertAbout(javaSource()).that(moduleFile)
@@ -720,7 +724,6 @@
         .onLine(6);
   }
 
-
   @Test
   public void enclosedInPrivateModule() {
     JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.Enclosing",
@@ -883,7 +886,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class ParentModule_ProvideListBFactory<A extends CharSequence,",
             "    B, C extends Number & Comparable<C>> implements Factory<List<B>> {",
             "  private final ParentModule<A, B, C> module;",
@@ -908,7 +911,8 @@
             "",
             "  public static <A extends CharSequence, B, C extends Number & Comparable<C>> List<B>",
             "      provideListB(ParentModule<A, B, C> instance, B b) {",
-            "    return Preconditions.checkNotNullFromProvides(instance.provideListB(b));",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideListB(b), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     JavaFileObject bElementFactory =
@@ -921,7 +925,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class ParentModule_ProvideBElementFactory<A extends CharSequence,",
             "    B, C extends Number & Comparable<C>> implements Factory<B> {",
             "  private final ParentModule<A, B, C> module;",
@@ -947,7 +951,8 @@
             "  public static <A extends CharSequence, B, C extends Number & Comparable<C>>",
             "      B provideBElement(",
             "          ParentModule<A, B, C> instance, B b) {",
-            "    return Preconditions.checkNotNullFromProvides(instance.provideBElement(b));",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideBElement(b), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     JavaFileObject bEntryFactory =
@@ -960,7 +965,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class ParentModule_ProvideBEntryFactory<A extends CharSequence,",
             "    B, C extends Number & Comparable<C>> implements Factory<B>> {",
             "  private final ParentModule<A, B, C> module;",
@@ -986,7 +991,8 @@
             "  public static <A extends CharSequence, B, C extends Number & Comparable<C>>",
             "      B provideBEntry(",
             "          ParentModule<A, B, C> instance, B b) {",
-            "    return Preconditions.checkNotNullFromProvides(instance.provideBEntry(b));",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideBEntry(b), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     JavaFileObject numberFactory =
@@ -998,7 +1004,7 @@
             "import dagger.internal.Preconditions;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class ChildNumberModule_ProvideNumberFactory",
             "    implements Factory<Number> {",
             "  private final ChildNumberModule module;",
@@ -1018,7 +1024,8 @@
             "  }",
             "",
             "  public static Number provideNumber(ChildNumberModule instance) {",
-            "    return Preconditions.checkNotNullFromProvides(instance.provideNumber());",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideNumber(), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     JavaFileObject integerFactory =
@@ -1030,7 +1037,7 @@
             "import dagger.internal.Preconditions;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class ChildIntegerModule_ProvideIntegerFactory",
             "    implements Factory<Integer> {",
             "  private final ChildIntegerModule module;",
@@ -1050,8 +1057,8 @@
             "  }",
             "",
             "  public static Integer provideInteger(ChildIntegerModule instance) {",
-            "    return Preconditions.checkNotNullFromProvides(",
-            "        instance.provideInteger());",
+            "    return Preconditions.checkNotNull(",
+            "        instance.provideInteger(), " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
     assertAbout(javaSources())
@@ -1104,26 +1111,24 @@
             "import java.util.Map;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class ParameterizedModule_ProvideMapStringNumberFactory",
             "    implements Factory<Map<String, Number>> {",
+            "  private static final ParameterizedModule_ProvideMapStringNumberFactory INSTANCE =",
+            "      new ParameterizedModule_ProvideMapStringNumberFactory();",
+            "",
             "  @Override",
             "  public Map<String, Number> get() {",
             "    return provideMapStringNumber();",
             "  }",
             "",
             "  public static ParameterizedModule_ProvideMapStringNumberFactory create() {",
-            "    return InstanceHolder.INSTANCE;",
+            "    return INSTANCE;",
             "  }",
             "",
             "  public static Map<String, Number> provideMapStringNumber() {",
-            "    return Preconditions.checkNotNullFromProvides(",
-            "        ParameterizedModule.provideMapStringNumber());",
-            "  }",
-            "",
-            "  private static final class InstanceHolder {",
-            "    private static final ParameterizedModule_ProvideMapStringNumberFactory INSTANCE =",
-            "        new ParameterizedModule_ProvideMapStringNumberFactory();",
+            "    return Preconditions.checkNotNull(ParameterizedModule.provideMapStringNumber(),",
+            "        " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
 
@@ -1136,26 +1141,24 @@
             "import dagger.internal.Preconditions;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class ParameterizedModule_ProvideNonGenericTypeFactory",
             "    implements Factory<Object> {",
+            "  private static final ParameterizedModule_ProvideNonGenericTypeFactory INSTANCE = ",
+            "      new ParameterizedModule_ProvideNonGenericTypeFactory();",
+            "",
             "  @Override",
             "  public Object get() {",
             "    return provideNonGenericType();",
             "  }",
             "",
             "  public static ParameterizedModule_ProvideNonGenericTypeFactory create() {",
-            "    return InstanceHolder.INSTANCE;",
+            "    return INSTANCE;",
             "  }",
             "",
             "  public static Object provideNonGenericType() {",
-            "    return Preconditions.checkNotNullFromProvides(",
-            "        ParameterizedModule.provideNonGenericType());",
-            "  }",
-            "",
-            "  private static final class InstanceHolder {",
-            "    private static final ParameterizedModule_ProvideNonGenericTypeFactory INSTANCE =",
-            "        new ParameterizedModule_ProvideNonGenericTypeFactory();",
+            "    return Preconditions.checkNotNull(ParameterizedModule.provideNonGenericType(),",
+            "        " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
 
@@ -1169,7 +1172,7 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "public final class ParameterizedModule_ProvideNonGenericTypeWithDepsFactory",
             "    implements Factory<String> {",
             "  private final Provider<Object> oProvider;",
@@ -1190,8 +1193,9 @@
             "  }",
             "",
             "  public static String provideNonGenericTypeWithDeps(Object o) {",
-            "    return Preconditions.checkNotNullFromProvides(",
-            "        ParameterizedModule.provideNonGenericTypeWithDeps(o));",
+            "    return Preconditions.checkNotNull(",
+            "        ParameterizedModule.provideNonGenericTypeWithDeps(o),",
+            "        " + NPE_FROM_PROVIDES_METHOD + ");",
             "  }",
             "}");
 
@@ -1406,7 +1410,7 @@
                 "test.TestModule_GetFactory",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "public final class TestModule_GetFactory implements Factory<Integer> {",
                 "  @Override",
                 "  public Integer get() {",
@@ -1414,7 +1418,7 @@
                 "  }",
                 "",
                 "  public static TestModule_GetFactory create() {",
-                "    return InstanceHolder.INSTANCE;",
+                "    return INSTANCE;",
                 "  }",
                 "",
                 "  public static int proxyGet() {",
@@ -1429,7 +1433,7 @@
                 "test.TestModule_CreateFactory",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "public final class TestModule_CreateFactory implements Factory<Boolean> {",
                 "  @Override",
                 "  public Boolean get() {",
@@ -1437,7 +1441,7 @@
                 "  }",
                 "",
                 "  public static TestModule_CreateFactory create() {",
-                "    return InstanceHolder.INSTANCE;",
+                "    return INSTANCE;",
                 "  }",
                 "",
                 "  public static boolean proxyCreate() {",
diff --git a/javatests/dagger/internal/codegen/ModuleValidationTest.java b/javatests/dagger/internal/codegen/ModuleValidationTest.java
index 162c8c0..649649a 100644
--- a/javatests/dagger/internal/codegen/ModuleValidationTest.java
+++ b/javatests/dagger/internal/codegen/ModuleValidationTest.java
@@ -342,18 +342,10 @@
             "",
             "@Module(includes = BadModule.class)",
             "abstract class IncludesBadModule {}");
-    Compilation compilation = daggerCompiler().compile(badModule, module);
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation)
+    assertThat(daggerCompiler().compile(badModule, module))
         .hadErrorContaining("test.BadModule has errors")
         .inFile(module)
         .onLine(5);
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@Binds methods must have exactly one parameter, whose type is assignable to the "
-                + "return type")
-        .inFile(badModule)
-        .onLine(8);
   }
 
   @Test
diff --git a/javatests/dagger/internal/codegen/MultibindingTest.java b/javatests/dagger/internal/codegen/MultibindingTest.java
index 152adb0..2bf9494 100644
--- a/javatests/dagger/internal/codegen/MultibindingTest.java
+++ b/javatests/dagger/internal/codegen/MultibindingTest.java
@@ -131,7 +131,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Map<String,String> "
+            "java.util.Map<java.lang.String,java.lang.String> "
                 + "cannot be provided without an @Provides-annotated method")
         .inFile(component)
         .onLineContaining("interface TestComponent");
@@ -183,7 +183,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Set<Produced<String>> "
+            "java.util.Set<dagger.producers.Produced<java.lang.String>> "
                 + "cannot be provided without an @Provides- or @Produces-annotated method")
         .inFile(component)
         .onLineContaining("interface TestComponent");
diff --git a/javatests/dagger/internal/codegen/NullableBindingValidationTest.java b/javatests/dagger/internal/codegen/NullableBindingValidationTest.java
new file mode 100644
index 0000000..24d5636
--- /dev/null
+++ b/javatests/dagger/internal/codegen/NullableBindingValidationTest.java
@@ -0,0 +1,419 @@
+/*
+ * 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.testing.compile.CompilationSubject.assertThat;
+import static com.google.testing.compile.Compiler.javac;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.NullableBindingValidator.nullableToNonNullable;
+
+import com.google.testing.compile.Compilation;
+import com.google.testing.compile.JavaFileObjects;
+import javax.tools.JavaFileObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class NullableBindingValidationTest {
+  private static final JavaFileObject NULLABLE =
+      JavaFileObjects.forSourceLines(
+          "test.Nullable", // force one-string-per-line format
+          "package test;",
+          "",
+          "public @interface Nullable {}");
+
+  @Test public void nullCheckForConstructorParameters() {
+    JavaFileObject a = JavaFileObjects.forSourceLines("test.A",
+        "package test;",
+        "",
+        "import javax.inject.Inject;",
+        "",
+        "final class A {",
+        "  @Inject A(String string) {}",
+        "}");
+    JavaFileObject module = JavaFileObjects.forSourceLines("test.TestModule",
+        "package test;",
+        "",
+        "import dagger.Provides;",
+        "import javax.inject.Inject;",
+        "",
+        "@dagger.Module",
+        "final class TestModule {",
+        "  @Nullable @Provides String provideString() { return null; }",
+        "}");
+    JavaFileObject component = JavaFileObjects.forSourceLines("test.TestComponent",
+        "package test;",
+        "",
+        "import dagger.Component;",
+        "",
+        "@Component(modules = TestModule.class)",
+        "interface TestComponent {",
+        "  A a();",
+        "}");
+    Compilation compilation = daggerCompiler().compile(NULLABLE, a, module, component);
+    assertThat(compilation).failed();
+    assertThat(compilation)
+        .hadErrorContaining(
+            nullableToNonNullable(
+                "java.lang.String",
+                "@test.Nullable @Provides String test.TestModule.provideString()"));
+
+    // but if we disable the validation, then it compiles fine.
+    Compilation compilation2 =
+        javac()
+            .withOptions("-Adagger.nullableValidation=WARNING")
+            .withProcessors(new ComponentProcessor())
+            .compile(NULLABLE, a, module, component);
+    assertThat(compilation2).succeeded();
+  }
+
+  @Test public void nullCheckForMembersInjectParam() {
+    JavaFileObject a = JavaFileObjects.forSourceLines("test.A",
+        "package test;",
+        "",
+        "import javax.inject.Inject;",
+        "",
+        "final class A {",
+        "  @Inject A() {}",
+        "  @Inject void register(String string) {}",
+        "}");
+    JavaFileObject module = JavaFileObjects.forSourceLines("test.TestModule",
+        "package test;",
+        "",
+        "import dagger.Provides;",
+        "import javax.inject.Inject;",
+        "",
+        "@dagger.Module",
+        "final class TestModule {",
+        "  @Nullable @Provides String provideString() { return null; }",
+        "}");
+    JavaFileObject component = JavaFileObjects.forSourceLines("test.TestComponent",
+        "package test;",
+        "",
+        "import dagger.Component;",
+        "",
+        "@Component(modules = TestModule.class)",
+        "interface TestComponent {",
+        "  A a();",
+        "}");
+    Compilation compilation = daggerCompiler().compile(NULLABLE, a, module, component);
+    assertThat(compilation).failed();
+    assertThat(compilation)
+        .hadErrorContaining(
+            nullableToNonNullable(
+                "java.lang.String",
+                "@test.Nullable @Provides String test.TestModule.provideString()"));
+
+    // but if we disable the validation, then it compiles fine.
+    Compilation compilation2 =
+        javac()
+            .withOptions("-Adagger.nullableValidation=WARNING")
+            .withProcessors(new ComponentProcessor())
+            .compile(NULLABLE, a, module, component);
+    assertThat(compilation2).succeeded();
+  }
+
+  @Test public void nullCheckForVariable() {
+    JavaFileObject a = JavaFileObjects.forSourceLines("test.A",
+        "package test;",
+        "",
+        "import javax.inject.Inject;",
+        "",
+        "final class A {",
+        "  @Inject String string;",
+        "  @Inject A() {}",
+        "}");
+    JavaFileObject module = JavaFileObjects.forSourceLines("test.TestModule",
+        "package test;",
+        "",
+        "import dagger.Provides;",
+        "import javax.inject.Inject;",
+        "",
+        "@dagger.Module",
+        "final class TestModule {",
+        "  @Nullable @Provides String provideString() { return null; }",
+        "}");
+    JavaFileObject component = JavaFileObjects.forSourceLines("test.TestComponent",
+        "package test;",
+        "",
+        "import dagger.Component;",
+        "",
+        "@Component(modules = TestModule.class)",
+        "interface TestComponent {",
+        "  A a();",
+        "}");
+    Compilation compilation = daggerCompiler().compile(NULLABLE, a, module, component);
+    assertThat(compilation).failed();
+    assertThat(compilation)
+        .hadErrorContaining(
+            nullableToNonNullable(
+                "java.lang.String",
+                "@test.Nullable @Provides String test.TestModule.provideString()"));
+
+    // but if we disable the validation, then it compiles fine.
+    Compilation compilation2 =
+        javac()
+            .withOptions("-Adagger.nullableValidation=WARNING")
+            .withProcessors(new ComponentProcessor())
+            .compile(NULLABLE, a, module, component);
+    assertThat(compilation2).succeeded();
+  }
+
+  @Test public void nullCheckForComponentReturn() {
+    JavaFileObject module = JavaFileObjects.forSourceLines("test.TestModule",
+        "package test;",
+        "",
+        "import dagger.Provides;",
+        "import javax.inject.Inject;",
+        "",
+        "@dagger.Module",
+        "final class TestModule {",
+        "  @Nullable @Provides String provideString() { return null; }",
+        "}");
+    JavaFileObject component = JavaFileObjects.forSourceLines("test.TestComponent",
+        "package test;",
+        "",
+        "import dagger.Component;",
+        "",
+        "@Component(modules = TestModule.class)",
+        "interface TestComponent {",
+        "  String string();",
+        "}");
+    Compilation compilation = daggerCompiler().compile(NULLABLE, module, component);
+    assertThat(compilation).failed();
+    assertThat(compilation)
+        .hadErrorContaining(
+            nullableToNonNullable(
+                "java.lang.String",
+                "@test.Nullable @Provides String test.TestModule.provideString()"));
+
+    // but if we disable the validation, then it compiles fine.
+    Compilation compilation2 =
+        javac()
+            .withOptions("-Adagger.nullableValidation=WARNING")
+            .withProcessors(new ComponentProcessor())
+            .compile(NULLABLE, module, component);
+    assertThat(compilation2).succeeded();
+  }
+
+  @Test
+  public void nullCheckForOptionalInstance() {
+    JavaFileObject a =
+        JavaFileObjects.forSourceLines(
+            "test.A",
+            "package test;",
+            "",
+            "import com.google.common.base.Optional;",
+            "import javax.inject.Inject;",
+            "",
+            "final class A {",
+            "  @Inject A(Optional<String> optional) {}",
+            "}");
+    JavaFileObject module =
+        JavaFileObjects.forSourceLines(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Provides;",
+            "import javax.inject.Inject;",
+            "",
+            "@dagger.Module",
+            "abstract class TestModule {",
+            "  @Nullable @Provides static String provideString() { return null; }",
+            "  @BindsOptionalOf abstract String optionalString();",
+            "}");
+    JavaFileObject component =
+        JavaFileObjects.forSourceLines(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = TestModule.class)",
+            "interface TestComponent {",
+            "  A a();",
+            "}");
+    Compilation compilation = daggerCompiler().compile(NULLABLE, a, module, component);
+    assertThat(compilation).failed();
+    assertThat(compilation)
+        .hadErrorContaining(
+            nullableToNonNullable(
+                "java.lang.String",
+                "@test.Nullable @Provides String test.TestModule.provideString()"));
+  }
+
+  @Test
+  public void nullCheckForOptionalProvider() {
+    JavaFileObject a =
+        JavaFileObjects.forSourceLines(
+            "test.A",
+            "package test;",
+            "",
+            "import com.google.common.base.Optional;",
+            "import javax.inject.Inject;",
+            "import javax.inject.Provider;",
+            "",
+            "final class A {",
+            "  @Inject A(Optional<Provider<String>> optional) {}",
+            "}");
+    JavaFileObject module =
+        JavaFileObjects.forSourceLines(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Provides;",
+            "import javax.inject.Inject;",
+            "",
+            "@dagger.Module",
+            "abstract class TestModule {",
+            "  @Nullable @Provides static String provideString() { return null; }",
+            "  @BindsOptionalOf abstract String optionalString();",
+            "}");
+    JavaFileObject component =
+        JavaFileObjects.forSourceLines(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = TestModule.class)",
+            "interface TestComponent {",
+            "  A a();",
+            "}");
+    Compilation compilation = daggerCompiler().compile(NULLABLE, a, module, component);
+    assertThat(compilation).succeeded();
+  }
+
+  @Test
+  public void nullCheckForOptionalLazy() {
+    JavaFileObject a =
+        JavaFileObjects.forSourceLines(
+            "test.A",
+            "package test;",
+            "",
+            "import com.google.common.base.Optional;",
+            "import dagger.Lazy;",
+            "import javax.inject.Inject;",
+            "",
+            "final class A {",
+            "  @Inject A(Optional<Lazy<String>> optional) {}",
+            "}");
+    JavaFileObject module =
+        JavaFileObjects.forSourceLines(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Provides;",
+            "import javax.inject.Inject;",
+            "",
+            "@dagger.Module",
+            "abstract class TestModule {",
+            "  @Nullable @Provides static String provideString() { return null; }",
+            "  @BindsOptionalOf abstract String optionalString();",
+            "}");
+    JavaFileObject component =
+        JavaFileObjects.forSourceLines(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = TestModule.class)",
+            "interface TestComponent {",
+            "  A a();",
+            "}");
+    Compilation compilation = daggerCompiler().compile(NULLABLE, a, module, component);
+    assertThat(compilation).succeeded();
+  }
+
+  @Test
+  public void nullCheckForOptionalProviderOfLazy() {
+    JavaFileObject a =
+        JavaFileObjects.forSourceLines(
+            "test.A",
+            "package test;",
+            "",
+            "import com.google.common.base.Optional;",
+            "import dagger.Lazy;",
+            "import javax.inject.Inject;",
+            "import javax.inject.Provider;",
+            "",
+            "final class A {",
+            "  @Inject A(Optional<Provider<Lazy<String>>> optional) {}",
+            "}");
+    JavaFileObject module =
+        JavaFileObjects.forSourceLines(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.BindsOptionalOf;",
+            "import dagger.Provides;",
+            "import javax.inject.Inject;",
+            "",
+            "@dagger.Module",
+            "abstract class TestModule {",
+            "  @Nullable @Provides static String provideString() { return null; }",
+            "  @BindsOptionalOf abstract String optionalString();",
+            "}");
+    JavaFileObject component =
+        JavaFileObjects.forSourceLines(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = TestModule.class)",
+            "interface TestComponent {",
+            "  A a();",
+            "}");
+    Compilation compilation = daggerCompiler().compile(NULLABLE, a, module, component);
+    assertThat(compilation).succeeded();
+  }
+
+  @Test
+  public void moduleValidation() {
+    JavaFileObject module =
+        JavaFileObjects.forSourceLines(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.Binds;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "abstract class TestModule {",
+            "  @Provides @Nullable static String nullableString() { return null; }",
+            "  @Binds abstract Object object(String string);",
+            "}");
+
+    Compilation compilation =
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
+            .compile(module, NULLABLE);
+    assertThat(compilation).failed();
+    assertThat(compilation)
+        .hadErrorContaining(
+            nullableToNonNullable(
+                "java.lang.String",
+                "@Provides @test.Nullable String test.TestModule.nullableString()"));
+  }
+}
diff --git a/javatests/dagger/internal/codegen/OptionalBindingRequestFulfillmentTest.java b/javatests/dagger/internal/codegen/OptionalBindingRequestFulfillmentTest.java
index 60b6898..b765166 100644
--- a/javatests/dagger/internal/codegen/OptionalBindingRequestFulfillmentTest.java
+++ b/javatests/dagger/internal/codegen/OptionalBindingRequestFulfillmentTest.java
@@ -20,7 +20,7 @@
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
 import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
@@ -110,13 +110,13 @@
                 "",
                 "import com.google.common.base.Optional;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {")
             .addLinesIn(
                 FAST_INIT_MODE,
                 "  private volatile Provider<Maybe> provideMaybeProvider;",
                 "",
-                "  private Provider<Maybe> maybeProvider() {",
+                "  private Provider<Maybe> getMaybeProvider() {",
                 "    Object local = provideMaybeProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(0);",
@@ -139,7 +139,7 @@
                 "        Maybe_MaybeModule_ProvideMaybeFactory.create()));")
             .addLinesIn(
                 FAST_INIT_MODE, //
-                "        maybeProvider()));")
+                "        getMaybeProvider()));")
             .addLines(
                 "  }",
                 "",
@@ -250,7 +250,7 @@
             "import com.google.common.base.Optional;",
             "import dagger.producers.internal.CancellationListener;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent, CancellationListener {",
             "  @Override",
             "  public ListenableFuture<Optional<Maybe>> maybe() {",
@@ -261,6 +261,7 @@
             "  @Override",
             "  public ListenableFuture<Optional<DefinitelyNot>> definitelyNot() {",
             "    return Futures.immediateFuture(Optional.<DefinitelyNot>absent());",
+
             "  }",
             "",
             "  @Override",
diff --git a/javatests/dagger/internal/codegen/OptionalBindingTest.java b/javatests/dagger/internal/codegen/OptionalBindingTest.java
index 4e158ef..1755101 100644
--- a/javatests/dagger/internal/codegen/OptionalBindingTest.java
+++ b/javatests/dagger/internal/codegen/OptionalBindingTest.java
@@ -89,7 +89,7 @@
     Compilation compilation = daggerCompiler().compile(parent, parentModule, child, childModule);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("Optional<String> is bound multiple times")
+        .hadErrorContaining("Optional<java.lang.String> is bound multiple times")
         .inFile(parent)
         .onLineContaining("interface Parent");
   }
diff --git a/javatests/dagger/internal/codegen/PluginsVisitFullBindingGraphTest.java b/javatests/dagger/internal/codegen/PluginsVisitFullBindingGraphTest.java
deleted file mode 100644
index b766463..0000000
--- a/javatests/dagger/internal/codegen/PluginsVisitFullBindingGraphTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.testing.compile.CompilationSubject.assertThat;
-import static com.google.testing.compile.Compiler.javac;
-import static dagger.internal.codegen.TestUtils.endsWithMessage;
-import static javax.tools.Diagnostic.Kind.ERROR;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.Compiler;
-import com.google.testing.compile.JavaFileObjects;
-import dagger.model.BindingGraph;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
-import java.util.regex.Pattern;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Tests for -Adagger.pluginsVisitFullBindingGraph. */
-@RunWith(JUnit4.class)
-public final class PluginsVisitFullBindingGraphTest {
-  private static final JavaFileObject MODULE_WITHOUT_ERRORS =
-      JavaFileObjects.forSourceLines(
-          "test.ModuleWithoutErrors",
-          "package test;",
-          "",
-          "import dagger.Binds;",
-          "import dagger.Module;",
-          "",
-          "@Module",
-          "interface ModuleWithoutErrors {",
-          "  @Binds Object object(String string);",
-          "}");
-
-  private static final JavaFileObject MODULE_WITH_ERRORS =
-      JavaFileObjects.forSourceLines(
-          "test.ModuleWithErrors",
-          "package test;",
-          "",
-          "import dagger.Binds;",
-          "import dagger.Module;",
-          "",
-          "@Module",
-          "interface ModuleWithErrors {",
-          "  @Binds Object object1(String string);",
-          "  @Binds Object object2(Long l);",
-          "}");
-
-  private static final Pattern PLUGIN_ERROR_MESSAGE =
-      endsWithMessage(
-          "[dagger.internal.codegen.PluginsVisitFullBindingGraphTest.ErrorPlugin] Error!");
-
-  @Test
-  public void testNoFlags() {
-    Compilation compilation = daggerCompiler().compile(MODULE_WITH_ERRORS);
-    assertThat(compilation).succeeded();
-  }
-
-  @Test
-  public void testWithVisitPlugins() {
-    Compilation compilation =
-        daggerCompiler()
-            .withOptions("-Adagger.pluginsVisitFullBindingGraphs=Enabled")
-            .compile(MODULE_WITH_ERRORS);
-
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContainingMatch(PLUGIN_ERROR_MESSAGE)
-        .inFile(MODULE_WITH_ERRORS)
-        .onLineContaining("interface ModuleWithErrors");
-  }
-
-  @Test
-  public void testWithValidationNone() {
-    Compilation compilation =
-        daggerCompiler()
-            .withOptions("-Adagger.fullBindingGraphValidation=NONE")
-            .compile(MODULE_WITHOUT_ERRORS);
-    assertThat(compilation).succeeded();
-  }
-
-  @Test
-  public void testWithValidationError() {
-    // Test that pluginsVisitFullBindingGraph is enabled with fullBindingGraphValidation.
-    Compilation compilation =
-        daggerCompiler()
-            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
-            .compile(MODULE_WITHOUT_ERRORS);
-
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContainingMatch(PLUGIN_ERROR_MESSAGE)
-        .inFile(MODULE_WITHOUT_ERRORS)
-        .onLineContaining("interface ModuleWithoutErrors");
-  }
-
-  @Test
-  public void testWithValidationErrorAndVisitPlugins() {
-    Compilation compilation =
-        daggerCompiler()
-            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
-            .withOptions("-Adagger.pluginsVisitFullBindingGraphs=Enabled")
-            .compile(MODULE_WITHOUT_ERRORS);
-
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation)
-        .hadErrorContainingMatch(PLUGIN_ERROR_MESSAGE)
-        .inFile(MODULE_WITHOUT_ERRORS)
-        .onLineContaining("interface ModuleWithoutErrors");
-  }
-
-  /** A test plugin that just reports each component with the given {@link Diagnostic.Kind}. */
-  private static final class ErrorPlugin implements BindingGraphPlugin {
-    @Override
-    public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
-      diagnosticReporter.reportComponent(ERROR, bindingGraph.rootComponentNode(), "Error!");
-    }
-  }
-
-  private static Compiler daggerCompiler() {
-    return javac().withProcessors(ComponentProcessor.forTesting(new ErrorPlugin()));
-  }
-}
diff --git a/javatests/dagger/internal/codegen/ProducerModuleFactoryGeneratorTest.java b/javatests/dagger/internal/codegen/ProducerModuleFactoryGeneratorTest.java
index d41bc2d..0b6ef8f 100644
--- a/javatests/dagger/internal/codegen/ProducerModuleFactoryGeneratorTest.java
+++ b/javatests/dagger/internal/codegen/ProducerModuleFactoryGeneratorTest.java
@@ -214,7 +214,6 @@
         .onLine(6);
   }
 
-
   @Test
   public void enclosedInPrivateModule() {
     JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.Enclosing",
@@ -370,8 +369,8 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
+            "@SuppressWarnings(\"FutureReturnValueIgnored\")",
             GENERATED_ANNOTATION,
-            "@SuppressWarnings({\"FutureReturnValueIgnored\", \"unchecked\", \"rawtypes\"})",
             "public final class TestModule_ProduceStringFactory",
             "    extends AbstractProducesMethodProducer<Void, String> {",
             "  private final TestModule module;",
@@ -443,8 +442,8 @@
             IMPORT_GENERATED_ANNOTATION,
             "import javax.inject.Provider;",
             "",
+            "@SuppressWarnings(\"FutureReturnValueIgnored\")",
             GENERATED_ANNOTATION,
-            "@SuppressWarnings({\"FutureReturnValueIgnored\", \"unchecked\", \"rawtypes\"})",
             "public final class TestModule_ProduceStringFactory",
             "    extends AbstractProducesMethodProducer<Void, String> {",
             "  private final TestModule module;",
diff --git a/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java b/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
index 797fe2e..9a852c7 100644
--- a/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
@@ -19,9 +19,8 @@
 import static com.google.common.truth.Truth.assertAbout;
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
@@ -70,7 +69,7 @@
         "  INSTANCE",
         "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation).hadErrorContaining("interface");
   }
@@ -84,7 +83,7 @@
         "@ProductionComponent",
         "@interface NotAComponent {}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation).hadErrorContaining("interface");
   }
@@ -98,7 +97,7 @@
         "@ProductionComponent(modules = Object.class)",
         "interface NotAComponent {}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(componentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining("is not annotated with one of @Module, @ProducerModule");
@@ -162,16 +161,17 @@
             .compile(moduleFile, producerModuleFile, componentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("String may not depend on the production executor")
+        .hadErrorContaining("java.lang.String may not depend on the production executor")
         .inFile(componentFile)
         .onLineContaining("interface SimpleComponent");
 
     compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(producerModuleFile);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("String may not depend on the production executor")
+        .hadErrorContaining("java.lang.String may not depend on the production executor")
         .inFile(producerModuleFile)
         .onLineContaining("class SimpleModule");
     // TODO(dpb): Report at the binding if enclosed in the module.
@@ -248,7 +248,7 @@
                 IMPORT_GENERATED_ANNOTATION,
                 "import javax.inject.Provider;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestClass_SimpleComponent",
                 "    implements TestClass.SimpleComponent, CancellationListener {",
                 "  private final TestClass.BModule bModule;",
@@ -278,7 +278,7 @@
                 "    return new Builder().build();",
                 "  }",
                 "",
-                "  private Executor productionImplementationExecutor() {",
+                "  private Executor getProductionImplementationExecutor() {",
                 "    Object local = productionImplementationExecutor;",
                 "    if (local instanceof MemoizedSentinel) {",
                 "      synchronized (local) {",
@@ -295,7 +295,7 @@
                 "    return (Executor) local;",
                 "  }",
                 "",
-                "  private Provider<Executor> productionImplementationExecutorProvider() {",
+                "  private Provider<Executor> getProductionImplementationExecutorProvider() {",
                 "    Object local = productionImplementationExecutorProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(0);",
@@ -304,7 +304,7 @@
                 "    return (Provider<Executor>) local;",
                 "  }",
                 "",
-                "  private ProductionComponentMonitor productionComponentMonitor() {",
+                "  private ProductionComponentMonitor getProductionComponentMonitor() {",
                 "    Object local = productionComponentMonitor;",
                 "    if (local instanceof MemoizedSentinel) {",
                 "      synchronized (local) {",
@@ -325,7 +325,7 @@
                 "  }",
                 "",
                 "  private Provider<ProductionComponentMonitor>",
-                "      productionComponentMonitorProvider() {",
+                "      getProductionComponentMonitorProvider() {",
                 "      Object local = monitorProvider;",
                 "      if (local == null) {",
                 "        local = new SwitchingProvider<>(1);",
@@ -334,11 +334,11 @@
                 "      return (Provider<ProductionComponentMonitor>) local;",
                 "  }",
                 "",
-                "  private TestClass.B b() {",
+                "  private TestClass.B getB() {",
                 "    return TestClass_BModule_BFactory.b(bModule, new TestClass.C());",
                 "  }",
                 "",
-                "  private Provider<TestClass.B> bProvider() {",
+                "  private Provider<TestClass.B> getBProvider() {",
                 "    Object local = bProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(2);",
@@ -353,12 +353,12 @@
                 "      final TestClass.BModule bModuleParam) {",
                 "    this.simpleComponentProvider =",
                 "        InstanceFactory.create((TestClass.SimpleComponent) this);",
-                "    this.bProducer = Producers.producerFromProvider(bProvider());",
+                "    this.bProducer = Producers.producerFromProvider(getBProvider());",
                 "    this.aProducer =",
                 "        TestClass_AModule_AFactory.create(",
                 "            aModuleParam,",
-                "            productionImplementationExecutorProvider(),",
-                "            productionComponentMonitorProvider(),",
+                "            getProductionImplementationExecutorProvider(),",
+                "            getProductionComponentMonitorProvider(),",
                 "            bProducer);",
                 "    this.aEntryPoint = Producers.entryPointViewOf(aProducer, this);",
                 "  }",
@@ -413,11 +413,11 @@
                 "    public T get() {",
                 "      switch (id) {",
                 "        case 0: return (T) DaggerTestClass_SimpleComponent.this",
-                "            .productionImplementationExecutor();",
+                "            .getProductionImplementationExecutor();",
                 "        case 1: return (T)",
-                "            DaggerTestClass_SimpleComponent.this.productionComponentMonitor();",
+                "            DaggerTestClass_SimpleComponent.this.getProductionComponentMonitor();",
                 "        case 2: return (T)",
-                "            DaggerTestClass_SimpleComponent.this.b();",
+                "            DaggerTestClass_SimpleComponent.this.getB();",
                 "        default: throw new AssertionError(id);",
                 "      }",
                 "    }",
@@ -443,7 +443,7 @@
                 IMPORT_GENERATED_ANNOTATION,
                 "import javax.inject.Provider;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestClass_SimpleComponent",
                 "    implements TestClass.SimpleComponent, CancellationListener {",
                 "  private Producer<TestClass.A> aEntryPoint;",
@@ -592,7 +592,7 @@
         "  }",
         "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(component);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(component);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .hadWarningContaining("@Nullable on @Produces methods does not do anything")
@@ -641,7 +641,8 @@
             "  ProductionScoped productionScoped();",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(productionScoped, parent, child);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -650,7 +651,7 @@
             new JavaFileBuilder(compilerMode, "test.DaggerRoot")
                 .addLines(
                     "package test;",
-                    GENERATED_CODE_ANNOTATIONS,
+                    GENERATED_ANNOTATION,
                     "final class DaggerParent implements Parent, CancellationListener {",
                     "  private final class ChildImpl implements Child, CancellationListener {",
                     "    @Override",
@@ -660,7 +661,7 @@
                     "      return DaggerParent.this.productionScopedProvider.get();")
                 .addLinesIn(
                     CompilerMode.FAST_INIT_MODE, //
-                    "      return DaggerParent.this.productionScoped();")
+                    "      return DaggerParent.this.getProductionScoped();")
                 .addLines(
                     "    }", //
                     "  }", //
diff --git a/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java b/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
index 3e416e9..8453e03 100644
--- a/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
+++ b/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
 
 import com.google.testing.compile.Compilation;
@@ -78,7 +77,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Bar cannot be provided without an @Inject constructor or an @Provides- or "
+            "test.Bar cannot be provided without an @Inject constructor or an @Provides- or "
                 + "@Produces-annotated method.")
         .inFile(component)
         .onLineContaining("interface MyComponent");
@@ -104,7 +103,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "TestClass.A cannot be provided without an @Provides- or @Produces-annotated "
+            "test.TestClass.A cannot be provided without an @Provides- or @Produces-annotated "
                 + "method.")
         .inFile(component)
         .onLineContaining("interface AComponent");
@@ -149,16 +148,17 @@
     Compilation compilation = daggerCompiler().compile(EXECUTOR_MODULE, component);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("TestClass.A is a provision, which cannot depend on a production.")
+        .hadErrorContaining("test.TestClass.A is a provision, which cannot depend on a production.")
         .inFile(component)
         .onLineContaining("interface AComponent");
 
     compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(EXECUTOR_MODULE, component);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("TestClass.A is a provision, which cannot depend on a production.")
+        .hadErrorContaining("test.TestClass.A is a provision, which cannot depend on a production.")
         .inFile(component)
         .onLineContaining("class AModule");
   }
@@ -194,7 +194,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "TestClass.A is a provision entry-point, which cannot depend on a production.")
+            "test.TestClass.A is a provision entry-point, which cannot depend on a production.")
         .inFile(component)
         .onLineContaining("interface AComponent");
   }
@@ -252,7 +252,7 @@
     Compilation compilation = daggerCompiler().compile(EXECUTOR_MODULE, component);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("TestClass.A is a provision, which cannot depend on a production")
+        .hadErrorContaining("test.TestClass.A is a provision, which cannot depend on a production")
         .inFile(component)
         .onLineContaining("interface AComponent");
   }
@@ -303,7 +303,7 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "TestClass.A cannot be provided without an @Provides-annotated method.")
+            "test.TestClass.A cannot be provided without an @Provides-annotated method.")
         .inFile(component)
         .onLineContaining("interface StringComponent");
   }
@@ -357,8 +357,8 @@
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Set<ProductionComponentMonitor.Factory>"
-                + " TestClass.MonitoringModule#monitorFactory is a provision,"
+            "java.util.Set<dagger.producers.monitoring.ProductionComponentMonitor.Factory>"
+                + " test.TestClass.MonitoringModule#monitorFactory is a provision,"
                 + " which cannot depend on a production.")
         .inFile(component)
         .onLineContaining("interface StringComponent");
@@ -488,7 +488,7 @@
     Compilation compilation = daggerCompiler().compile(badModule, badComponent);
     assertThat(compilation).failed();
     assertThat(compilation)
-        .hadErrorContaining("BadModule has errors")
+        .hadErrorContaining("test.BadModule has errors")
         .inFile(badComponent)
         .onLine(7);
   }
diff --git a/javatests/dagger/internal/codegen/ScopingValidationTest.java b/javatests/dagger/internal/codegen/ScopingValidationTest.java
index 58ab2af..9efcc2a 100644
--- a/javatests/dagger/internal/codegen/ScopingValidationTest.java
+++ b/javatests/dagger/internal/codegen/ScopingValidationTest.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
 import static dagger.internal.codegen.TestUtils.message;
 
@@ -77,9 +76,9 @@
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "MyComponent (unscoped) may not reference scoped bindings:",
-                "    @Singleton class ScopedType",
-                "    @Provides @Singleton String ScopedModule.string()"));
+                "test.MyComponent (unscoped) may not reference scoped bindings:",
+                "    @Singleton class test.ScopedType",
+                "    @Provides @Singleton String test.ScopedModule.string()"));
   }
 
   @Test // b/79859714
@@ -158,9 +157,9 @@
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "Parent scoped with @Singleton may not reference bindings with different "
+                "test.Parent scoped with @Singleton may not reference bindings with different "
                     + "scopes:",
-                "    @Binds @ChildScope Foo ParentModule.bind(FooImpl)"));
+                "    @Binds @test.ChildScope test.Foo test.ParentModule.bind(test.FooImpl)"));
   }
 
   @Test
@@ -233,27 +232,28 @@
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "MyComponent scoped with @Singleton "
+                "test.MyComponent scoped with @Singleton "
                     + "may not reference bindings with different scopes:",
-                "    @PerTest class ScopedType",
-                "    @Provides @PerTest String ScopedModule.string()",
-                "    @Provides @Per(MyComponent.class) boolean "
-                    + "ScopedModule.bool()"))
+                "    @test.PerTest class test.ScopedType",
+                "    @Provides @test.PerTest String test.ScopedModule.string()",
+                "    @Provides @test.Per(test.MyComponent.class) boolean "
+                    + "test.ScopedModule.bool()"))
         .inFile(componentFile)
         .onLineContaining("interface MyComponent");
 
     compilation =
-        compilerWithOptions("-Adagger.fullBindingGraphValidation=ERROR")
+        daggerCompiler()
+            .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
             .compile(componentFile, scopeFile, scopeWithAttribute, typeFile, moduleFile);
     // The @Inject binding for ScopedType should not appear here, but the @Singleton binding should.
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "ScopedModule contains bindings with different scopes:",
-                "    @Provides @PerTest String ScopedModule.string()",
-                "    @Provides @Singleton float ScopedModule.floatingPoint()",
-                "    @Provides @Per(MyComponent.class) boolean "
-                    + "ScopedModule.bool()"))
+                "test.ScopedModule contains bindings with different scopes:",
+                "    @Provides @test.PerTest String test.ScopedModule.string()",
+                "    @Provides @Singleton float test.ScopedModule.floatingPoint()",
+                "    @Provides @test.Per(test.MyComponent.class) boolean "
+                    + "test.ScopedModule.bool()"))
         .inFile(moduleFile)
         .onLineContaining("class ScopedModule");
   }
@@ -261,7 +261,8 @@
   @Test
   public void fullBindingGraphValidationDoesNotReportForOneScope() {
     Compilation compilation =
-        compilerWithOptions(
+        daggerCompiler()
+            .withOptions(
                 "-Adagger.fullBindingGraphValidation=ERROR",
                 "-Adagger.moduleHasDifferentScopesValidation=ERROR")
             .compile(
@@ -285,7 +286,8 @@
   @Test
   public void fullBindingGraphValidationDoesNotReportInjectBindings() {
     Compilation compilation =
-        compilerWithOptions(
+        daggerCompiler()
+            .withOptions(
                 "-Adagger.fullBindingGraphValidation=ERROR",
                 "-Adagger.moduleHasDifferentScopesValidation=ERROR")
             .compile(
@@ -382,8 +384,9 @@
   }
 
   @Test
-  public void componentWithScopeCanDependOnMultipleScopedComponents() {
-    // If a scoped component will have dependencies, they can include multiple scoped component
+  public void componentWithScopeMayDependOnOnlyOneScopedComponent() {
+    // If a scoped component will have dependencies, they must only include, at most, a single
+    // scoped component
     JavaFileObject type =
         JavaFileObjects.forSourceLines(
             "test.SimpleType",
@@ -458,116 +461,14 @@
         daggerCompiler()
             .compile(
                 type, simpleScope, simpleScoped, singletonScopedA, singletonScopedB, scopeless);
-    assertThat(compilation).succeededWithoutWarnings();
-  }
-
-
-
-  // Tests the following component hierarchy:
-  //
-  //        @ScopeA
-  //        ComponentA
-  //        [SimpleType getSimpleType()]
-  //        /        \
-  //       /          \
-  //   @ScopeB         @ScopeB
-  //   ComponentB1     ComponentB2
-  //      \            [SimpleType getSimpleType()]
-  //       \          /
-  //        \        /
-  //         @ScopeC
-  //         ComponentC
-  //         [SimpleType getSimpleType()]
-  @Test
-  public void componentWithScopeCanDependOnMultipleScopedComponentsEvenDoingADiamond() {
-    JavaFileObject type =
-        JavaFileObjects.forSourceLines(
-            "test.SimpleType",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class SimpleType {",
-            "  @Inject SimpleType() {}",
-            "}");
-    JavaFileObject simpleScope =
-        JavaFileObjects.forSourceLines(
-            "test.SimpleScope",
-            "package test;",
-            "",
-            "import javax.inject.Scope;",
-            "",
-            "@Scope @interface SimpleScope {}");
-    JavaFileObject scopeA =
-        JavaFileObjects.forSourceLines(
-            "test.ScopeA",
-            "package test;",
-            "",
-            "import javax.inject.Scope;",
-            "",
-            "@Scope @interface ScopeA {}");
-    JavaFileObject scopeB =
-        JavaFileObjects.forSourceLines(
-            "test.ScopeB",
-            "package test;",
-            "",
-            "import javax.inject.Scope;",
-            "",
-            "@Scope @interface ScopeB {}");
-    JavaFileObject componentA =
-        JavaFileObjects.forSourceLines(
-            "test.ComponentA",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@ScopeA",
-            "@Component",
-            "interface ComponentA {",
-            "  SimpleType type();",
-            "}");
-    JavaFileObject componentB1 =
-        JavaFileObjects.forSourceLines(
-            "test.ComponentB1",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@ScopeB",
-            "@Component(dependencies = ComponentA.class)",
-            "interface ComponentB1 {",
-            "  SimpleType type();",
-            "}");
-    JavaFileObject componentB2 =
-        JavaFileObjects.forSourceLines(
-            "test.ComponentB2",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@ScopeB",
-            "@Component(dependencies = ComponentA.class)",
-            "interface ComponentB2 {",
-            "}");
-    JavaFileObject componentC =
-        JavaFileObjects.forSourceLines(
-            "test.ComponentC",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@SimpleScope",
-            "@Component(dependencies = {ComponentB1.class, ComponentB2.class})",
-            "interface ComponentC {",
-            "  SimpleType type();",
-            "}");
-
-    Compilation compilation =
-        daggerCompiler()
-            .compile(
-                type, simpleScope, scopeA, scopeB,
-                componentA, componentB1, componentB2, componentC);
-    assertThat(compilation).succeededWithoutWarnings();
+    assertThat(compilation).failed();
+    assertThat(compilation)
+        .hadErrorContaining(
+            message(
+                "@test.SimpleScope test.SimpleScopedComponent depends on more than one scoped "
+                    + "component:",
+                "    @Singleton test.SingletonComponentA",
+                "    @Singleton test.SingletonComponentB"));
   }
 
   @Test
@@ -675,98 +576,6 @@
   }
 
   @Test
-  public void componentScopeWithMultipleScopedDependenciesMustNotCycle() {
-    JavaFileObject type =
-        JavaFileObjects.forSourceLines(
-            "test.SimpleType",
-            "package test;",
-            "",
-            "import javax.inject.Inject;",
-            "",
-            "class SimpleType {",
-            "  @Inject SimpleType() {}",
-            "}");
-    JavaFileObject scopeA =
-        JavaFileObjects.forSourceLines(
-            "test.ScopeA",
-            "package test;",
-            "",
-            "import javax.inject.Scope;",
-            "",
-            "@Scope @interface ScopeA {}");
-    JavaFileObject scopeB =
-        JavaFileObjects.forSourceLines(
-            "test.ScopeB",
-            "package test;",
-            "",
-            "import javax.inject.Scope;",
-            "",
-            "@Scope @interface ScopeB {}");
-    JavaFileObject longLifetime =
-        JavaFileObjects.forSourceLines(
-            "test.ComponentLong",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@ScopeA",
-            "@Component",
-            "interface ComponentLong {",
-            "  SimpleType type();",
-            "}");
-    JavaFileObject mediumLifetime1 =
-        JavaFileObjects.forSourceLines(
-            "test.ComponentMedium1",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@ScopeB",
-            "@Component(dependencies = ComponentLong.class)",
-            "interface ComponentMedium1 {",
-            "  SimpleType type();",
-            "}");
-    JavaFileObject mediumLifetime2 =
-        JavaFileObjects.forSourceLines(
-            "test.ComponentMedium2",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@ScopeB",
-            "@Component",
-            "interface ComponentMedium2 {",
-            "}");
-    JavaFileObject shortLifetime =
-        JavaFileObjects.forSourceLines(
-            "test.ComponentShort",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@ScopeA",
-            "@Component(dependencies = {ComponentMedium1.class, ComponentMedium2.class})",
-            "interface ComponentShort {",
-            "  SimpleType type();",
-            "}");
-
-    Compilation compilation =
-        daggerCompiler()
-            .compile(
-                type, scopeA, scopeB,
-                longLifetime, mediumLifetime1, mediumLifetime2, shortLifetime);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            message(
-                "test.ComponentShort depends on scoped components in a non-hierarchical scope "
-                    + "ordering:",
-                "    @test.ScopeA test.ComponentLong",
-                "    @test.ScopeB test.ComponentMedium1",
-                "    @test.ScopeA test.ComponentShort"));
-  }
-
-  @Test
   public void componentScopeAncestryMustNotCycle() {
     // The dependency relationship of components is necessarily from shorter lifetimes to
     // longer lifetimes.  The scoping annotations must reflect this, and so one cannot declare
@@ -845,14 +654,6 @@
                 "    @test.ScopeA test.ComponentLong",
                 "    @test.ScopeB test.ComponentMedium",
                 "    @test.ScopeA test.ComponentShort"));
-
-
-    // Test that compilation succeeds when transitive validation is disabled because the scope cycle
-    // cannot be detected.
-    compilation =
-        compilerWithOptions("-Adagger.validateTransitiveComponentDependencies=DISABLED")
-            .compile(type, scopeA, scopeB, longLifetime, mediumLifetime, shortLifetime);
-    assertThat(compilation).succeeded();
   }
 
   @Test
diff --git a/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentTest.java b/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentTest.java
index e143370..3fb0e9c 100644
--- a/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentTest.java
+++ b/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentTest.java
@@ -18,8 +18,8 @@
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static dagger.internal.codegen.Compilers.CLASS_PATH_WITHOUT_GUAVA_OPTION;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
@@ -96,7 +96,7 @@
             "",
             "import dagger.internal.SetBuilder;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  @Override",
             "  public Set<String> strings() {",
@@ -191,9 +191,9 @@
             "import other.UsesInaccessible;",
             "import other.UsesInaccessible_Factory;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
-            "  private Set setOfInaccessible2() {",
+            "  private Set getSetOfInaccessible2() {",
             "    return SetBuilder.newSetBuilder(1)",
             "        .addAll(TestModule_EmptySetFactory.emptySet())",
             "        .build();",
@@ -203,7 +203,7 @@
             "  public UsesInaccessible usesInaccessible() {",
             "    return UsesInaccessible_Factory.newInstance(",
             "        (Set) Collections.emptySet(),",
-            "        (Set) setOfInaccessible2());",
+            "        (Set) getSetOfInaccessible2());",
             "  }",
             "}");
     Compilation compilation =
@@ -266,7 +266,7 @@
             "import java.util.Set;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParent implements Parent {",
             "  private DaggerParent() {}",
             "",
@@ -316,7 +316,7 @@
   }
 
   private Compiler daggerCompilerWithoutGuava() {
-    return compilerWithOptions(compilerMode.javacopts())
-        .withClasspath(CLASS_PATH_WITHOUT_GUAVA_OPTION);
+    return daggerCompiler()
+        .withOptions(compilerMode.javacopts().append(CLASS_PATH_WITHOUT_GUAVA_OPTION));
   }
 }
diff --git a/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentWithGuavaTest.java b/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentWithGuavaTest.java
index 2e3686f..7a47393 100644
--- a/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentWithGuavaTest.java
+++ b/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentWithGuavaTest.java
@@ -17,8 +17,8 @@
 package dagger.internal.codegen;
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
@@ -99,7 +99,7 @@
             "",
             "import com.google.common.collect.ImmutableSet;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
             "  @Override",
             "  public Set<String> strings() {",
@@ -122,7 +122,8 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(emptySetModuleFile, setModuleFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -202,9 +203,9 @@
             "import other.UsesInaccessible;",
             "import other.UsesInaccessible_Factory;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent {",
-            "  private Set setOfInaccessible2() {",
+            "  private Set getSetOfInaccessible2() {",
             "    return ImmutableSet.copyOf(TestModule_EmptySetFactory.emptySet());",
             "  }",
             "",
@@ -212,11 +213,12 @@
             "  public UsesInaccessible usesInaccessible() {",
             "    return UsesInaccessible_Factory.newInstance(",
             "        (Set) ImmutableSet.of(),",
-            "        (Set) setOfInaccessible2());",
+            "        (Set) getSetOfInaccessible2());",
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(module, inaccessible, inaccessible2, usesInaccessible, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -272,7 +274,7 @@
             "",
             "import com.google.common.collect.ImmutableSet;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParent implements Parent {",
             "  private final class ChildImpl implements Child {",
             "    @Override",
@@ -283,7 +285,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(parent, parentModule, child);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(parent, parentModule, child);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerParent")
@@ -331,7 +333,7 @@
             "import java.util.Set;",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerTestComponent implements TestComponent, "
                 + "CancellationListener {",
             "  private DaggerTestComponent() {}",
@@ -344,14 +346,14 @@
             "    return new Builder().build();",
             "  }",
             "",
-            "  private Set<String> setOfString() {",
+            "  private Set<String> getSetOfString() {",
             "    return ImmutableSet.<String>copyOf(",
             "        EmptySetModule_EmptySetFactory.emptySet());",
             "  }",
             "",
             "  @Override",
             "  public ListenableFuture<Set<String>> strings() {",
-            "    return Futures.immediateFuture(setOfString());",
+            "    return Futures.immediateFuture(getSetOfString());",
             "  }",
             "",
             "  @Override",
@@ -367,7 +369,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(emptySetModuleFile, componentFile);
     assertThat(compilation).succeeded();
     assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/SourceFilesTest.java b/javatests/dagger/internal/codegen/SourceFilesTest.java
index 248e2ef..c7fe998 100644
--- a/javatests/dagger/internal/codegen/SourceFilesTest.java
+++ b/javatests/dagger/internal/codegen/SourceFilesTest.java
@@ -17,10 +17,9 @@
 package dagger.internal.codegen;
 
 import static com.google.common.truth.Truth.assertThat;
-import static dagger.internal.codegen.binding.SourceFiles.simpleVariableName;
+import static dagger.internal.codegen.SourceFiles.simpleVariableName;
 
 import com.google.testing.compile.CompilationRule;
-import dagger.internal.codegen.binding.SourceFiles;
 import java.util.List;
 import javax.lang.model.element.TypeElement;
 import org.junit.Rule;
diff --git a/javatests/dagger/internal/codegen/SubcomponentBuilderValidationTest.java b/javatests/dagger/internal/codegen/SubcomponentBuilderValidationTest.java
index 0fd7e08..5dab4c4 100644
--- a/javatests/dagger/internal/codegen/SubcomponentBuilderValidationTest.java
+++ b/javatests/dagger/internal/codegen/SubcomponentBuilderValidationTest.java
@@ -18,12 +18,11 @@
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.SUBCOMPONENT_BUILDER;
-import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.SUBCOMPONENT_BUILDER;
+import static dagger.internal.codegen.ErrorMessages.creatorMessagesFor;
 
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
-import dagger.internal.codegen.binding.ErrorMessages;
 import javax.tools.JavaFileObject;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/javatests/dagger/internal/codegen/SubcomponentCreatorRequestFulfillmentTest.java b/javatests/dagger/internal/codegen/SubcomponentCreatorRequestFulfillmentTest.java
index ea0b4cc..de0067f 100644
--- a/javatests/dagger/internal/codegen/SubcomponentCreatorRequestFulfillmentTest.java
+++ b/javatests/dagger/internal/codegen/SubcomponentCreatorRequestFulfillmentTest.java
@@ -21,15 +21,14 @@
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.SUBCOMPONENT_BUILDER;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.SUBCOMPONENT_FACTORY;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.SUBCOMPONENT_BUILDER;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.SUBCOMPONENT_FACTORY;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.testing.compile.Compilation;
-import dagger.internal.codegen.binding.ComponentCreatorAnnotation;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
@@ -101,7 +100,7 @@
             "",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerC implements C {",
             "  @Override",
             "  public Sub.Builder sBuilder() {",
diff --git a/javatests/dagger/internal/codegen/SubcomponentCreatorValidationTest.java b/javatests/dagger/internal/codegen/SubcomponentCreatorValidationTest.java
index 371253a..b5753d4 100644
--- a/javatests/dagger/internal/codegen/SubcomponentCreatorValidationTest.java
+++ b/javatests/dagger/internal/codegen/SubcomponentCreatorValidationTest.java
@@ -18,19 +18,18 @@
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.SUBCOMPONENT_BUILDER;
+import static dagger.internal.codegen.ComponentCreatorAnnotation.SUBCOMPONENT_FACTORY;
+import static dagger.internal.codegen.ComponentCreatorKind.BUILDER;
+import static dagger.internal.codegen.ComponentCreatorKind.FACTORY;
+import static dagger.internal.codegen.ComponentKind.SUBCOMPONENT;
+import static dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages.moreThanOneRefToSubcomponent;
+import static dagger.internal.codegen.ErrorMessages.componentMessagesFor;
 import static dagger.internal.codegen.TestUtils.message;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.SUBCOMPONENT_BUILDER;
-import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.SUBCOMPONENT_FACTORY;
-import static dagger.internal.codegen.binding.ComponentCreatorKind.BUILDER;
-import static dagger.internal.codegen.binding.ComponentCreatorKind.FACTORY;
-import static dagger.internal.codegen.binding.ComponentKind.SUBCOMPONENT;
-import static dagger.internal.codegen.binding.ErrorMessages.ComponentCreatorMessages.moreThanOneRefToSubcomponent;
-import static dagger.internal.codegen.binding.ErrorMessages.componentMessagesFor;
 
 import com.google.common.collect.ImmutableList;
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
-import dagger.internal.codegen.binding.ComponentCreatorAnnotation;
 import java.util.Collection;
 import javax.tools.JavaFileObject;
 import org.junit.Test;
@@ -674,18 +673,19 @@
     Compilation compilation = compile(componentFile, childComponentFile);
     assertThat(compilation).failed();
     String firstBinding = creatorKind.equals(FACTORY)
-        ? "ChildComponent.Factory.create(s1, …)"
-        : "@BindsInstance void ChildComponent.Builder.set1(String)";
+        ? "test.ChildComponent.Factory.create(s1, …)"
+        : "@BindsInstance void test.ChildComponent.Builder.set1(String)";
     String secondBinding = creatorKind.equals(FACTORY)
-        ? "ChildComponent.Factory.create(…, s2)"
-        : "@BindsInstance void ChildComponent.Builder.set2(String)";
+        ? "test.ChildComponent.Factory.create(…, s2)"
+        : "@BindsInstance void test.ChildComponent.Builder.set2(String)";
     assertThat(compilation)
         .hadErrorContaining(
             message(
-                "String is bound multiple times:",
+                "java.lang.String is bound multiple times:",
                 "    " + firstBinding,
                 "    " + secondBinding,
-                "    in component: [ParentComponent → ChildComponent]"))
+                "    java.lang.String is provided at",
+                "        test.ChildComponent.s() [test.ParentComponent → test.ChildComponent]"))
         .inFile(componentFile)
         .onLineContaining("interface ParentComponent {");
   }
diff --git a/javatests/dagger/internal/codegen/SubcomponentValidationTest.java b/javatests/dagger/internal/codegen/SubcomponentValidationTest.java
index 19a27ff..ad08160 100644
--- a/javatests/dagger/internal/codegen/SubcomponentValidationTest.java
+++ b/javatests/dagger/internal/codegen/SubcomponentValidationTest.java
@@ -19,9 +19,8 @@
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
-import static dagger.internal.codegen.Compilers.compilerWithOptions;
 import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
 
 import com.google.testing.compile.Compilation;
@@ -84,7 +83,8 @@
         "  }",
         "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(componentFile, childComponentFile, moduleFile);
     assertThat(compilation).failed();
     assertThat(compilation)
@@ -152,15 +152,16 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(component, childComponent, grandchildComponent, grandchildModule);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "[ChildComponent.newGrandchildComponent()] "
-                + "GrandchildComponent requires modules which have no visible default "
+            "[test.ChildComponent.newGrandchildComponent()] "
+                + "test.GrandchildComponent requires modules which have no visible default "
                 + "constructors. Add the following modules as parameters to this method: "
-                + "GrandchildModule")
+                + "test.GrandchildModule")
         .inFile(component)
         .onLineContaining("interface TestComponent");
   }
@@ -183,7 +184,8 @@
         "@Subcomponent",
         "interface ChildComponent {}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(componentFile, childComponentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
@@ -219,7 +221,8 @@
         "@Subcomponent(modules = TestModule.class)",
         "interface ChildComponent {}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(moduleFile, componentFile, childComponentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
@@ -256,7 +259,8 @@
         "@Subcomponent",
         "interface ChildComponent {}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(moduleFile, componentFile, childComponentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
@@ -296,15 +300,16 @@
         "",
         "@Subcomponent(modules = TestModule.class)",
         "interface ChildComponent {",
-        "  String string();",
+        "  String getString();",
         "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(moduleFile, componentFile, childComponentFile);
     assertThat(compilation).failed();
     assertThat(compilation)
         .hadErrorContaining(
-            "Integer cannot be provided without an @Inject constructor or an "
+            "java.lang.Integer cannot be provided without an @Inject constructor or an "
                 + "@Provides-annotated method")
         .inFile(componentFile)
         .onLineContaining("interface TestComponent");
@@ -319,7 +324,7 @@
         "@Subcomponent",
         "final class NotASubcomponent {}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(subcomponentFile);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(subcomponentFile);
     assertThat(compilation).failed();
     assertThat(compilation).hadErrorContaining("interface");
   }
@@ -343,7 +348,7 @@
         "",
         "@Subcomponent(modules = ChildModule.class)",
         "interface ChildComponent {",
-        "  Object object();",
+        "  Object getObject();",
         "}");
     JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.ChildModule",
         "package test;",
@@ -357,7 +362,8 @@
         "  @Provides @Singleton Object provideObject() { return null; }",
         "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(componentFile, subcomponentFile, moduleFile);
     assertThat(compilation).failed();
     assertThat(compilation).hadErrorContaining("@Singleton");
@@ -377,8 +383,8 @@
             "@Component",
             "interface ParentComponent {",
             "  ChildComponent childComponent();",
-            "  Dep1 dep1();",
-            "  Dep2 dep2();",
+            "  Dep1 getDep1();",
+            "  Dep2 getDep2();",
             "}");
     JavaFileObject childComponentFile =
         JavaFileObjects.forSourceLines(
@@ -389,7 +395,7 @@
             "",
             "@Subcomponent(modules = ChildModule.class)",
             "interface ChildComponent {",
-            "  Object object();",
+            "  Object getObject();",
             "}");
     JavaFileObject childModuleFile =
         JavaFileObjects.forSourceLines(
@@ -457,7 +463,7 @@
             .addLines(
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerParentComponent implements ParentComponent {")
             .addLinesIn(
                 DEFAULT_MODE,
@@ -469,7 +475,7 @@
                 "")
             .addLines(
                 "  @Override", //
-                "  public Dep1 dep1() {")
+                "  public Dep1 getDep1() {")
             .addLinesIn(
                 FAST_INIT_MODE,
                 "   Object local = dep1;",
@@ -490,7 +496,7 @@
                 "  }", //
                 "",
                 "  @Override",
-                "  public Dep2 dep2() {")
+                "  public Dep2 getDep2() {")
             .addLinesIn(
                 FAST_INIT_MODE,
                 "   Object local = dep2;",
@@ -539,34 +545,34 @@
                 "")
             .addLinesIn(
                 DEFAULT_MODE,
-                "    private NeedsDep1 needsDep1() {",
+                "    private NeedsDep1 getNeedsDep1() {",
                 "      return new NeedsDep1(DaggerParentComponent.this.dep1Provider.get());",
                 "    }")
             .addLinesIn(
                 FAST_INIT_MODE,
-                "    private NeedsDep1 needsDep1() {",
-                "      return new NeedsDep1(DaggerParentComponent.this.dep1());",
+                "    private NeedsDep1 getNeedsDep1() {",
+                "      return new NeedsDep1(DaggerParentComponent.this.getDep1());",
                 "    }")
             .addLines(
-                "    private A a() {",
+                "    private A getA() {",
                 "      return injectA(",
                 "          A_Factory.newInstance(",
-                "              needsDep1(),")
+                "              getNeedsDep1(),")
             .addLinesIn(
                 DEFAULT_MODE,
                 "              DaggerParentComponent.this.dep1Provider.get(),",
                 "              DaggerParentComponent.this.dep2Provider.get()));")
             .addLinesIn(
                 FAST_INIT_MODE,
-                "              DaggerParentComponent.this.dep1(),",
-                "              DaggerParentComponent.this.dep2()));")
+                "              DaggerParentComponent.this.getDep1(),",
+                "              DaggerParentComponent.this.getDep2()));")
             .addLines(
                 "    }",
                 "",
                 "    @Override",
-                "    public Object object() {",
+                "    public Object getObject() {",
                 "      return ChildModule_ProvideObjectFactory.provideObject(",
-                "          childModule, a());",
+                "          childModule, getA());",
                 "    }",
                 "",
                 "    @CanIgnoreReturnValue",
@@ -579,7 +585,8 @@
             .build();
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(
                 parentComponentFile,
                 childComponentFile,
@@ -656,7 +663,7 @@
             "",
             "import test.subpackage.Sub;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParentComponent implements ParentComponent {",
             "  @Override",
             "  public Foo.Sub newInstanceSubcomponent() {",
@@ -693,7 +700,8 @@
             "  private final class NoConflictImpl implements NoConflict {}",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(parent, foo, bar, baz, noConflict);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -738,7 +746,7 @@
             "test.DaggerParentComponent",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParentComponent implements ParentComponent {",
             "  @Override",
             "  public Sub newSubcomponent() {",
@@ -764,7 +772,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(parent, sub, deepSub);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(parent, sub, deepSub);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerParentComponent")
@@ -803,7 +811,7 @@
         JavaFileObjects.forSourceLines(
             "DaggerParentComponent",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParentComponent implements ParentComponent {",
             "  @Override",
             "  public Sub newSubcomponent() {",
@@ -827,7 +835,7 @@
             "");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(parent, sub, deepSub);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(parent, sub, deepSub);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("DaggerParentComponent")
@@ -880,7 +888,7 @@
             "",
             "import top1.a.b.c.d.E;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerParentComponent implements ParentComponent {",
             "  @Override",
             "  public E.F.Sub top1() {",
@@ -901,7 +909,7 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(parent, top1, top2);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(parent, top1, top2);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerParentComponent")
@@ -937,7 +945,7 @@
             "test.DaggerC",
             "package test;",
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerC implements C {",
             "  @Override",
             "  public Foo.C newInstanceC() {",
@@ -948,7 +956,8 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(parent, subcomponentWithSameSimpleNameAsParent);
     assertThat(compilation).succeeded();
     assertThat(compilation)
@@ -998,7 +1007,7 @@
             "",
             IMPORT_GENERATED_ANNOTATION,
             "",
-            GENERATED_CODE_ANNOTATIONS,
+            GENERATED_ANNOTATION,
             "final class DaggerC implements C {",
             "  @Override",
             "  public C.Foo.Sub.Builder fooBuilder() {",
@@ -1010,7 +1019,7 @@
             "    return new B_SubBuilder();",
             "  }",
             "",
-            // TODO(bcorso): Reverse the order of subcomponent and builder so that subcomponent
+            // TODO(user): Reverse the order of subcomponent and builder so that subcomponent
             // comes first.
             "  private final class F_SubBuilder implements C.Foo.Sub.Builder {",
             "    @Override",
@@ -1035,7 +1044,7 @@
             "  }",
             "}");
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts()).compile(parent);
+        daggerCompiler().withOptions(compilerMode.javacopts()).compile(parent);
     assertThat(compilation).succeeded();
     assertThat(compilation)
         .generatedSourceFile("test.DaggerC")
@@ -1088,16 +1097,17 @@
             "}");
 
     Compilation compilation =
-        compilerWithOptions(compilerMode.javacopts())
+        daggerCompiler()
+            .withOptions(compilerMode.javacopts())
             .compile(module, component, subcomponent);
     assertThat(compilation).failed();
-    assertThat(compilation).hadErrorContaining("Sub.Builder is bound multiple times:");
+    assertThat(compilation).hadErrorContaining("test.Sub.Builder is bound multiple times:");
     assertThat(compilation)
         .hadErrorContaining(
-            "@Provides Sub.Builder "
-                + "TestModule.providesConflictsWithModuleSubcomponents()");
+            "@Provides test.Sub.Builder "
+                + "test.TestModule.providesConflictsWithModuleSubcomponents()");
     assertThat(compilation)
-        .hadErrorContaining("@Module(subcomponents = Sub.class) for TestModule");
+        .hadErrorContaining("@Module(subcomponents = test.Sub.class) for test.TestModule");
   }
 
   @Test
diff --git a/javatests/dagger/internal/codegen/SwitchingProviderTest.java b/javatests/dagger/internal/codegen/SwitchingProviderTest.java
index 593ad49..2898f2e 100644
--- a/javatests/dagger/internal/codegen/SwitchingProviderTest.java
+++ b/javatests/dagger/internal/codegen/SwitchingProviderTest.java
@@ -18,7 +18,7 @@
 
 import static com.google.testing.compile.CompilationSubject.assertThat;
 import static com.google.testing.compile.Compiler.javac;
-import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS;
+import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
 
 import com.google.common.collect.ImmutableList;
 import com.google.testing.compile.Compilation;
@@ -68,7 +68,7 @@
         JavaFileObjects.forSourceLines(
             "test.DaggerTestComponent",
                 "package test;",
-            GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private final class SwitchingProvider<T> implements Provider<T> {",
                 "    @SuppressWarnings(\"unchecked\")",
@@ -248,11 +248,11 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private volatile Provider<String> sProvider;",
                 "",
-                "  private Provider<String> stringProvider() {",
+                "  private Provider<String> getStringProvider() {",
                 "    Object local = sProvider;",
                 "    if (local == null) {",
                 "      local = new SwitchingProvider<>(0);",
@@ -263,12 +263,12 @@
                 "",
                 "  @Override",
                 "  public Provider<Object> objectProvider() {",
-                "    return (Provider) stringProvider();",
+                "    return (Provider) getStringProvider();",
                 "  }",
                 "",
                 "  @Override",
                 "  public Provider<CharSequence> charSequenceProvider() {",
-                "    return (Provider) stringProvider();",
+                "    return (Provider) getStringProvider();",
                 "  }",
                 "",
                 "  private final class SwitchingProvider<T> implements Provider<T> {",
@@ -333,12 +333,12 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private volatile Object charSequence = new MemoizedSentinel();",
                 "  private volatile Provider<CharSequence> cProvider;",
                 "",
-                "  private CharSequence charSequence() {",
+                "  private CharSequence getCharSequence() {",
                 "    Object local = charSequence;",
                 "    if (local instanceof MemoizedSentinel) {",
                 "      synchronized (local) {",
@@ -373,7 +373,7 @@
                 "    public T get() {",
                 "      switch (id) {",
                 "        case 0:",
-                "          return (T) DaggerTestComponent.this.charSequence();",
+                "          return (T) DaggerTestComponent.this.getCharSequence();",
                 "        default:",
                 "          throw new AssertionError(id);",
                 "      }",
@@ -424,7 +424,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  @Override",
                 "  public Provider<Set<String>> setProvider() {",
@@ -469,7 +469,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  private Provider<MembersInjector<Foo>> fooMembersInjectorProvider;",
                 "",
@@ -540,7 +540,7 @@
                 "test.DaggerTestComponent",
                 "package test;",
                 "",
-                GENERATED_CODE_ANNOTATIONS,
+                GENERATED_ANNOTATION,
                 "final class DaggerTestComponent implements TestComponent {",
                 "  @SuppressWarnings(\"rawtypes\")",
                 "  private static final Provider ABSENT_JDK_OPTIONAL_PROVIDER =",
diff --git a/javatests/dagger/internal/codegen/TypeProtoConverterTest.java b/javatests/dagger/internal/codegen/TypeProtoConverterTest.java
new file mode 100644
index 0000000..8c8628c
--- /dev/null
+++ b/javatests/dagger/internal/codegen/TypeProtoConverterTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 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.common.truth.Truth.assertWithMessage;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+
+import com.google.testing.compile.CompilationRule;
+import dagger.internal.Factory;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.TypeProto;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.lang.model.type.TypeMirror;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests {@link TypeProtoConverter}. */
+@RunWith(JUnit4.class)
+public class TypeProtoConverterTest {
+  @Rule public CompilationRule compilationRule = new CompilationRule();
+
+  private DaggerElements elements;
+  private DaggerTypes types;
+  private TypeProtoConverter typeProtoConverter;
+
+  @Before
+  public void setUp() {
+    this.elements = new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
+    this.types = new DaggerTypes(compilationRule.getTypes(), elements);
+    this.typeProtoConverter = new TypeProtoConverter(types, elements);
+  }
+
+  static class Outer<O> {
+    @SuppressWarnings("ClassCanBeStatic") // We want to specifically test inner classes
+    class Inner<I> {}
+  }
+
+  @SuppressWarnings({"rawtypes", "unused"})
+  static class TypeMirrorConversionSubjects {
+    private Map rawMap;
+    private List<String> listOfString;
+    private List<HashMap<String, Integer>> listOfHashMapOfStringToInteger;
+    private Map<HashMap<String, Integer>, Set<Factory>> mapOfHashMapOfStringToIntegerToSetOfFactory;
+    private Map<HashMap<String, Integer>, Set<Factory>>[][]
+        arrayOfArrayOfMapOfHashMapOfStringToIntegerToSetOfFactory;
+    private Map<HashMap<?, Integer>, ?> mapOfHashMapOfWildcardToIntegerToWildcard;
+    private List<? extends String> listOfWildcardExtendsString;
+    private List<? extends Set<? super String>> listOfWildcardExtendsSetOfWildcardSuperString;
+    private Outer<Object>.Inner<Integer> outerOfObjectDotInnerOfInteger;
+    private List<int[]> listOfIntArray;
+    private List<? extends CharSequence[]> listOfWildcardExtendsCharSequenceArray;
+  }
+
+  @Test
+  public void typeMirrorProtoConversions() {
+    assertProtoConversionEquality(fieldType("rawMap"));
+    assertProtoConversionEquality(fieldType("listOfString"));
+    assertProtoConversionEquality(fieldType("listOfHashMapOfStringToInteger"));
+    assertProtoConversionEquality(fieldType("mapOfHashMapOfStringToIntegerToSetOfFactory"));
+    assertProtoConversionEquality(
+        fieldType("arrayOfArrayOfMapOfHashMapOfStringToIntegerToSetOfFactory"));
+    assertProtoConversionEquality(fieldType("mapOfHashMapOfWildcardToIntegerToWildcard"));
+    assertProtoConversionEquality(fieldType("listOfWildcardExtendsString"));
+    assertProtoConversionEquality(fieldType("listOfWildcardExtendsSetOfWildcardSuperString"));
+    assertProtoConversionEquality(fieldType("outerOfObjectDotInnerOfInteger"));
+    assertProtoConversionEquality(fieldType("listOfIntArray"));
+    assertProtoConversionEquality(fieldType("listOfWildcardExtendsCharSequenceArray"));
+  }
+
+  private TypeMirror fieldType(String fieldName) {
+    return fieldsIn(
+            elements.getTypeElement(TypeMirrorConversionSubjects.class).getEnclosedElements())
+        .stream()
+        .filter(field -> field.getSimpleName().contentEquals(fieldName))
+        .findFirst()
+        .get()
+        .asType();
+  }
+
+  /**
+   * Converts {@link TypeMirror} to a {@link dagger.internal.codegen.serialization.TypeProto} and
+   * back to a {@link TypeMirror}. Asserts that the round-trip conversion is lossless.
+   */
+  private void assertProtoConversionEquality(TypeMirror typeMirror) {
+    TypeProto toProto = TypeProtoConverter.toProto(typeMirror);
+    TypeMirror fromProto = typeProtoConverter.fromProto(toProto);
+    assertWithMessage("expected: %s\nactual  : %s", typeMirror, fromProto)
+        .that(types.isSameType(typeMirror, fromProto))
+        .isTrue();
+  }
+}
diff --git a/javatests/dagger/internal/codegen/ValidationReportTest.java b/javatests/dagger/internal/codegen/ValidationReportTest.java
index d1c3a2e..b0f2f2f 100644
--- a/javatests/dagger/internal/codegen/ValidationReportTest.java
+++ b/javatests/dagger/internal/codegen/ValidationReportTest.java
@@ -23,8 +23,7 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.testing.compile.Compilation;
 import com.google.testing.compile.JavaFileObjects;
-import dagger.internal.codegen.validation.ValidationReport;
-import dagger.internal.codegen.validation.ValidationReport.Builder;
+import dagger.internal.codegen.ValidationReport.Builder;
 import java.util.Set;
 import javax.annotation.processing.AbstractProcessor;
 import javax.annotation.processing.RoundEnvironment;
diff --git a/javatests/dagger/internal/codegen/javapoet/BUILD b/javatests/dagger/internal/codegen/javapoet/BUILD
index 438d377..99c11bd 100644
--- a/javatests/dagger/internal/codegen/javapoet/BUILD
+++ b/javatests/dagger/internal/codegen/javapoet/BUILD
@@ -15,11 +15,11 @@
 # Description:
 #   Tests for dagger.internal.codegen.javapoet
 
+package(default_visibility = ["//:src"])
+
 load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "javapoet_tests",
     srcs = glob(["*.java"]),
@@ -28,10 +28,10 @@
     deps = [
         "//java/dagger/internal/codegen/javapoet",
         "//java/dagger/internal/codegen/langmodel",
+        "@google_bazel_common//third_party/java/auto:common",
         "@google_bazel_common//third_party/java/compile_testing",
         "@google_bazel_common//third_party/java/javapoet",
         "@google_bazel_common//third_party/java/junit",
         "@google_bazel_common//third_party/java/truth",
-        "@maven//:com_google_auto_auto_common",
     ],
 )
diff --git a/javatests/dagger/lint/BUILD b/javatests/dagger/lint/BUILD
deleted file mode 100644
index 268340d..0000000
--- a/javatests/dagger/lint/BUILD
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2020 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.
-
-# Description:
-#   Tests for the Dagger Lint Rules
-
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_test")
-
-package(default_visibility = ["//:src"])
-
-kt_jvm_test(
-    name = "DaggerKotlinIssueDetectorTest",
-    srcs = ["DaggerKotlinIssueDetectorTest.kt"],
-    deps = [
-        "@google_bazel_common//third_party/java/junit",
-        "//java/dagger/lint:lint-artifact-lib",
-        "@maven//:com_android_tools_lint_lint_checks",
-        "@maven//:com_android_tools_lint_lint_tests",
-        "@maven//:com_android_tools_testutils",
-        "@maven//:org_jetbrains_kotlin_kotlin_stdlib",
-    ],
-)
diff --git a/javatests/dagger/lint/DaggerKotlinIssueDetectorTest.kt b/javatests/dagger/lint/DaggerKotlinIssueDetectorTest.kt
deleted file mode 100644
index f112392..0000000
--- a/javatests/dagger/lint/DaggerKotlinIssueDetectorTest.kt
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2020 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.lint
-
-import com.android.tools.lint.checks.infrastructure.LintDetectorTest
-import com.android.tools.lint.detector.api.Detector
-import com.android.tools.lint.detector.api.Issue
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@Suppress("UnstableApiUsage")
-@RunWith(JUnit4::class)
-class DaggerKotlinIssueDetectorTest : LintDetectorTest() {
-
-  private companion object {
-    private val javaxInjectStubs = kotlin(
-      """
-        package javax.inject
-
-        annotation class Inject
-        annotation class Qualifier
-      """
-    ).indented()
-
-    private val daggerStubs = kotlin(
-      """
-        package dagger
-
-        annotation class Provides
-        annotation class Module
-      """
-    ).indented()
-
-    // For some reason in Bazel the stdlib dependency on the classpath isn't visible to the
-    // LintTestTask, so we just include it ourselves here for now.
-    private val jvmStaticStubs = kotlin(
-      """
-        package kotlin.jvm
-
-        annotation class JvmStatic
-      """
-    ).indented()
-  }
-
-  override fun getDetector(): Detector = DaggerKotlinIssueDetector()
-
-  override fun getIssues(): List<Issue> = DaggerKotlinIssueDetector.issues
-
-  @Test
-  fun simpleSmokeTestForQualifiersAndProviders() {
-    lint()
-      .allowMissingSdk()
-      .files(
-        javaxInjectStubs,
-        daggerStubs,
-        jvmStaticStubs,
-        kotlin(
-          """
-          package foo
-          import javax.inject.Inject
-          import javax.inject.Qualifier
-          import kotlin.jvm.JvmStatic
-          import dagger.Provides
-          import dagger.Module
-
-          @Qualifier
-          annotation class MyQualifier
-
-          class InjectedTest {
-            // This should fail because of `:field`
-            @Inject
-            @field:MyQualifier
-            lateinit var prop: String
-
-            // This is fine!
-            @Inject
-            @MyQualifier
-            lateinit var prop2: String
-          }
-
-          @Module
-          object ObjectModule {
-            // This should fail because it uses `@JvmStatic`
-            @JvmStatic
-            @Provides
-            fun provideFoo(): String {
-
-            }
-
-            // This is fine!
-            @Provides
-            fun provideBar(): String {
-
-            }
-          }
-
-          @Module
-          class ClassModule {
-            companion object {
-              // This should fail because the companion object is part of ClassModule, so this is unnecessary.
-              @JvmStatic
-              @Provides
-              fun provideBaz(): String {
-
-              }
-            }
-          }
-
-          @Module
-          class ClassModuleQualified {
-            companion object {
-              // This should fail because the companion object is part of ClassModule, so this is unnecessary.
-              // This specifically tests a fully qualified annotation
-              @kotlin.jvm.JvmStatic
-              @Provides
-              fun provideBaz(): String {
-
-              }
-            }
-          }
-
-          @Module
-          class ClassModule2 {
-            // This should fail because the companion object is part of ClassModule
-            @Module
-            companion object {
-              @Provides
-              fun provideBaz(): String {
-
-              }
-            }
-          }
-
-          @Module
-          class ClassModule2Qualified {
-            // This should fail because the companion object is part of ClassModule
-            // This specifically tests a fully qualified annotation
-            @dagger.Module
-            companion object {
-              @Provides
-              fun provideBaz(): String {
-
-              }
-            }
-          }
-
-          // This is correct as of Dagger 2.26!
-          @Module
-          class ClassModule3 {
-            companion object {
-              @Provides
-              fun provideBaz(): String {
-
-              }
-            }
-          }
-
-          class ClassModule4 {
-            // This is should fail because this should be extracted to a standalone object.
-            @Module
-            companion object {
-              @Provides
-              fun provideBaz(): String {
-
-              }
-            }
-          }
-        """
-        ).indented()
-      )
-      .allowCompilationErrors(false)
-      .run()
-      .expect(
-        """
-        src/foo/MyQualifier.kt:14: Warning: Redundant 'field:' used for Dagger qualifier annotation. [FieldSiteTargetOnQualifierAnnotation]
-          @field:MyQualifier
-          ~~~~~~~~~~~~~~~~~~
-        src/foo/MyQualifier.kt:26: Warning: @JvmStatic used for @Provides function in an object class [JvmStaticProvidesInObjectDetector]
-          @JvmStatic
-          ~~~~~~~~~~
-        src/foo/MyQualifier.kt:43: Warning: @JvmStatic used for @Provides function in an object class [JvmStaticProvidesInObjectDetector]
-            @JvmStatic
-            ~~~~~~~~~~
-        src/foo/MyQualifier.kt:56: Warning: @JvmStatic used for @Provides function in an object class [JvmStaticProvidesInObjectDetector]
-            @kotlin.jvm.JvmStatic
-            ~~~~~~~~~~~~~~~~~~~~~
-        src/foo/MyQualifier.kt:66: Warning: Module companion objects should not be annotated with @Module. [ModuleCompanionObjects]
-          // This should fail because the companion object is part of ClassModule
-          ^
-        src/foo/MyQualifier.kt:78: Warning: Module companion objects should not be annotated with @Module. [ModuleCompanionObjects]
-          // This should fail because the companion object is part of ClassModule
-          ^
-        src/foo/MyQualifier.kt:101: Warning: Module companion objects should not be annotated with @Module. [ModuleCompanionObjects]
-          // This is should fail because this should be extracted to a standalone object.
-          ^
-        0 errors, 7 warnings
-        """.trimIndent()
-      )
-      .expectFixDiffs(
-        """
-        Fix for src/foo/MyQualifier.kt line 14: Remove 'field:':
-        @@ -14 +14
-        -   @field:MyQualifier
-        +   @MyQualifier
-        Fix for src/foo/MyQualifier.kt line 26: Remove @JvmStatic:
-        @@ -26 +26
-        -   @JvmStatic
-        +  
-        Fix for src/foo/MyQualifier.kt line 43: Remove @JvmStatic:
-        @@ -43 +43
-        -     @JvmStatic
-        +    
-        Fix for src/foo/MyQualifier.kt line 56: Remove @JvmStatic:
-        @@ -56 +56
-        -     @kotlin.jvm.JvmStatic
-        +    
-        Fix for src/foo/MyQualifier.kt line 66: Remove @Module:
-        @@ -67 +67
-        -   @Module
-        +  
-        Fix for src/foo/MyQualifier.kt line 78: Remove @Module:
-        @@ -80 +80
-        -   @dagger.Module
-        +  
-        Fix for src/foo/MyQualifier.kt line 101: Remove @Module:
-        @@ -102 +102
-        -   @Module
-        +  
-        """.trimIndent()
-      )
-  }
-}
diff --git a/javatests/dagger/producers/BUILD b/javatests/dagger/producers/BUILD
index 9404d85..1e1bd66 100644
--- a/javatests/dagger/producers/BUILD
+++ b/javatests/dagger/producers/BUILD
@@ -15,6 +15,8 @@
 # Description:
 #   Tests for dagger.producers
 
+package(default_visibility = ["//:src"])
+
 load(
     "//:build_defs.bzl",
     "DOCLINT_HTML_AND_SYNTAX",
@@ -23,17 +25,14 @@
 )
 load("//:test_defs.bzl", "GenJavaTests")
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "producers_tests",
     srcs = glob(["**/*.java"]),
     functional = 0,
     javacopts = SOURCE_7_TARGET_7 + DOCLINT_REFERENCES + DOCLINT_HTML_AND_SYNTAX,
     deps = [
-        "//java/dagger/internal/guava:collect",
-        "//java/dagger/internal/guava:concurrent",
         "//java/dagger/producers",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/guava:testlib",
         "@google_bazel_common//third_party/java/junit",
         "@google_bazel_common//third_party/java/mockito",
diff --git a/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java b/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
index af13504..b29cb3c 100644
--- a/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
+++ b/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
@@ -18,8 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
@@ -56,7 +55,7 @@
   public void initMocks() {
     MockitoAnnotations.initMocks(this);
     monitor = Mockito.mock(ProducerMonitor.class, Mockito.CALLS_REAL_METHODS);
-    when(componentMonitor.producerMonitorFor(nullable(ProducerToken.class))).thenReturn(monitor);
+    when(componentMonitor.producerMonitorFor(any(ProducerToken.class))).thenReturn(monitor);
     componentMonitorProvider =
         new Provider<ProductionComponentMonitor>() {
           @Override
diff --git a/javatests/dagger/producers/monitoring/TimingProductionComponentMonitorTest.java b/javatests/dagger/producers/monitoring/TimingProductionComponentMonitorTest.java
index 5c443a4..449b5a6 100644
--- a/javatests/dagger/producers/monitoring/TimingProductionComponentMonitorTest.java
+++ b/javatests/dagger/producers/monitoring/TimingProductionComponentMonitorTest.java
@@ -16,7 +16,7 @@
 
 package dagger.producers.monitoring;
 
-import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
diff --git a/javatests/dagger/producers/monitoring/TimingRecordersTest.java b/javatests/dagger/producers/monitoring/TimingRecordersTest.java
index eefcb01..4e5d74f 100644
--- a/javatests/dagger/producers/monitoring/TimingRecordersTest.java
+++ b/javatests/dagger/producers/monitoring/TimingRecordersTest.java
@@ -17,9 +17,8 @@
 package dagger.producers.monitoring;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyLong;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -97,8 +96,7 @@
   public void singleRecorder_nullProducerTimingRecorder() {
     when(mockProductionComponentTimingRecorderFactory.create(any(Object.class)))
         .thenReturn(mockProductionComponentTimingRecorder);
-    when(mockProductionComponentTimingRecorder.producerTimingRecorderFor(
-            nullable(ProducerToken.class)))
+    when(mockProductionComponentTimingRecorder.producerTimingRecorderFor(any(ProducerToken.class)))
         .thenReturn(null);
     ProductionComponentTimingRecorder.Factory factory =
         TimingRecorders.delegatingProductionComponentTimingRecorderFactory(
@@ -112,8 +110,7 @@
   public void singleRecorder_throwingProductionComponentTimingRecorder() {
     when(mockProductionComponentTimingRecorderFactory.create(any(Object.class)))
         .thenReturn(mockProductionComponentTimingRecorder);
-    when(mockProductionComponentTimingRecorder.producerTimingRecorderFor(
-            nullable(ProducerToken.class)))
+    when(mockProductionComponentTimingRecorder.producerTimingRecorderFor(any(ProducerToken.class)))
         .thenThrow(new RuntimeException("monkey"));
     ProductionComponentTimingRecorder.Factory factory =
         TimingRecorders.delegatingProductionComponentTimingRecorderFactory(
@@ -223,8 +220,7 @@
         .thenReturn(mockProductionComponentTimingRecorderA);
     when(mockProductionComponentTimingRecorderFactoryB.create(any(Object.class))).thenReturn(null);
     when(mockProductionComponentTimingRecorderFactoryC.create(any(Object.class))).thenReturn(null);
-    when(mockProductionComponentTimingRecorderA.producerTimingRecorderFor(
-            nullable(ProducerToken.class)))
+    when(mockProductionComponentTimingRecorderA.producerTimingRecorderFor(any(ProducerToken.class)))
         .thenReturn(mockProducerTimingRecorderA);
     ProductionComponentTimingRecorder.Factory factory =
         TimingRecorders.delegatingProductionComponentTimingRecorderFactory(
@@ -253,8 +249,7 @@
         .thenThrow(new RuntimeException("monkey"));
     when(mockProductionComponentTimingRecorderFactoryC.create(any(Object.class)))
         .thenThrow(new RuntimeException("monkey"));
-    when(mockProductionComponentTimingRecorderA.producerTimingRecorderFor(
-            nullable(ProducerToken.class)))
+    when(mockProductionComponentTimingRecorderA.producerTimingRecorderFor(any(ProducerToken.class)))
         .thenReturn(mockProducerTimingRecorderA);
     ProductionComponentTimingRecorder.Factory factory =
         TimingRecorders.delegatingProductionComponentTimingRecorderFactory(
@@ -345,8 +340,7 @@
   private void setUpNormalSingleRecorder() {
     when(mockProductionComponentTimingRecorderFactory.create(any(Object.class)))
         .thenReturn(mockProductionComponentTimingRecorder);
-    when(mockProductionComponentTimingRecorder.producerTimingRecorderFor(
-            nullable(ProducerToken.class)))
+    when(mockProductionComponentTimingRecorder.producerTimingRecorderFor(any(ProducerToken.class)))
         .thenReturn(mockProducerTimingRecorder);
   }
 
@@ -357,14 +351,11 @@
         .thenReturn(mockProductionComponentTimingRecorderB);
     when(mockProductionComponentTimingRecorderFactoryC.create(any(Object.class)))
         .thenReturn(mockProductionComponentTimingRecorderC);
-    when(mockProductionComponentTimingRecorderA.producerTimingRecorderFor(
-            nullable(ProducerToken.class)))
+    when(mockProductionComponentTimingRecorderA.producerTimingRecorderFor(any(ProducerToken.class)))
         .thenReturn(mockProducerTimingRecorderA);
-    when(mockProductionComponentTimingRecorderB.producerTimingRecorderFor(
-            nullable(ProducerToken.class)))
+    when(mockProductionComponentTimingRecorderB.producerTimingRecorderFor(any(ProducerToken.class)))
         .thenReturn(mockProducerTimingRecorderB);
-    when(mockProductionComponentTimingRecorderC.producerTimingRecorderFor(
-            nullable(ProducerToken.class)))
+    when(mockProductionComponentTimingRecorderC.producerTimingRecorderFor(any(ProducerToken.class)))
         .thenReturn(mockProducerTimingRecorderC);
   }
 }
diff --git a/javatests/dagger/producers/monitoring/internal/MonitorsTest.java b/javatests/dagger/producers/monitoring/internal/MonitorsTest.java
index ada4e33..47ccccb 100644
--- a/javatests/dagger/producers/monitoring/internal/MonitorsTest.java
+++ b/javatests/dagger/producers/monitoring/internal/MonitorsTest.java
@@ -17,8 +17,7 @@
 package dagger.producers.monitoring.internal;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -88,7 +87,7 @@
   public void singleMonitor_nullProducerMonitor() {
     when(mockProductionComponentMonitorFactory.create(any(Object.class)))
         .thenReturn(mockProductionComponentMonitor);
-    when(mockProductionComponentMonitor.producerMonitorFor(nullable(ProducerToken.class)))
+    when(mockProductionComponentMonitor.producerMonitorFor(any(ProducerToken.class)))
         .thenReturn(null);
     ProductionComponentMonitor.Factory factory =
         Monitors.delegatingProductionComponentMonitorFactory(
@@ -104,7 +103,7 @@
         .thenReturn(mockProductionComponentMonitor);
     doThrow(new RuntimeException("monkey"))
         .when(mockProductionComponentMonitor)
-        .producerMonitorFor(nullable(ProducerToken.class));
+        .producerMonitorFor(any(ProducerToken.class));
     ProductionComponentMonitor.Factory factory =
         Monitors.delegatingProductionComponentMonitorFactory(
             ImmutableList.of(mockProductionComponentMonitorFactory));
@@ -165,9 +164,7 @@
     doThrow(new RuntimeException("monkey")).when(mockProducerMonitor).requested();
     doThrow(new RuntimeException("monkey")).when(mockProducerMonitor).methodStarting();
     doThrow(new RuntimeException("monkey")).when(mockProducerMonitor).methodFinished();
-    doThrow(new RuntimeException("monkey"))
-        .when(mockProducerMonitor)
-        .succeeded(nullable(Object.class));
+    doThrow(new RuntimeException("monkey")).when(mockProducerMonitor).succeeded(any(Object.class));
     ProductionComponentMonitor.Factory factory =
         Monitors.delegatingProductionComponentMonitorFactory(
             ImmutableList.of(mockProductionComponentMonitorFactory));
@@ -255,7 +252,7 @@
         .thenReturn(mockProductionComponentMonitorA);
     when(mockProductionComponentMonitorFactoryB.create(any(Object.class))).thenReturn(null);
     when(mockProductionComponentMonitorFactoryC.create(any(Object.class))).thenReturn(null);
-    when(mockProductionComponentMonitorA.producerMonitorFor(nullable(ProducerToken.class)))
+    when(mockProductionComponentMonitorA.producerMonitorFor(any(ProducerToken.class)))
         .thenReturn(mockProducerMonitorA);
     ProductionComponentMonitor.Factory factory =
         Monitors.delegatingProductionComponentMonitorFactory(
@@ -291,7 +288,7 @@
     doThrow(new RuntimeException("monkey"))
         .when(mockProductionComponentMonitorFactoryC)
         .create(any(Object.class));
-    when(mockProductionComponentMonitorA.producerMonitorFor(nullable(ProducerToken.class)))
+    when(mockProductionComponentMonitorA.producerMonitorFor(any(ProducerToken.class)))
         .thenReturn(mockProducerMonitorA);
     ProductionComponentMonitor.Factory factory =
         Monitors.delegatingProductionComponentMonitorFactory(
@@ -393,9 +390,7 @@
     doThrow(new RuntimeException("monkey")).when(mockProducerMonitorA).requested();
     doThrow(new RuntimeException("monkey")).when(mockProducerMonitorA).methodStarting();
     doThrow(new RuntimeException("monkey")).when(mockProducerMonitorB).methodFinished();
-    doThrow(new RuntimeException("monkey"))
-        .when(mockProducerMonitorC)
-        .succeeded(nullable(Object.class));
+    doThrow(new RuntimeException("monkey")).when(mockProducerMonitorC).succeeded(any(Object.class));
     ProductionComponentMonitor.Factory factory =
         Monitors.delegatingProductionComponentMonitorFactory(
             ImmutableList.of(
@@ -470,7 +465,7 @@
   private void setUpNormalSingleMonitor() {
     when(mockProductionComponentMonitorFactory.create(any(Object.class)))
         .thenReturn(mockProductionComponentMonitor);
-    when(mockProductionComponentMonitor.producerMonitorFor(nullable(ProducerToken.class)))
+    when(mockProductionComponentMonitor.producerMonitorFor(any(ProducerToken.class)))
         .thenReturn(mockProducerMonitor);
   }
 
@@ -481,11 +476,11 @@
         .thenReturn(mockProductionComponentMonitorB);
     when(mockProductionComponentMonitorFactoryC.create(any(Object.class)))
         .thenReturn(mockProductionComponentMonitorC);
-    when(mockProductionComponentMonitorA.producerMonitorFor(nullable(ProducerToken.class)))
+    when(mockProductionComponentMonitorA.producerMonitorFor(any(ProducerToken.class)))
         .thenReturn(mockProducerMonitorA);
-    when(mockProductionComponentMonitorB.producerMonitorFor(nullable(ProducerToken.class)))
+    when(mockProductionComponentMonitorB.producerMonitorFor(any(ProducerToken.class)))
         .thenReturn(mockProducerMonitorB);
-    when(mockProductionComponentMonitorC.producerMonitorFor(nullable(ProducerToken.class)))
+    when(mockProductionComponentMonitorC.producerMonitorFor(any(ProducerToken.class)))
         .thenReturn(mockProducerMonitorC);
   }
 }
diff --git a/javatests/dagger/spi/BUILD b/javatests/dagger/spi/BUILD
index 849037b..a94461b 100644
--- a/javatests/dagger/spi/BUILD
+++ b/javatests/dagger/spi/BUILD
@@ -15,6 +15,8 @@
 # Description:
 #   Tests for the Dagger SPI
 
+package(default_visibility = ["//:src"])
+
 load("//:test_defs.bzl", "GenJavaTests")
 load(
     "//:build_defs.bzl",
@@ -22,8 +24,6 @@
     "DOCLINT_REFERENCES",
 )
 
-package(default_visibility = ["//:src"])
-
 GenJavaTests(
     name = "spi_tests",
     srcs = glob(["*.java"]),
@@ -32,11 +32,11 @@
     deps = [
         "//java/dagger:core",
         "//java/dagger/internal/codegen:processor",
-        "//java/dagger/internal/guava:base",
-        "//java/dagger/internal/guava:collect",
+        "//java/dagger/model",
         "//java/dagger/spi",
         "@google_bazel_common//third_party/java/auto:service",
         "@google_bazel_common//third_party/java/compile_testing",
+        "@google_bazel_common//third_party/java/guava",
         "@google_bazel_common//third_party/java/jsr330_inject",
         "@google_bazel_common//third_party/java/junit",
         "@google_bazel_common//third_party/java/truth",
diff --git a/javatests/dagger/spi/FailingPlugin.java b/javatests/dagger/spi/FailingPlugin.java
index 2d13e21..8fd0e35 100644
--- a/javatests/dagger/spi/FailingPlugin.java
+++ b/javatests/dagger/spi/FailingPlugin.java
@@ -83,6 +83,7 @@
           .forEach(
               edge -> diagnosticReporter.reportDependency(ERROR, edge, "Bad Dependency: %s", edge));
     }
+
   }
 
   @Override
diff --git a/javatests/dagger/spi/SpiPluginTest.java b/javatests/dagger/spi/SpiPluginTest.java
index 1df8cd1..613a915 100644
--- a/javatests/dagger/spi/SpiPluginTest.java
+++ b/javatests/dagger/spi/SpiPluginTest.java
@@ -53,9 +53,7 @@
         javac()
             .withProcessors(new ComponentProcessor())
             .withOptions(
-                "-Aerror_on_binding=java.lang.Integer",
-                "-Adagger.fullBindingGraphValidation=ERROR",
-                "-Adagger.pluginsVisitFullBindingGraphs=ENABLED")
+                "-Aerror_on_binding=java.lang.Integer", "-Adagger.fullBindingGraphValidation=ERROR")
             .compile(module);
     assertThat(compilation).failed();
     assertThat(compilation)
@@ -99,7 +97,7 @@
         .hadErrorContaining(
             message(
                 "[FailingPlugin] Bad Binding: @Inject test.Foo()",
-                "    test.Foo is requested at",
+                "    test.Foo is provided at",
                 "        test.TestComponent.foo()"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
@@ -187,7 +185,7 @@
         .hadErrorContaining(
             message(
                 "[FailingPlugin] Bad Dependency: test.TestComponent.entryPoint() (entry point)",
-                "    test.EntryPoint is requested at",
+                "    test.EntryPoint is provided at",
                 "        test.TestComponent.entryPoint()"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
@@ -197,7 +195,7 @@
                 "[FailingPlugin] Bad Dependency: test.EntryPoint(…, dup1, …)",
                 "    test.Duplicated is injected at",
                 "        test.EntryPoint(…, dup1, …)",
-                "    test.EntryPoint is requested at",
+                "    test.EntryPoint is provided at",
                 "        test.TestComponent.entryPoint()"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
@@ -207,7 +205,7 @@
                 "[FailingPlugin] Bad Dependency: test.EntryPoint(…, dup2)",
                 "    test.Duplicated is injected at",
                 "        test.EntryPoint(…, dup2)",
-                "    test.EntryPoint is requested at",
+                "    test.EntryPoint is provided at",
                 "        test.TestComponent.entryPoint()"))
         .inFile(component)
         .onLineContaining("interface TestComponent");
@@ -222,7 +220,7 @@
                 "        test.Foo(inFooDep)",
                 "    test.Foo is injected at",
                 "        test.EntryPoint(foo, …)",
-                "    test.EntryPoint is requested at",
+                "    test.EntryPoint is provided at",
                 "        test.TestComponent.entryPoint()",
                 "The following other entry points also depend on it:",
                 "    test.TestComponent.chain()"))
@@ -282,7 +280,7 @@
             message(
                 "[FailingPlugin] Bad Dependency: "
                     + "test.TestSubcomponent.childEntryPoint() (entry point)",
-                "    test.EntryPoint is requested at",
+                "    test.EntryPoint is provided at",
                 "        test.TestSubcomponent.childEntryPoint()"
                     + " [test.TestComponent → test.TestSubcomponent]"))
         .inFile(component)
@@ -297,7 +295,7 @@
                 "[FailingPlugin] Bad Dependency: test.EntryPoint(foo)",
                 "    test.Foo is injected at",
                 "        test.EntryPoint(foo)",
-                "    test.EntryPoint is requested at",
+                "    test.EntryPoint is provided at",
                 "        test.TestSubcomponent.childEntryPoint() "
                     + "[test.TestComponent → test.TestSubcomponent]"))
         .inFile(component)
@@ -474,7 +472,7 @@
                 "        test.Chain2(chain)",
                 "    test.Chain2 is injected at",
                 "        test.Chain1(chain)",
-                "    test.Chain1 is requested at",
+                "    test.Chain1 is provided at",
                 "        test.TestComponent.chain()",
                 "The following other entry points also depend on it:",
                 "    test.TestSubcomponent.exposedOnSubcomponent() "
diff --git a/lib/NOTICE b/lib/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/lib/NOTICE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/lib/auto-common-0.10-sources.jar b/lib/auto-common-0.10-sources.jar
new file mode 100644
index 0000000..59bf056
--- /dev/null
+++ b/lib/auto-common-0.10-sources.jar
Binary files differ
diff --git a/lib/auto-common-0.10-sources.jar.asc b/lib/auto-common-0.10-sources.jar.asc
new file mode 100644
index 0000000..ecc3339
--- /dev/null
+++ b/lib/auto-common-0.10-sources.jar.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1
+
+iQEcBAABAgAGBQJaYLeuAAoJEF4feafCmGYeVzIH/A0rkeHli229WFOj5c3HnFqK
+hbyy32JRw8GZXTqNFamkuxWDF03jHwQn0ymp0nxRQ+I3JRTzbfuTnT73e+kiNSI8
+02PowzbrghgsuaifiOGpHaO/FRSBaexzjE1TbZncO6jM8RIg1J7GPqgUenRwA5YT
+7VL7Ig+5G9bXOZMcQ4OuHwqi2O1rSfnSDDIFGlDqmKNiJWHi4KijxNred9CvUGeW
+7zFBOzQkqUqm7Vs2MHmBvNM79fcD1F1SFa2I7+p6/oD1ecC0TAHLdlLhR1/sLBaG
+iw3uQeeflVZ6ilzJg93Rl2kNUw77nnywkt12SY76j1tpF5Ny2l8tid3bBrQEUPE=
+=0e1a
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-common-0.10-sources.jar.sha1 b/lib/auto-common-0.10-sources.jar.sha1
new file mode 100644
index 0000000..b9b3bee
--- /dev/null
+++ b/lib/auto-common-0.10-sources.jar.sha1
@@ -0,0 +1 @@
+913c8de9604380c6e135086132adb26c77fa6c53
\ No newline at end of file
diff --git a/lib/auto-common-0.10.jar b/lib/auto-common-0.10.jar
new file mode 100644
index 0000000..8cbfa72
--- /dev/null
+++ b/lib/auto-common-0.10.jar
Binary files differ
diff --git a/lib/auto-common-0.10.jar.asc b/lib/auto-common-0.10.jar.asc
new file mode 100644
index 0000000..6d81bdf
--- /dev/null
+++ b/lib/auto-common-0.10.jar.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1
+
+iQEcBAABAgAGBQJaYLeuAAoJEF4feafCmGYe/1gIAInqdd+9NqxfOKRw6ujpL3nT
+XmmsP9gR/Tvvi3xRKj8PjcO9ydO2IfQ9ySAS6qbKuS9SIQn+Plq+6E+rwYkKy5t/
+MZ7Ff59XgMW0uxFEA2zUbcprgQyR6M4A31MYVmKuZ2fGBs5OsoN0+sZPCDmo4EzN
+TIgZ/LdNUWXLIsIRAKzCnUkYjlnNHKcJbW527obNH0UF/TBARrEAtmfCbKT6f91/
+zl1GtnxNR/9LVRxErFHQPcHrRxVP72xRHjdTCJHsL0t5cJJPr9maqkXq8DAyyptU
+XcjisvelIubTqnBDXcqJBIM3beGYPa5rot+3NjnNbylbfSqMED1dSGJL/fypY/U=
+=5BoX
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-common-0.10.jar.sha1 b/lib/auto-common-0.10.jar.sha1
new file mode 100644
index 0000000..2056a80
--- /dev/null
+++ b/lib/auto-common-0.10.jar.sha1
@@ -0,0 +1 @@
+c8f153ebe04a17183480ab4016098055fb474364
\ No newline at end of file
diff --git a/lib/auto-factory-1.0-beta6-sources.jar b/lib/auto-factory-1.0-beta6-sources.jar
new file mode 100644
index 0000000..56c6909
--- /dev/null
+++ b/lib/auto-factory-1.0-beta6-sources.jar
Binary files differ
diff --git a/lib/auto-factory-1.0-beta6-sources.jar.asc b/lib/auto-factory-1.0-beta6-sources.jar.asc
new file mode 100644
index 0000000..be05c6e
--- /dev/null
+++ b/lib/auto-factory-1.0-beta6-sources.jar.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQEzBAABCgAdFiEEMoi4voUS1sDKGFJoxR5svH/0bwsFAlvN1rYACgkQxR5svH/0
+bwsyngf8C60gBeqMcbTJ05w6IccmLONiVEBfXXVASLGxJRW6A4C6CZCOaeu/JTGV
+RlyKSL4RxT6LdN4IE1k/b+SWwhAGxES6n2J1G9TFq/SiRSEjPL2a41qRynjXo9Sx
+D/jWX4flGS4fT229EDx18d+Vy3So5+jPNLN7KyB4E9yBZfnTTmeENsgvs0Y1jw5D
+MNK73Nwwg+f7R42J+07FauRU8YXPYcG1UYZcnmAeHNDmwfL1UOsfSzrglHbU59mw
+MrupMb3h5VSBZcqknQUBbPQUUWo7e+jSJZKDB750CxBNSBfF3tN2D1vJ1/ynCIDA
+i+iY39xggnIbyKTPj1/aOGTBVfiVJQ==
+=xs9M
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-factory-1.0-beta6-sources.jar.sha1 b/lib/auto-factory-1.0-beta6-sources.jar.sha1
new file mode 100644
index 0000000..9b5c0a8
--- /dev/null
+++ b/lib/auto-factory-1.0-beta6-sources.jar.sha1
@@ -0,0 +1 @@
+fab31580230ac3001579238a8857a74bd045e3b9
\ No newline at end of file
diff --git a/lib/auto-factory-1.0-beta6.jar b/lib/auto-factory-1.0-beta6.jar
new file mode 100644
index 0000000..e47130f
--- /dev/null
+++ b/lib/auto-factory-1.0-beta6.jar
Binary files differ
diff --git a/lib/auto-factory-1.0-beta6.jar.asc b/lib/auto-factory-1.0-beta6.jar.asc
new file mode 100644
index 0000000..5da4253
--- /dev/null
+++ b/lib/auto-factory-1.0-beta6.jar.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQEzBAABCgAdFiEEMoi4voUS1sDKGFJoxR5svH/0bwsFAlvN1rIACgkQxR5svH/0
+bwt0VAf/S4AELEOE7cdcSkSF8vNCUhHgJbyRIb9SLT9Jh6ZXt0sVt1ZMB4Jcx9WL
+GfIwCAZhPcidTF3yVRvK0Sj2zHq53bGNsejL5BLO73oSoVowv7NV96v42zbBtMDU
+K6AI8G7lXEHYDlW4gwiyz/5CjP8VYSJgQ5vuC81rNL0vrBY0S30MlzHmCLjCvE2b
+DpV+thGWluhStwJRwvQArtUDgXYW6BPGetls/Mr0LKiSvz9uS9EvRvcQHiiwqxPu
+Jj5vheKyyeaRq7BOOswoUvfidr+UrNBt/Jit3L2kuo5n4n7sfb6irR610X8mMMN/
+kx5cA78f+p7XHbLZh6w3pySp+HCvKw==
+=1KAq
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-factory-1.0-beta6.jar.sha1 b/lib/auto-factory-1.0-beta6.jar.sha1
new file mode 100644
index 0000000..57a5e61
--- /dev/null
+++ b/lib/auto-factory-1.0-beta6.jar.sha1
@@ -0,0 +1 @@
+58c804763a4d80c0884ac8a740fcff4d61da72bc
\ No newline at end of file
diff --git a/lib/auto-service-1.0-rc5-sources.jar b/lib/auto-service-1.0-rc5-sources.jar
new file mode 100644
index 0000000..8a05c9d
--- /dev/null
+++ b/lib/auto-service-1.0-rc5-sources.jar
Binary files differ
diff --git a/lib/auto-service-1.0-rc5-sources.jar.asc b/lib/auto-service-1.0-rc5-sources.jar.asc
new file mode 100644
index 0000000..08ea732
--- /dev/null
+++ b/lib/auto-service-1.0-rc5-sources.jar.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQEzBAABCgAdFiEEMoi4voUS1sDKGFJoxR5svH/0bwsFAlyZH5AACgkQxR5svH/0
+bwuBWwf/QMOlEF0td8ykweHGoOt5B6JmBLk4lPNhZDZdGmvqn+RzbWHo7F5QoBL6
+RQ+Wn97UDroLrIeMRsWvOzL/dA/kMhE2tNX8OKP1kaU7d1ahSkY6PRrPrdcf34IA
+Ku62psSXM5L78HdmhfVpf6UBsa3QJ9ZtLrBMjubxJ7aVrHCTIPP8obVgfgFWHnZD
+nGiynMUNXT6H+L9mDtkWHnVEkC07VBTCFr+6HA3TIf76KQ8LiIj6h+7l6KlPz48h
+eyaElzUUn5deTIG7jrPC2SaVhC0fKu/j1ZazN8tj/25+v9Q9mgZieYYEtiKjrEJU
+tli80ajN26E2NduLldkSVPt6N1Nf/w==
+=6nn7
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-service-1.0-rc5-sources.jar.sha1 b/lib/auto-service-1.0-rc5-sources.jar.sha1
new file mode 100644
index 0000000..3638b53
--- /dev/null
+++ b/lib/auto-service-1.0-rc5-sources.jar.sha1
@@ -0,0 +1 @@
+76bf7fbfc5a924f13115005a134546c4e2d1b245
\ No newline at end of file
diff --git a/lib/auto-service-1.0-rc5.jar b/lib/auto-service-1.0-rc5.jar
new file mode 100644
index 0000000..8c43e8f
--- /dev/null
+++ b/lib/auto-service-1.0-rc5.jar
Binary files differ
diff --git a/lib/auto-service-1.0-rc5.jar.2 b/lib/auto-service-1.0-rc5.jar.2
new file mode 100644
index 0000000..8c43e8f
--- /dev/null
+++ b/lib/auto-service-1.0-rc5.jar.2
Binary files differ
diff --git a/lib/auto-service-1.0-rc5.jar.asc b/lib/auto-service-1.0-rc5.jar.asc
new file mode 100644
index 0000000..e1d0163
--- /dev/null
+++ b/lib/auto-service-1.0-rc5.jar.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQEzBAABCgAdFiEEMoi4voUS1sDKGFJoxR5svH/0bwsFAlyZH48ACgkQxR5svH/0
+bwuZSAgAgmJ8gEx+MLtdt8IJY0ZGZtzntCOv2kTmieTQdwLKbmEc/WeQBXZeAWjb
+xKctEnesbNGwJY5jpPBiQH0nDd0MyIOc25gCvug2ezveo9eNe9ptOQFi+4gsG3mv
+0SGD9ZnRkzW8wNyMMWdBUJYdGPJp/FshsOVajBVsMDSev3OBxw8qfT4ZqhTO3LN6
+UnFydeqtbukqBiQRBrWEO7zXDmeHP+6GMWOD4Tkt60VRrSo7Sk6WeUkSJcB0rrmw
++/blQ3jBlN2/ummOc1dWUu7EyBoWhJhChQDQAuwev5oMMyQnhTLiFcHPvoKWFTlO
+GsBFENSqqxlW4j2ZYpoMX42inuaqbQ==
+=AMUZ
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-service-1.0-rc5.jar.sha1 b/lib/auto-service-1.0-rc5.jar.sha1
new file mode 100644
index 0000000..2edbbf4
--- /dev/null
+++ b/lib/auto-service-1.0-rc5.jar.sha1
@@ -0,0 +1 @@
+d25246bae325b4bcc63b55d6d782515fac32215a
\ No newline at end of file
diff --git a/lib/auto-service-annotations-1.0-rc5-sources.jar b/lib/auto-service-annotations-1.0-rc5-sources.jar
new file mode 100644
index 0000000..72fd4a9
--- /dev/null
+++ b/lib/auto-service-annotations-1.0-rc5-sources.jar
Binary files differ
diff --git a/lib/auto-service-annotations-1.0-rc5-sources.jar.asc b/lib/auto-service-annotations-1.0-rc5-sources.jar.asc
new file mode 100644
index 0000000..0058623
--- /dev/null
+++ b/lib/auto-service-annotations-1.0-rc5-sources.jar.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQEzBAABCgAdFiEEMoi4voUS1sDKGFJoxR5svH/0bwsFAlyZH4IACgkQxR5svH/0
+bwtnEwgAntYeAk/i4kaPhOdKCni4pZpkJ3WcEaDIiZROIvxn3GLFxDp1+WaFOuZS
+kYrqKLmDJdOwEK31FGP/XjsedmB6PP90pp01apaw2XS7pAzXQyNGMOypgCntJsN6
+ZkQYNLum8HQ6XXvEQh9j0eKU/9D+x7DRaxQZ69GkjFS1EwpytEYIEdFsjvHz3SYW
+G15++0H5+l7ZyNjXCs//x6tQ73nqhEu6UylwR4A9YvDuZhpMoFPNvB1+L6mlARgi
+cDRtm8hGLhsNeIYqGmbUEzwwKtKY/n7NwJX1zpXAg86/9E8R1xdbdzfGL6ctqQal
+w3WSYcNnmiZQfPinZuGHnrqDk/rN2w==
+=lgp6
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-service-annotations-1.0-rc5-sources.jar.sha1 b/lib/auto-service-annotations-1.0-rc5-sources.jar.sha1
new file mode 100644
index 0000000..fc01aa3
--- /dev/null
+++ b/lib/auto-service-annotations-1.0-rc5-sources.jar.sha1
@@ -0,0 +1 @@
+a2e50e3ba1f9a88f89142e7ea9a0f5380574f4e4
\ No newline at end of file
diff --git a/lib/auto-service-annotations-1.0-rc5.jar b/lib/auto-service-annotations-1.0-rc5.jar
new file mode 100644
index 0000000..fbc08ab
--- /dev/null
+++ b/lib/auto-service-annotations-1.0-rc5.jar
Binary files differ
diff --git a/lib/auto-service-annotations-1.0-rc5.jar.asc b/lib/auto-service-annotations-1.0-rc5.jar.asc
new file mode 100644
index 0000000..b7e43ce
--- /dev/null
+++ b/lib/auto-service-annotations-1.0-rc5.jar.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQEzBAABCgAdFiEEMoi4voUS1sDKGFJoxR5svH/0bwsFAlyZH4EACgkQxR5svH/0
+bwtNcwf+IvcoHSI7AvrM+z6Lhqes8wEdU9Q59ixakvEos/umjYwCXoGJyAG/w8N5
+4woRDJRg8KgWC0Kls7CGs5ZwplQTLRte/SmXWux8CV0/3v6OlIP4voWvXBueqKST
+gNN/Miy0Qx5uX1Qwh0inqlFF7jOj+IuTofQ4ZM3UjZPLVYhSfS/wTwLmNWNawQq7
+b/PkxaYgC1RuNv9onA8Vru2UCIlH8NFP9iPqPMwhRVVxoSaZzo5NxrRNRPZUfPzF
+GUH/SRDOfXHJ1joeZRK21s8adOGzZZJsSxxZ393xx1jl5qLdoowjTtENgc9gOSQG
+FzxOfWCoWncsJP10KfyYRV70JnJMrQ==
+=dWz/
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-service-annotations-1.0-rc5.jar.sha1 b/lib/auto-service-annotations-1.0-rc5.jar.sha1
new file mode 100644
index 0000000..4c48b47
--- /dev/null
+++ b/lib/auto-service-annotations-1.0-rc5.jar.sha1
@@ -0,0 +1 @@
+6ea999af2b6262a7179a09c51a3d54e7b40a3833
\ No newline at end of file
diff --git a/lib/auto-value-1.6.5-sources.jar b/lib/auto-value-1.6.5-sources.jar
new file mode 100644
index 0000000..7d08fa7
--- /dev/null
+++ b/lib/auto-value-1.6.5-sources.jar
Binary files differ
diff --git a/lib/auto-value-1.6.5-sources.jar.asc b/lib/auto-value-1.6.5-sources.jar.asc
new file mode 100644
index 0000000..36551c1
--- /dev/null
+++ b/lib/auto-value-1.6.5-sources.jar.asc
@@ -0,0 +1,12 @@
+-----BEGIN PGP SIGNATURE-----
+Comment: GPGTools - https://gpgtools.org
+
+iQEzBAABCgAdFiEEx75bzJ/sFVGM/aiCsPNxD6ZJAOcFAlyuMe0ACgkQsPNxD6ZJ
+AOc+4wgAkYRN5mdnQ54oLb/YGL9jnU7tdcFnq73ddH9wJH9cTGE8dAHIlNT4lEjy
+ligUXdi6YbuAC2Fjs7nMZiSOjEEDlKRozbwE82WOiIdV/MltMJgFCdBbVpszHFmu
+NWxDq5KocdgLODHwmIWJ0Xey6M1rjVZEshNf/U70604eEbGl9Hu0aTVFFVcASMM5
+CC38/X/G72Ja1Cz404WqGpmAsrHgDHdcPUVT3xxDReV1B+yPKxazzuKZA8/+KkWP
+RddLifE3W2NYnLVX49DS9iWCBiEbh5P6jtHvQSiyXIawexhQJGhjQMwHoi0+jHJd
+INp5YyrB64PHqaSgtuXhwgTfXmxkMA==
+=5Cw9
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-value-1.6.5-sources.jar.md5 b/lib/auto-value-1.6.5-sources.jar.md5
new file mode 100644
index 0000000..ca18ea4
--- /dev/null
+++ b/lib/auto-value-1.6.5-sources.jar.md5
@@ -0,0 +1 @@
+4a433a939d3f77766c785288d5c24c10
\ No newline at end of file
diff --git a/lib/auto-value-1.6.5-sources.jar.sha1 b/lib/auto-value-1.6.5-sources.jar.sha1
new file mode 100644
index 0000000..17f16a8
--- /dev/null
+++ b/lib/auto-value-1.6.5-sources.jar.sha1
@@ -0,0 +1 @@
+bfc251753f9bbdd8855825361d5f8c7fec8a1471
\ No newline at end of file
diff --git a/lib/auto-value-1.6.5.jar b/lib/auto-value-1.6.5.jar
new file mode 100644
index 0000000..be17cd1
--- /dev/null
+++ b/lib/auto-value-1.6.5.jar
Binary files differ
diff --git a/lib/auto-value-1.6.5.jar.asc b/lib/auto-value-1.6.5.jar.asc
new file mode 100644
index 0000000..f0cdc39
--- /dev/null
+++ b/lib/auto-value-1.6.5.jar.asc
@@ -0,0 +1,12 @@
+-----BEGIN PGP SIGNATURE-----
+Comment: GPGTools - https://gpgtools.org
+
+iQEzBAABCgAdFiEEx75bzJ/sFVGM/aiCsPNxD6ZJAOcFAlyuMewACgkQsPNxD6ZJ
+AOd5ygf8DOjgClYv8hCaiHiu2mDwFV4s24SbyvSZrAeBrHOoY6/E7leSqilJ+mF9
+3kjDv/VtHTv9Ds2cX2daH5hnvuYIwiCzdze3ZWdKJ+PtWsKpqEAevfEMRmSPPUV4
+ZZ5Zd6VZspD+rUViKfwF8ZW1zjKjdcIPbhuiYR4TF718kPL8WCV2bGruYidjYBoe
+hzLUUqY0rv+IwV+OycbyZwtmx1DVCTkYlDdepSyswr2RGb/UFIf44E0koboI+Xue
+6nF+w6AaOaufjdqe2ObIWNa2tsPTj4KABh3tHmOMs35x367/PzwQmh0I25gFAQrX
+KYo6dYVZeLWmNpdIJxeMIZRok0MAKA==
+=KnCZ
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-value-1.6.5.jar.md5 b/lib/auto-value-1.6.5.jar.md5
new file mode 100644
index 0000000..11a5e9d
--- /dev/null
+++ b/lib/auto-value-1.6.5.jar.md5
@@ -0,0 +1 @@
+d3730b8e2f9c6f62153181618a13f3a2
\ No newline at end of file
diff --git a/lib/auto-value-1.6.5.jar.sha1 b/lib/auto-value-1.6.5.jar.sha1
new file mode 100644
index 0000000..edf62d8
--- /dev/null
+++ b/lib/auto-value-1.6.5.jar.sha1
@@ -0,0 +1 @@
+816872c85048f36a67a276ef7a49cc2e4595711c
\ No newline at end of file
diff --git a/lib/auto-value-annotations-1.6.5-sources.jar b/lib/auto-value-annotations-1.6.5-sources.jar
new file mode 100644
index 0000000..b1a8b08
--- /dev/null
+++ b/lib/auto-value-annotations-1.6.5-sources.jar
Binary files differ
diff --git a/lib/auto-value-annotations-1.6.5-sources.jar.asc b/lib/auto-value-annotations-1.6.5-sources.jar.asc
new file mode 100644
index 0000000..81a4515
--- /dev/null
+++ b/lib/auto-value-annotations-1.6.5-sources.jar.asc
@@ -0,0 +1,12 @@
+-----BEGIN PGP SIGNATURE-----
+Comment: GPGTools - https://gpgtools.org
+
+iQEzBAABCgAdFiEEx75bzJ/sFVGM/aiCsPNxD6ZJAOcFAlyuMdUACgkQsPNxD6ZJ
+AOfNYwgAqoJ9hi7JyS1iwf646TPLPbtRaaRzl/w9hrZntVlMiHL5Ov+LHq6WW1tS
+IWqz9K6dbEDW4O3WbNXUsiWTGzUvkNc/bjQOY4MTCthTj/LO9PqHVSDGgWo/Y37c
+jazTbUNxctFSziu9mVZdw1VdCI65LVCbhSaOeIc7Msmr/ALtZ1pBGdJ8dzxuC3Dl
+BeT2khADj7C13Kicu7QtZfZypbTqB6JnjAwMO56c4pRviIqRpJsOKHbJM1KBxms+
+6JGv63XTBP22f83XX38wAAPocT5NZBn+lZcDcbC6Mh0NIhaISdx73ujWtTwHX5fC
+x0NYKIIBdyEb5GkPeD1D/IjB4w8o5w==
+=Hbou
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-value-annotations-1.6.5-sources.jar.sha1 b/lib/auto-value-annotations-1.6.5-sources.jar.sha1
new file mode 100644
index 0000000..897752c
--- /dev/null
+++ b/lib/auto-value-annotations-1.6.5-sources.jar.sha1
@@ -0,0 +1 @@
+3499fd80025705c502699d1154c4b9631cb7a95e
\ No newline at end of file
diff --git a/lib/auto-value-annotations-1.6.5.jar b/lib/auto-value-annotations-1.6.5.jar
new file mode 100644
index 0000000..f68a013
--- /dev/null
+++ b/lib/auto-value-annotations-1.6.5.jar
Binary files differ
diff --git a/lib/auto-value-annotations-1.6.5.jar.asc b/lib/auto-value-annotations-1.6.5.jar.asc
new file mode 100644
index 0000000..1356995
--- /dev/null
+++ b/lib/auto-value-annotations-1.6.5.jar.asc
@@ -0,0 +1,12 @@
+-----BEGIN PGP SIGNATURE-----
+Comment: GPGTools - https://gpgtools.org
+
+iQEzBAABCgAdFiEEx75bzJ/sFVGM/aiCsPNxD6ZJAOcFAlyuMdQACgkQsPNxD6ZJ
+AOeeQQf/cRfXuh8RCDR5WWAHPXpK9JzA5OEEvtXl13uSqpcU+f2/APNOmG9tJz2B
+53bp6d18knaoSAWtC1Hl2kM8eZPYNlpB+MC8VJ+/JAZMf2arLMKGuvii9eYmGrvJ
+kXfRHqWgZQMQIKrd2ne/PMgnmixLPSF6HtyFh2JN/LbjR7ipQR3VAJe89QGmIFFf
+njSptIgKuDauQrjq//yXpWRyhUNheAH42y3aIaUvydcSOLsGIqQfTJLOe3sSMxlU
+d0fJWP47uW04y2j6kXv4SYKXGnBrv2M+c/6YRriPv69tSBc+2DY6SpMZsYdV9Car
+pDM+7m5lxCN8mI/KRRNcXaSR9GLJ2A==
+=ey6m
+-----END PGP SIGNATURE-----
diff --git a/lib/auto-value-annotations-1.6.5.jar.sha1 b/lib/auto-value-annotations-1.6.5.jar.sha1
new file mode 100644
index 0000000..858c96e
--- /dev/null
+++ b/lib/auto-value-annotations-1.6.5.jar.sha1
@@ -0,0 +1 @@
+c3dad10377f0e2242c9a4b88e9704eaf79103679
\ No newline at end of file
diff --git a/lib/google-java-format-1.7-all-deps.jar b/lib/google-java-format-1.7-all-deps.jar
new file mode 100644
index 0000000..e2d40de
--- /dev/null
+++ b/lib/google-java-format-1.7-all-deps.jar
Binary files differ
diff --git a/lib/google-java-format-1.7-all-deps.jar.asc b/lib/google-java-format-1.7-all-deps.jar.asc
new file mode 100644
index 0000000..73ae0e2
--- /dev/null
+++ b/lib/google-java-format-1.7-all-deps.jar.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCgAdFiEE53QXrBlBYKP6vQSWmiWcfuY2xe0FAlw2hwoACgkQmiWcfuY2
+xe22Ww//YIHLWoQApuSmLdq4A1fcNOYbSpm6J9I2J1i2VoK84XSXP1XJTWsoYNbx
+Y3Xx6I8p28AxH7LOWcdtds9enbF06blzz+1CxuSxvN32M7DDursiihsUYU9wmZVU
+7V1ZYBtaYTYYw8C5U+UchcIVJrHdG9KrAiBcn1s76gigNAtCYV/1PyryupS1wcDZ
+bdj48mI6adcnIpV+9D9W4rLuXw2Hg+ewktXTj3HYqkg+5Nvc/zP9ueBvqEsyh5Iz
+3+69egblhuN7gRaEWarlYfJ2n/kF9T/UMAkQrWD8+9cOgUcgTHkNADNOLpmDH6t7
+OYvZhgwQT920ZJgGP8e3DGyvMxBMxlr19ciTT19HL5qglyhFm/SeHvFdpaHkIjb9
+CmASWrlkALdEv2gPx+m79EJifyK5tYtViZgLhfjwYkS/opw5TfJX0+Ngh9ehgune
+c6TgEIzRQAEQ/9QoVk2crGT/lhXnJI3Zid7cSP2/fRdui91KaKGi9qFvXyJf7XKI
+vH0De+e3yZN/GXLYyQSUzmdQU8HMF9iuc81CT1ANgU+e9HU5k9FWSPHrA3gN7CKt
+/a3qIsIBpcdKe9zcPxSoEqRzVNept4IhszgiIVxZPNrPShzCRbS1sGURoOTbSFSP
++aKWNFoswX/RANGQVajOyfF5mJ3lB4N0u2eI0HIR3NzNx0HN+2Q=
+=+/96
+-----END PGP SIGNATURE-----
diff --git a/lib/google-java-format-1.7-all-deps.jar.sha1 b/lib/google-java-format-1.7-all-deps.jar.sha1
new file mode 100644
index 0000000..b247a7c
--- /dev/null
+++ b/lib/google-java-format-1.7-all-deps.jar.sha1
@@ -0,0 +1 @@
+b6d34a51e579b08db7c624505bdf9af4397f1702
\ No newline at end of file
diff --git a/lib/google-java-format-1.7-sources.jar b/lib/google-java-format-1.7-sources.jar
new file mode 100644
index 0000000..70fca1b
--- /dev/null
+++ b/lib/google-java-format-1.7-sources.jar
Binary files differ
diff --git a/lib/google-java-format-1.7-sources.jar.asc b/lib/google-java-format-1.7-sources.jar.asc
new file mode 100644
index 0000000..713333c
--- /dev/null
+++ b/lib/google-java-format-1.7-sources.jar.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCgAdFiEE53QXrBlBYKP6vQSWmiWcfuY2xe0FAlw2hwsACgkQmiWcfuY2
+xe1j6BAAsDY9DTTcjRtrT6AiZchELcJleOdqK3TRdbl193Mtw5eR+BdKqtcLZSmZ
+1EqYNcldOu9wgbZFpFL99xWNAPOt8tTU9hTsZvrRN0e5CwKXrlJl0MeJi/6yYquG
+FerYGZuDMMEza1q9D2TG5erLOjDEWVLjkSs3jw8mSyMvN0OJFhhMrU4sqhlXMGNV
+lDxeYXLXr+QtIi0tXAUQ5XSwtR7eukSevA7n3zQJKfYMlFbG82lMGJccfazJpdPf
+cJLAGY9/q3RVZx5vk00kz3sDmL+rMU01Lh+CHwT9D8ASRfzjkssHuKaMYBysuh7s
+YZ6X3Txvtkzf3fJjYl5jID3jEui82iR5jv5ncZFZFCsZsTRM0sLAP5/KeX128dHM
+fJzVH4GIUvOqt9aIDKQ+3aNsARsIH2Z2AHymUxVZoP33V9HoC8x0ghxM0xohvkh5
+L+VgUOEjekOneqWD1QEF+HD7S3hpy36+g37PYGcQRRaCIDn00Se+UbJ9RZrUVdvu
+JgmVXcpagrLmcSnkG265zdDW9Vu7vjAKhxjLXmbE0aowzdo/HZ+u3R2hpZbOyv33
+NmakhTwaUtQtDm34GVPqoypnu85va27vxVDQgTsk3im9M1l/UP65NidPuuSk7iOI
+UECD7wc6Ddh80jmDlXdlxSNG+zzGp95gS5UVoDXgwNEok7UgrY4=
+=zj6k
+-----END PGP SIGNATURE-----
diff --git a/lib/google-java-format-1.7-sources.jar.sha1 b/lib/google-java-format-1.7-sources.jar.sha1
new file mode 100644
index 0000000..31d6337
--- /dev/null
+++ b/lib/google-java-format-1.7-sources.jar.sha1
@@ -0,0 +1 @@
+dbb14f20004dfaf01a5ce9f5e75c5993f18cc0a5
\ No newline at end of file
diff --git a/lib/google-java-format-1.7.jar b/lib/google-java-format-1.7.jar
new file mode 100644
index 0000000..953541c
--- /dev/null
+++ b/lib/google-java-format-1.7.jar
Binary files differ
diff --git a/lib/google-java-format-1.7.jar.asc b/lib/google-java-format-1.7.jar.asc
new file mode 100644
index 0000000..3642d69
--- /dev/null
+++ b/lib/google-java-format-1.7.jar.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCgAdFiEE53QXrBlBYKP6vQSWmiWcfuY2xe0FAlw2hwkACgkQmiWcfuY2
+xe1uIhAAt9sWjStHkfHmWNFd5exYsjBmN0eObgOU5A386j5Q5P4hZjFDYsDvKlVo
+DWZKI2A9ZvpisuI083DwGJCXvbtD1WICh5Xx1B2tK2oCgl5bYiU88LCw5jS9F2IZ
+thPFhFDMIw4tQZp2J4o+itO7gtoUMfN5J9Y7ZcOWG60F3ouGc6vd8PnMk/CfxNZ0
+Zy21dkBzJVJsNghUWsHfP6WS2ySVBNQaarY+/4IuIrBVqRNZBhD+qEtZRG3mwc4X
+ydd4hCvoAQ7lysrdZEMDRx0qLQoqEWyfNFX7b8X/Oi6Ape765mD3Ss1WFgsjLqo+
+kt4Ge09f4QOCtMP95M8AnnHGjpVuibC0tb2E7qXfcrMWf+EX8ksFJKwaXZQfG4lv
+7kxZDTeeDdU6SUakiwfkEKN6s4v0MrGi8TM+776gLihcD/tx09555h+EwXrbp3IE
+1SWJCiYCuaqe1UXNEsZGYKv72GkPSEjY813Tn3endvGXX+QrLCU6DrLRyy1IWFKJ
+Yu6THeT0Z+M6h+oTO0ug2gJ6Ur7apQC4JBIi12XE+QhwuTuV0byiUArmO+3elLH4
+Nd9O0yFhKClaJ+ye+X+XLYkIjh+IJGFmbUahvCFuMMKuwbFRHwn5pw0DOJvE7qjg
+dBZhwjzKN8RHzik5nFwzhBBIzj3UglacGkUPFv7JW1TqcY2X6kE=
+=VIxo
+-----END PGP SIGNATURE-----
diff --git a/lib/google-java-format-1.7.jar.sha1 b/lib/google-java-format-1.7.jar.sha1
new file mode 100644
index 0000000..d0a76c2
--- /dev/null
+++ b/lib/google-java-format-1.7.jar.sha1
@@ -0,0 +1 @@
+97cb6afc835d65682edc248e19170a8e4ecfe4c4
\ No newline at end of file
diff --git a/lib/javax.inject-1-sources.jar b/lib/javax.inject-1-sources.jar
new file mode 100644
index 0000000..0c98053
--- /dev/null
+++ b/lib/javax.inject-1-sources.jar
Binary files differ
diff --git a/lib/javax.inject-1-sources.jar.sha1 b/lib/javax.inject-1-sources.jar.sha1
new file mode 100644
index 0000000..b69cdf0
--- /dev/null
+++ b/lib/javax.inject-1-sources.jar.sha1
@@ -0,0 +1 @@
+a00123f261762a7c5e0ec916a2c7c8298d29c400  /home/maven/repository-staging/to-ibiblio/maven2/javax/inject/javax.inject/1/javax.inject-1-sources.jar
diff --git a/lib/javax.inject-1.jar b/lib/javax.inject-1.jar
new file mode 100644
index 0000000..b2a9d0b
--- /dev/null
+++ b/lib/javax.inject-1.jar
Binary files differ
diff --git a/lib/javax.inject-1.jar.sha1 b/lib/javax.inject-1.jar.sha1
new file mode 100644
index 0000000..41e75ef
--- /dev/null
+++ b/lib/javax.inject-1.jar.sha1
@@ -0,0 +1 @@
+6975da39a7040257bd51d21a231b76c915872d38  /home/maven/repository-staging/to-ibiblio/maven2/javax/inject/javax.inject/1/javax.inject-1.jar
diff --git a/lint-baseline.xml b/lint-baseline.xml
deleted file mode 100644
index cf790c2..0000000
--- a/lint-baseline.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
-
-    <issue
-        id="NewApi"
-        message="Multi-catch with these reflection exceptions requires API level 19 (current min is 14) because they get compiled to the common but new super type `ReflectiveOperationException`. As a workaround either create individual catch statements, or catch `Exception`."
-        errorLine1="    } catch (ClassNotFoundException"
-        errorLine2="             ^">
-        <location
-            file="external/dagger2/java/dagger/hilt/android/internal/testing/TestApplicationComponentManager.java"
-            line="85"
-            column="14"/>
-    </issue>
-
-</issues>
diff --git a/test_defs.bzl b/test_defs.bzl
index d16ad36..15ab299 100644
--- a/test_defs.bzl
+++ b/test_defs.bzl
@@ -12,18 +12,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""This file defines constants useful across the Dagger tests."""
-
-load("@rules_java//java:defs.bzl", "java_library", "java_test")
 
 # Defines a set of build variants and the list of extra javacopts to build with.
 # The key will be appended to the generated test names to ensure uniqueness.
 BUILD_VARIANTS = {
     "FastInit": ["-Adagger.fastInit=enabled"],
+    "AheadOfTimeSubcomponents": ["-Adagger.experimentalAheadOfTimeSubcomponents=enabled"],
+    "FastInitAndAheadOfTimeSubcomponents": [
+        "-Adagger.fastInit=enabled",
+        "-Adagger.experimentalAheadOfTimeSubcomponents=enabled",
+    ],
+    "AheadOfTimeSubcomponents_ForceUseSerializedComponentImplementations": [
+        "-Adagger.experimentalAheadOfTimeSubcomponents=enabled",
+        "-Adagger.forceUseSerializedComponentImplementations=enabled",
+    ],
 }
 
 # TODO(ronshapiro): convert this to use bazel_common
-# TODO(bcorso): split into two functions for functional vs non-functional tests?
+# TODO(user): split into two functions for functional vs non-functional tests?
 def GenJavaTests(
         name,
         srcs,
@@ -35,8 +41,8 @@
         test_javacopts = None,
         functional = True):
     _GenTests(
-        java_library,
-        java_test,
+        native.java_library,
+        native.java_test,
         name,
         srcs,
         deps,
@@ -184,5 +190,6 @@
             **test_kwargs
         )
 
+
 def _hjar_test(name, tags):
     pass
diff --git a/tools/BUILD b/tools/BUILD
index 83d5048..7b3cc6c 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -15,30 +15,8 @@
 # Description:
 #   Tools for Dagger
 
-load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
-load(":maven_info.bzl", "maven_info_tests")
-
 package(default_visibility = ["//:src"])
 
-maven_info_tests()
-
 exports_files([
     "pom-template.xml",
 ])
-
-bzl_library(
-    name = "maven_bzl",
-    srcs = ["maven.bzl"],
-    deps = [":maven_info_bzl"],
-)
-
-bzl_library(
-    name = "maven_info_bzl",
-    srcs = ["maven_info.bzl"],
-    deps = ["@bazel_skylib//lib:unittest"],
-)
-
-bzl_library(
-    name = "dejetify_bzl",
-    srcs = ["dejetify.bzl"],
-)
diff --git a/tools/dejetify.bzl b/tools/dejetify.bzl
deleted file mode 100644
index 4f0b0ce..0000000
--- a/tools/dejetify.bzl
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2020 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.
-
-"""Macro for producing dejetified artifacts.
-"""
-
-# See: https://developer.android.com/studio/command-line/jetifier
-JETIFIER_STANDALONE = "https://dl.google.com/dl/android/studio/jetifier-zips/1.0.0-beta08/jetifier-standalone.zip"
-
-def dejetified_library(name, input, output):
-    _dejetify_library(name, input, output)
-
-def _dejetify_library(name, input, output):
-    """Generates a dejetified library artifact.
-
-    A dejetified artifact is one that has been transformed to migrate its
-    AndroidX APIs to the support equivalents.
-
-    Args:
-      name: The name of the target.
-      input: The android_library input, e.g. ":myLibrary.aar".
-      output: The name of the output artifact, e.g. "dejetified-myLibrary.aar".
-    """
-    native.genrule(
-        name = name,
-        srcs = [input],
-        outs = [output],
-        cmd = """
-            TEMP="$$(mktemp -d)"
-            curl {tool_link} --output $$TEMP/jetifier-standalone.zip
-            unzip $$TEMP/jetifier-standalone.zip -d $$TEMP/
-            $$TEMP/jetifier-standalone/bin/jetifier-standalone -r \
-              -l info -i $< -o $@
-        """.format(tool_link = JETIFIER_STANDALONE),
-        local = 1,
-    )
diff --git a/tools/maven.bzl b/tools/maven.bzl
index 2c648a2..2ac0359 100644
--- a/tools/maven.bzl
+++ b/tools/maven.bzl
@@ -16,9 +16,6 @@
 """
 
 load("@google_bazel_common//tools/maven:pom_file.bzl", default_pom_file = "pom_file")
-load(":maven_info.bzl", "MavenInfo", "collect_maven_info")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-load("@google_bazel_common//tools/jarjar:jarjar.bzl", "jarjar_library")
 
 def pom_file(name, targets, artifact_name, artifact_id, packaging = None, **kwargs):
     default_pom_file(
@@ -38,366 +35,4 @@
         **kwargs
     )
 
-def gen_maven_artifact(
-        name,
-        artifact_name,
-        artifact_coordinates,
-        artifact_target,
-        artifact_target_libs = None,
-        artifact_target_maven_deps = None,
-        artifact_target_maven_deps_banned = None,
-        testonly = 0,
-        pom_name = "pom",
-        packaging = None,
-        javadoc_srcs = None,
-        javadoc_root_packages = None,
-        javadoc_exclude_packages = None,
-        javadoc_android_api_level = None,
-        shaded_deps = None,
-        shaded_rules = None,
-        manifest = None,
-        lint_deps = None,
-        proguard_specs = None):
-    _gen_maven_artifact(
-        name,
-        artifact_name,
-        artifact_coordinates,
-        artifact_target,
-        artifact_target_libs,
-        artifact_target_maven_deps,
-        artifact_target_maven_deps_banned,
-        testonly,
-        pom_name,
-        packaging,
-        javadoc_srcs,
-        javadoc_root_packages,
-        javadoc_exclude_packages,
-        javadoc_android_api_level,
-        shaded_deps,
-        shaded_rules,
-        manifest,
-        lint_deps,
-        proguard_specs
-    )
-
-def _gen_maven_artifact(
-        name,
-        artifact_name,
-        artifact_coordinates,
-        artifact_target,
-        artifact_target_libs,
-        artifact_target_maven_deps,
-        artifact_target_maven_deps_banned,
-        testonly,
-        pom_name,
-        packaging,
-        javadoc_srcs,
-        javadoc_root_packages,
-        javadoc_exclude_packages,
-        javadoc_android_api_level,
-        shaded_deps,
-        shaded_rules,
-        manifest,
-        lint_deps,
-        proguard_specs):
-    """Generates the files required for a maven artifact.
-
-    This macro generates the following targets:
-        * ":pom": The pom file for the given target and deps
-        * ":<NAME>": The artifact file for the given target and deps
-        * ":<NAME>-src": The sources jar file for the given target and deps
-        * ":<NAME>-javadoc": The javadocs jar file for the given target and deps
-
-    This macro also validates a few things. First, it validates that the
-    given "target" is a maven artifact (i.e. the "tags" attribute contains
-    "maven_coordinates=..."). Second, it calculates the list of transitive
-    dependencies of the target that are not owned by another maven artifact,
-    and validates that the given "deps" matches exactly.
-
-    Args:
-      name: The name associated with the various output targets.
-      artifact_target: The target containing the maven_coordinates.
-      artifact_name: The name of the maven artifact.
-      artifact_coordinates: The coordinates of the maven artifact in the
-                            form: "<group_id>:<artifact_id>:<version>"
-      artifact_target_libs: The set of transitive libraries of the target.
-      artifact_target_maven_deps: The required maven deps of the target.
-      artifact_target_maven_deps_banned: The banned maven deps of the target.
-      testonly: True if the jar should be testonly.
-      packaging: The packaging of the maven artifact. E.g. "aar"
-      pom_name: The name of the pom file (or "pom" if absent).
-      javadoc_srcs: The srcs for the javadocs.
-      javadoc_root_packages: The root packages for the javadocs.
-      javadoc_exclude_packages: The packages to exclude from the javadocs.
-      javadoc_android_api_level: The android api level for the javadocs.
-      shaded_deps: The shaded deps for the jarjar.
-      shaded_rules: The shaded rules for the jarjar.
-      manifest: The AndroidManifest.xml to bundle in when packaing an 'aar'.
-      lint_deps: The lint targets to be bundled in when packaging an 'aar'.
-      proguard_specs: The proguard spec files to be bundled in when packaging an 'aar'
-    """
-
-    _validate_maven_deps(
-        name = name + "-validation",
-        testonly = 1,
-        target = artifact_target,
-        expected_artifact = artifact_coordinates,
-        expected_libs = artifact_target_libs,
-        expected_maven_deps = artifact_target_maven_deps,
-        banned_maven_deps = artifact_target_maven_deps_banned,
-    )
-
-    shaded_deps = shaded_deps or []
-    shaded_rules = shaded_rules or []
-    artifact_targets = [artifact_target] + (artifact_target_libs or [])
-    lint_deps = lint_deps or []
-
-    # META-INF resources files that can be combined by appending lines.
-    merge_meta_inf_files = [
-        "gradle/incremental.annotation.processors",
-    ]
-
-    artifact_id = artifact_coordinates.split(":")[1]
-    pom_file(
-        name = pom_name,
-        testonly = testonly,
-        artifact_id = artifact_id,
-        artifact_name = artifact_name,
-        packaging = packaging,
-        targets = artifact_targets,
-    )
-
-    if (packaging == "aar"):
-        jarjar_library(
-            name = name + "-classes",
-            testonly = testonly,
-            jars = artifact_targets + shaded_deps,
-            rules = shaded_rules,
-            merge_meta_inf_files = merge_meta_inf_files,
-        )
-        if lint_deps:
-            # jarjar all lint artifacts since an aar only contains a single lint.jar.
-            jarjar_library(
-                name = name + "-lint",
-                jars = lint_deps,
-            )
-            lint_jar_name = name + "-lint.jar"
-        else:
-            lint_jar_name = None
-
-        if proguard_specs:
-            # Concatenate all proguard rules since an aar only contains a single proguard.txt
-            native.genrule(
-                name = name + "-proguard",
-                srcs = proguard_specs,
-                outs = [name + "-proguard.txt"],
-                cmd = "cat $(SRCS) > $@",
-            )
-            proguard_file = name + "-proguard.txt"
-        else:
-            proguard_file = None
-
-        _package_android_library(
-            name = name + "-android-lib",
-            manifest = manifest,
-            classesJar = name + "-classes.jar",
-            lintJar = lint_jar_name,
-            proguardSpec = proguard_file,
-        )
-
-        # Copy intermediate outputs to final one.
-        native.genrule(
-            name = name,
-            srcs = [name + "-android-lib"],
-            outs = [name + ".aar"],
-            cmd = "cp $< $@",
-        )
-    else:
-        jarjar_library(
-            name = name,
-            testonly = testonly,
-            jars = artifact_targets + shaded_deps,
-            rules = shaded_rules,
-            merge_meta_inf_files = merge_meta_inf_files,
-        )
-
-    jarjar_library(
-        name = name + "-src",
-        testonly = testonly,
-        jars = [_src_jar(dep) for dep in artifact_targets],
-        merge_meta_inf_files = merge_meta_inf_files,
-    )
-
-    if javadoc_srcs != None:
-        javadoc_library(
-            name = name + "-javadoc",
-            srcs = javadoc_srcs,
-            testonly = testonly,
-            root_packages = javadoc_root_packages,
-            exclude_packages = javadoc_exclude_packages,
-            android_api_level = javadoc_android_api_level,
-            deps = artifact_targets,
-        )
-    else:
-        # Build an empty javadoc because Sonatype requires javadocs
-        # even if the jar is empty.
-        # https://central.sonatype.org/pages/requirements.html#supply-javadoc-and-sources
-        native.java_binary(
-            name = name + "-javadoc",
-        )
-
-def _src_jar(target):
-    if target.startswith(":"):
-        target = Label("//" + native.package_name() + target)
-    else:
-        target = Label(target)
-    return "//%s:lib%s-src.jar" % (target.package, target.name)
-
-def _validate_maven_deps_impl(ctx):
-    """Validates the given Maven target and deps
-
-    Validates that the given "target" is a maven artifact (i.e. the "tags"
-    attribute contains "maven_coordinates=..."). Second, it calculates the
-    list of transitive dependencies of the target that are not owned by
-    another maven artifact, and validates that the given "deps" matches
-    exactly.
-    """
-    target = ctx.attr.target
-    artifact = target[MavenInfo].artifact
-    if not artifact:
-        fail("\t[Error]: %s is not a maven artifact" % target.label)
-
-    if artifact != ctx.attr.expected_artifact:
-        fail(
-            "\t[Error]: %s expected artifact, %s, but was: %s" % (
-                target.label,
-                ctx.attr.expected_artifact,
-                artifact,
-            ),
-        )
-
-    all_transitive_deps = target[MavenInfo].all_transitive_deps.to_list()
-    maven_nearest_artifacts = target[MavenInfo].maven_nearest_artifacts.to_list()
-    maven_transitive_deps = target[MavenInfo].maven_transitive_deps.to_list()
-
-    expected_libs = [dep.label for dep in getattr(ctx.attr, "expected_libs", [])]
-    actual_libs = [dep for dep in all_transitive_deps if dep not in maven_transitive_deps]
-    _validate_list("artifact_target_libs", actual_libs, expected_libs)
-
-    expected_maven_deps = [dep for dep in getattr(ctx.attr, "expected_maven_deps", [])]
-    actual_maven_deps = [_strip_artifact_version(artifact) for artifact in maven_nearest_artifacts]
-    _validate_list(
-        "artifact_target_maven_deps",
-        actual_maven_deps,
-        expected_maven_deps,
-        ctx.attr.banned_maven_deps,
-    )
-
-def _validate_list(name, actual_list, expected_list, banned_list = []):
-    missing = sorted(['"{}",'.format(x) for x in actual_list if x not in expected_list])
-    if missing:
-        fail("\t[Error]: Found missing {}: \n\t\t".format(name) + "\n\t\t".join(missing))
-
-    extra = sorted(['"{}",'.format(x) for x in expected_list if x not in actual_list])
-    if extra:
-        fail("\t[Error]: Found extra {}: \n\t\t".format(name) + "\n\t\t".join(extra))
-
-    banned = sorted(['"{}",'.format(x) for x in actual_list if x in banned_list])
-    if banned:
-        fail("\t[Error]: Found banned {}: \n\t\t".format(name) + "\n\t\t".join(banned))
-
-def _strip_artifact_version(artifact):
-    return artifact.rsplit(":", 1)[0]
-
-_validate_maven_deps = rule(
-    implementation = _validate_maven_deps_impl,
-    attrs = {
-        "target": attr.label(
-            doc = "The target to generate a maven artifact for.",
-            aspects = [collect_maven_info],
-            mandatory = True,
-        ),
-        "expected_artifact": attr.string(
-            doc = "The artifact name of the target.",
-            mandatory = True,
-        ),
-        "expected_libs": attr.label_list(
-            doc = "The set of transitive libraries of the target, if any.",
-        ),
-        "expected_maven_deps": attr.string_list(
-            doc = "The required maven dependencies of the target, if any.",
-        ),
-        "banned_maven_deps": attr.string_list(
-            doc = "The required maven dependencies of the target, if any.",
-        ),
-    },
-)
-
-def _package_android_library_impl(ctx):
-    """A very, very simple Android Library (aar) packaging rule.
-
-    This rule only support packaging simple android libraries. No resources
-    support, assets, extra libs, nor jni. This rule is needed because
-    there is no 'JarJar equivalent' for AARs and some of our artifacts are
-    composed of sources spread across multiple android_library targets.
-
-    See: https://developer.android.com/studio/projects/android-library.html#aar-contents
-    """
-    inputs = [ctx.file.manifest, ctx.file.classesJar]
-    if ctx.file.lintJar:
-        inputs.append(ctx.file.lintJar)
-    if ctx.file.proguardSpec:
-        inputs.append(ctx.file.proguardSpec)
-
-    ctx.actions.run_shell(
-        inputs = inputs,
-        outputs = [ctx.outputs.aar],
-        command = """
-            TMPDIR="$(mktemp -d)"
-            cp {manifest} $TMPDIR/AndroidManifest.xml
-            cp {classesJar} $TMPDIR/classes.jar
-            if [[ -a {lintJar} ]]; then
-                cp {lintJar} $TMPDIR/lint.jar
-            fi
-            if [[ -a {proguardSpec} ]]; then
-                cp {proguardSpec} $TMPDIR/proguard.txt
-            fi
-            touch $TMPDIR/R.txt
-            zip -j {outputFile} $TMPDIR/*
-            """.format(
-            manifest = ctx.file.manifest.path,
-            classesJar = ctx.file.classesJar.path,
-            lintJar = ctx.file.lintJar.path if ctx.file.lintJar else "none",
-            proguardSpec = ctx.file.proguardSpec.path if ctx.file.proguardSpec else "none",
-            outputFile = ctx.outputs.aar.path,
-        ),
-    )
-
-_package_android_library = rule(
-    implementation = _package_android_library_impl,
-    attrs = {
-        "manifest": attr.label(
-            doc = "The AndroidManifest.xml file.",
-            allow_single_file = True,
-            mandatory = True,
-        ),
-        "classesJar": attr.label(
-            doc = "The classes.jar file.",
-            allow_single_file = True,
-            mandatory = True,
-        ),
-        "lintJar": attr.label(
-            doc = "The lint.jar file.",
-            allow_single_file = True,
-            mandatory = False,
-        ),
-        "proguardSpec": attr.label(
-            doc = "The proguard.txt file.",
-            allow_single_file = True,
-            mandatory = False,
-        ),
-    },
-    outputs = {
-        "aar": "%{name}.aar",
-    },
-)
+POM_VERSION = "2.23.1"
diff --git a/tools/maven_info.bzl b/tools/maven_info.bzl
deleted file mode 100644
index 5ebed3f..0000000
--- a/tools/maven_info.bzl
+++ /dev/null
@@ -1,243 +0,0 @@
-# Copyright (C) 2019 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.
-"""Skylark rules to collect Maven artifacts information.
-"""
-
-load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
-
-# TODO(b/142057516): Unfork this file once we've settled on a more general API.
-MavenInfo = provider(
-    fields = {
-        "artifact": """
-        The Maven coordinate for the artifact that is exported by this target, if one exists.
-        """,
-        "has_srcs": """
-        True if this library contains srcs..
-        """,
-        "all_transitive_deps": """
-        All transitive deps of the target with srcs.
-        """,
-        "maven_nearest_artifacts": """
-        The nearest maven deps of the target.
-        """,
-        "maven_transitive_deps": """
-        All transitive deps that are included in some maven dependency.
-        """,
-    },
-)
-
-_EMPTY_MAVEN_INFO = MavenInfo(
-    artifact = None,
-    has_srcs = False,
-    maven_nearest_artifacts = depset(),
-    maven_transitive_deps = depset(),
-    all_transitive_deps = depset(),
-)
-
-_MAVEN_COORDINATES_PREFIX = "maven_coordinates="
-
-def _collect_maven_info_impl(target, ctx):
-    tags = getattr(ctx.rule.attr, "tags", [])
-    srcs = getattr(ctx.rule.attr, "srcs", [])
-    deps = getattr(ctx.rule.attr, "deps", [])
-    exports = getattr(ctx.rule.attr, "exports", [])
-
-    artifact = None
-    for tag in tags:
-        if tag in ("maven:compile_only", "maven:shaded"):
-            return [_EMPTY_MAVEN_INFO]
-        if tag.startswith(_MAVEN_COORDINATES_PREFIX):
-            artifact = tag[len(_MAVEN_COORDINATES_PREFIX):]
-
-    all_deps = [dep.label for dep in (deps + exports) if dep[MavenInfo].has_srcs]
-    all_transitive_deps = [dep[MavenInfo].all_transitive_deps for dep in (deps + exports)]
-
-    maven_artifacts = []
-    maven_nearest_artifacts = []
-    maven_deps = []
-    maven_transitive_deps = []
-    for dep in (deps + exports):
-        # If the dep is itself a maven artifact, add it and all of its transitive deps.
-        # Otherwise, just propagate its transitive maven deps.
-        if dep[MavenInfo].artifact or dep[MavenInfo] == _EMPTY_MAVEN_INFO:
-            if (dep[MavenInfo].artifact):
-                maven_artifacts.append(dep[MavenInfo].artifact)
-            maven_deps.append(dep.label)
-            maven_transitive_deps.append(dep[MavenInfo].all_transitive_deps)
-        else:
-            maven_nearest_artifacts.append(dep[MavenInfo].maven_nearest_artifacts)
-            maven_transitive_deps.append(dep[MavenInfo].maven_transitive_deps)
-
-    return [MavenInfo(
-        artifact = artifact,
-        has_srcs = len(srcs) > 0,
-        maven_nearest_artifacts = depset(maven_artifacts, transitive = maven_nearest_artifacts),
-        maven_transitive_deps = depset(maven_deps, transitive = maven_transitive_deps),
-        all_transitive_deps = depset(all_deps, transitive = all_transitive_deps),
-    )]
-
-collect_maven_info = aspect(
-    attr_aspects = [
-        "deps",
-        "exports",
-    ],
-    doc = """
-    Collects the Maven information for targets, their dependencies, and their transitive exports.
-    """,
-    implementation = _collect_maven_info_impl,
-)
-
-def _fake_java_library(name, deps = None, exports = None, is_artifact = True):
-    src_file = ["%s.java" % name]
-    native.genrule(
-        name = "%s_source_file" % name,
-        outs = src_file,
-        cmd = "echo 'package pkg; class %s {}' > $@" % name,
-    )
-    native.java_library(
-        name = name,
-        srcs = src_file,
-        tags = ["maven_coordinates=%s:_:_" % name] if is_artifact else [],
-        deps = deps or [],
-        exports = exports or [],
-    )
-
-def _maven_info_test_impl(ctx):
-    env = unittest.begin(ctx)
-    asserts.equals(
-        env,
-        expected = ctx.attr.artifact if ctx.attr.artifact else None,
-        actual = ctx.attr.target[MavenInfo].artifact,
-        msg = "MavenInfo.artifact",
-    )
-    asserts.equals(
-        env,
-        expected = sorted([ctx.label.relative(dep) for dep in ctx.attr.maven_transitive_deps]),
-        actual = sorted(ctx.attr.target[MavenInfo].maven_transitive_deps.to_list()),
-        msg = "MavenInfo.maven_transitive_deps",
-    )
-    asserts.equals(
-        env,
-        expected = sorted([ctx.label.relative(dep) for dep in ctx.attr.all_transitive_deps]),
-        actual = sorted(ctx.attr.target[MavenInfo].all_transitive_deps.to_list()),
-        msg = "MavenInfo.all_transitive_deps",
-    )
-    return unittest.end(env)
-
-_maven_info_test = unittest.make(
-    _maven_info_test_impl,
-    attrs = {
-        "target": attr.label(aspects = [collect_maven_info]),
-        "artifact": attr.string(),
-        "maven_transitive_deps": attr.string_list(),
-        "all_transitive_deps": attr.string_list(),
-    },
-)
-
-def maven_info_tests():
-    """Tests for `pom_file` and `MavenInfo`.
-    """
-    _fake_java_library(name = "A")
-    _fake_java_library(
-        name = "DepOnA",
-        deps = [":A"],
-    )
-
-    _maven_info_test(
-        name = "a_test",
-        target = ":A",
-        artifact = "A:_:_",
-        maven_transitive_deps = [],
-        all_transitive_deps = [],
-    )
-
-    _maven_info_test(
-        name = "dependencies_test",
-        target = ":DepOnA",
-        artifact = "DepOnA:_:_",
-        maven_transitive_deps = [":A"],
-        all_transitive_deps = [":A"],
-    )
-
-    _fake_java_library(
-        name = "ExportsA",
-        exports = [":A"],
-    )
-
-    _maven_info_test(
-        name = "exports_test",
-        target = ":ExportsA",
-        artifact = "ExportsA:_:_",
-        maven_transitive_deps = [":A"],
-        all_transitive_deps = [":A"],
-    )
-
-    _fake_java_library(
-        name = "TransitiveExports",
-        exports = [":ExportsA"],
-    )
-
-    _maven_info_test(
-        name = "transitive_exports_test",
-        target = ":TransitiveExports",
-        artifact = "TransitiveExports:_:_",
-        maven_transitive_deps = [":ExportsA", ":A"],
-        all_transitive_deps = [":ExportsA", ":A"],
-    )
-
-    _fake_java_library(
-        name = "TransitiveDeps",
-        deps = [":ExportsA"],
-    )
-
-    _maven_info_test(
-        name = "transitive_deps_test",
-        target = ":TransitiveDeps",
-        artifact = "TransitiveDeps:_:_",
-        maven_transitive_deps = [":ExportsA", ":A"],
-        all_transitive_deps = [":ExportsA", ":A"],
-    )
-
-    _fake_java_library(name = "Node1", is_artifact = False)
-    _maven_info_test(
-        name = "test_node1",
-        target = ":Node1",
-        maven_transitive_deps = [],
-        all_transitive_deps = [],
-    )
-
-    _fake_java_library(name = "Node2_Artifact", deps = [":Node1"])
-    _maven_info_test(
-        name = "test_node2",
-        target = ":Node2_Artifact",
-        artifact = "Node2_Artifact:_:_",
-        maven_transitive_deps = [],
-        all_transitive_deps = [":Node1"],
-    )
-
-    _fake_java_library(name = "Node3", deps = [":Node2_Artifact"], is_artifact = False)
-    _maven_info_test(
-        name = "test_node3",
-        target = ":Node3",
-        maven_transitive_deps = [":Node1", ":Node2_Artifact"],
-        all_transitive_deps = [":Node1", ":Node2_Artifact"],
-    )
-
-    _fake_java_library(name = "Node4", deps = [":Node3"], is_artifact = False)
-    _maven_info_test(
-        name = "test_node4",
-        target = ":Node4",
-        maven_transitive_deps = [":Node1", ":Node2_Artifact"],
-        all_transitive_deps = [":Node1", ":Node2_Artifact", ":Node3"],
-    )
diff --git a/tools/pom-template.xml b/tools/pom-template.xml
index 68b6ac0..39ed62d 100644
--- a/tools/pom-template.xml
+++ b/tools/pom-template.xml
@@ -16,6 +16,7 @@
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
+
   <parent>
     <groupId>org.sonatype.oss</groupId>
     <artifactId>oss-parent</artifactId>
@@ -31,7 +32,7 @@
   <packaging>{packaging}</packaging>
 
   <scm>
-    <url>https://github.com/google/dagger/</url>
+    <url>http://github.com/google/dagger/</url>
     <connection>scm:git:git://github.com/google/dagger.git</connection>
     <developerConnection>scm:git:ssh://git@github.com/google/dagger.git</developerConnection>
     <tag>HEAD</tag>
@@ -39,21 +40,22 @@
 
   <issueManagement>
     <system>GitHub Issues</system>
-    <url>https://github.com/google/dagger/issues</url>
+    <url>http://github.com/google/dagger/issues</url>
   </issueManagement>
 
   <licenses>
     <license>
       <name>Apache 2.0</name>
-      <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
     </license>
   </licenses>
 
   <organization>
     <name>Google, Inc.</name>
-    <url>https://www.google.com</url>
+    <url>http://www.google.com</url>
   </organization>
+
   <dependencies>
-    {generated_bzl_deps}
+{generated_bzl_deps}
   </dependencies>
 </project>
diff --git a/util/deploy-dagger.sh b/util/deploy-dagger.sh
deleted file mode 100755
index ddf4926..0000000
--- a/util/deploy-dagger.sh
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/bin/bash
-
-set -eu
-
-readonly MVN_GOAL="$1"
-readonly VERSION_NAME="$2"
-shift 2
-readonly EXTRA_MAVEN_ARGS=("$@")
-
-# Builds and deploys the given artifacts to a configured maven goal.
-# @param {string} library the library to deploy.
-# @param {string} pomfile the pom file to deploy.
-# @param {string} srcjar the sources jar of the library. This is an optional
-# parameter, if provided then javadoc must also be provided.
-# @param {string} javadoc the java doc jar of the library. This is an optional
-# parameter, if provided then srcjar must also be provided.
-_deploy() {
-  local library=$1
-  local pomfile=$2
-  local srcjar=$3
-  local javadoc=$4
-  bash $(dirname $0)/deploy-library.sh \
-      "$library" \
-      "$pomfile" \
-      "$srcjar" \
-      "$javadoc" \
-      "$MVN_GOAL" \
-      "$VERSION_NAME" \
-      "${EXTRA_MAVEN_ARGS[@]:+${EXTRA_MAVEN_ARGS[@]}}"
-}
-
-_deploy \
-  java/dagger/libcore.jar \
-  java/dagger/pom.xml \
-  java/dagger/libcore-src.jar \
-  java/dagger/core-javadoc.jar
-
-_deploy \
-  gwt/libgwt.jar \
-  gwt/pom.xml \
-  gwt/libgwt.jar \
-  gwt/libgwt.jar
-
-_deploy \
-  java/dagger/internal/codegen/artifact.jar \
-  java/dagger/internal/codegen/pom.xml \
-  java/dagger/internal/codegen/artifact-src.jar \
-  java/dagger/internal/codegen/artifact-javadoc.jar
-
-_deploy \
-  java/dagger/producers/artifact.jar \
-  java/dagger/producers/pom.xml \
-  java/dagger/producers/artifact-src.jar \
-  java/dagger/producers/artifact-javadoc.jar
-
-_deploy \
-  java/dagger/spi/artifact.jar \
-  java/dagger/spi/pom.xml \
-  java/dagger/spi/artifact-src.jar \
-  java/dagger/spi/artifact-javadoc.jar
-
-_deploy \
-  java/dagger/android/android.aar \
-  java/dagger/android/pom.xml \
-  java/dagger/android/libandroid-src.jar \
-  java/dagger/android/android-javadoc.jar
-
-_deploy \
-  java/dagger/android/android-legacy.aar \
-  java/dagger/android/legacy-pom.xml \
-  "" \
-  ""
-
-# b/37741866 and https://github.com/google/dagger/issues/715
-_deploy \
-  java/dagger/android/libandroid.jar \
-  java/dagger/android/jarimpl-pom.xml \
-  java/dagger/android/libandroid-src.jar \
-  java/dagger/android/android-javadoc.jar
-
-_deploy \
-  java/dagger/android/support/support.aar \
-  java/dagger/android/support/pom.xml \
-  java/dagger/android/support/libsupport-src.jar \
-  java/dagger/android/support/support-javadoc.jar
-
-_deploy \
-  java/dagger/android/support/support-legacy.aar \
-  java/dagger/android/support/legacy-pom.xml \
-  "" \
-  ""
-
-_deploy \
-  shaded_android_processor.jar \
-  java/dagger/android/processor/pom.xml \
-  java/dagger/android/processor/libprocessor-src.jar \
-  java/dagger/android/processor/processor-javadoc.jar
-
-_deploy \
-  java/dagger/grpc/server/libserver.jar \
-  java/dagger/grpc/server/server-pom.xml \
-  java/dagger/grpc/server/libserver-src.jar \
-  java/dagger/grpc/server/javadoc.jar
-
-_deploy \
-  java/dagger/grpc/server/libannotations.jar \
-  java/dagger/grpc/server/annotations-pom.xml \
-  java/dagger/grpc/server/libannotations-src.jar \
-  java/dagger/grpc/server/javadoc.jar
-
-_deploy \
-  shaded_grpc_server_processor.jar \
-  java/dagger/grpc/server/processor/pom.xml \
-  java/dagger/grpc/server/processor/libprocessor-src.jar \
-  java/dagger/grpc/server/processor/javadoc.jar
-
-_deploy \
-  java/dagger/lint/lint-artifact.jar \
-  java/dagger/lint/lint-pom.xml \
-  java/dagger/lint/lint-artifact-src.jar \
-  java/dagger/lint/lint-artifact-javadoc.jar
-
-_deploy \
-  java/dagger/lint/lint-android-artifact.aar \
-  java/dagger/lint/lint-android-pom.xml \
-  "" \
-  ""
diff --git a/util/deploy-hilt.sh b/util/deploy-hilt.sh
deleted file mode 100755
index 3c25c10..0000000
--- a/util/deploy-hilt.sh
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/bin/bash
-
-set -eu
-
-readonly MVN_GOAL="$1"
-readonly VERSION_NAME="$2"
-shift 2
-readonly EXTRA_MAVEN_ARGS=("$@")
-
-# Builds and deploys the given artifacts to a configured maven goal.
-# @param {string} library the library to deploy.
-# @param {string} pomfile the pom file to deploy.
-# @param {string} srcjar the sources jar of the library. This is an optional
-# parameter, if provided then javadoc must also be provided.
-# @param {string} javadoc the java doc jar of the library. This is an optional
-# parameter, if provided then srcjar must also be provided.
-_deploy() {
-  local library=$1
-  local pomfile=$2
-  local srcjar=$3
-  local javadoc=$4
-  bash $(dirname $0)/deploy-library.sh \
-      "$library" \
-      "$pomfile" \
-      "$srcjar" \
-      "$javadoc" \
-      "$MVN_GOAL" \
-      "$VERSION_NAME" \
-      "${EXTRA_MAVEN_ARGS[@]:+${EXTRA_MAVEN_ARGS[@]}}"
-}
-
-_deploy \
-  java/dagger/hilt/android/artifact.aar \
-  java/dagger/hilt/android/pom.xml \
-  java/dagger/hilt/android/artifact-src.jar \
-  java/dagger/hilt/android/artifact-javadoc.jar
-
-_deploy \
-  java/dagger/hilt/android/testing/artifact.aar \
-  java/dagger/hilt/android/testing/pom.xml \
-  java/dagger/hilt/android/testing/artifact-src.jar \
-  java/dagger/hilt/android/testing/artifact-javadoc.jar
-
-_deploy \
-  java/dagger/hilt/processor/artifact.jar \
-  java/dagger/hilt/processor/pom.xml \
-  java/dagger/hilt/processor/artifact-src.jar \
-  java/dagger/hilt/processor/artifact-javadoc.jar
-
-_deploy \
-  java/dagger/hilt/android/processor/artifact.jar \
-  java/dagger/hilt/android/processor/pom.xml \
-  java/dagger/hilt/android/processor/artifact-src.jar \
-  java/dagger/hilt/android/processor/artifact-javadoc.jar
-
-_deploy \
-  java/dagger/hilt/artifact-core.jar \
-  java/dagger/hilt/pom.xml \
-  java/dagger/hilt/artifact-core-src.jar \
-  java/dagger/hilt/artifact-core-javadoc.jar
-
-# Builds and deploy the Gradle plugin.
-_deploy_plugin() {
-  local plugindir=java/dagger/hilt/android/plugin
-  ./$plugindir/gradlew -p $plugindir --no-daemon clean \
-    publishAllPublicationsToMavenRepository -PPublishVersion="$VERSION_NAME"
-  local outdir=$plugindir/build/repo/com/google/dagger/hilt-android-gradle-plugin/$VERSION_NAME
-  # When building '-SNAPSHOT' versions in gradle, the filenames replaces
-  # '-SNAPSHOT' with timestamps, so we need to disambiguate by finding each file
-  # to deploy. See: https://stackoverflow.com/questions/54182823/
-  local suffix
-  if [[ "$VERSION_NAME" == *"-SNAPSHOT" ]]; then
-    # Gets the timestamp part out of the name to be used as suffix.
-    # Timestamp format is ########.######-#.
-    suffix=$(find $outdir -name "*.pom" | grep -Eo '[0-9]{8}\.[0-9]{6}-[0-9]{1}')
-  else
-    suffix=$VERSION_NAME
-  fi
-  mvn "$MVN_GOAL" \
-    -Dfile="$(find $outdir -name "*-$suffix.jar")" \
-    -DpomFile="$(find $outdir -name "*-$suffix.pom")" \
-    -Dsources="$(find $outdir -name "*-$suffix-sources.jar")" \
-    -Djavadoc="$(find $outdir -name "*-$suffix-javadoc.jar")" \
-    "${EXTRA_MAVEN_ARGS[@]:+${EXTRA_MAVEN_ARGS[@]}}"
-}
-
-# Gradle Plugin is built with Gradle, but still deployed via Maven (mvn)
-_deploy_plugin
diff --git a/util/deploy-library.sh b/util/deploy-library.sh
deleted file mode 100755
index a744402..0000000
--- a/util/deploy-library.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/bash
-
-set -eu
-
-# Builds and deploys the given artifacts to a configured maven goal.
-# @param {string} library the library to deploy.
-# @param {string} pomfile the pom file to deploy.
-# @param {string} srcjar the sources jar of the library. This is an optional
-# parameter, if provided then javadoc must also be provided.
-# @param {string} javadoc the java doc jar of the library. This is an optional
-# parameter, if provided then srcjar must also be provided.
-deploy_library() {
-  local library=$1
-  local pomfile=$2
-  local srcjar=$3
-  local javadoc=$4
-  local mvn_goal=$5
-  local version_name=$6
-  shift 6
-  local extra_maven_args=("$@")
-
-  bazel build --define=pom_version="$version_name" \
-    $library $pomfile
-
-  # TODO(bcorso): Consider moving this into the "gen_maven_artifact" macro, this
-  # requires having the version checked-in for the build system.
-  add_tracking_version \
-    $(bazel_output_file $library) \
-    $(bazel_output_file $pomfile) \
-    $version_name
-
-  if [ -n "$srcjar" ] && [ -n "$javadoc" ] ; then
-    bazel build --define=pom_version="$version_name" \
-      $srcjar $javadoc
-    mvn $mvn_goal \
-      -Dfile=$(bazel_output_file $library) \
-      -Djavadoc=$(bazel_output_file $javadoc) \
-      -DpomFile=$(bazel_output_file $pomfile) \
-      -Dsources=$(bazel_output_file $srcjar) \
-      "${extra_maven_args[@]:+${extra_maven_args[@]}}"
-  else
-    mvn $mvn_goal \
-      -Dfile=$(bazel_output_file $library) \
-      -DpomFile=$(bazel_output_file $pomfile) \
-      "${extra_maven_args[@]:+${extra_maven_args[@]}}"
-  fi
-}
-
-bazel_output_file() {
-  local library=$1
-  local output_file=bazel-bin/$library
-  if [[ ! -e $output_file ]]; then
-     output_file=bazel-genfiles/$library
-  fi
-  if [[ ! -e $output_file ]]; then
-    echo "Could not find bazel output file for $library"
-    exit 1
-  fi
-  echo -n $output_file
-}
-
-add_tracking_version() {
-  local library=$1
-  local pomfile=$2
-  local version_name=$3
-  local group_id=$(find_pom_value $pomfile "groupId")
-  local artifact_id=$(find_pom_value $pomfile "artifactId")
-  local temp_dir=$(mktemp -d)
-  local version_file="META-INF/${group_id}_${artifact_id}.version"
-  mkdir -p "$temp_dir/META-INF/"
-  echo $version_name >> "$temp_dir/$version_file"
-  if [[ $library =~ \.jar$ ]]; then
-    jar uf $library -C $temp_dir $version_file
-  elif [[ $library =~ \.aar$ ]]; then
-    unzip $library classes.jar -d $temp_dir
-    jar uf $temp_dir/classes.jar -C $temp_dir $version_file
-    jar uf $library -C $temp_dir classes.jar
-  else
-    echo "Could not add tracking version file to $library"
-    exit 1
-  fi
-}
-
-find_pom_value() {
-  local pomfile=$1
-  local attribute=$2
-  # Using Python here because `mvn help:evaluate` doesn't work with our gen pom
-  # files since they don't include the aar packaging plugin.
-  python $(dirname $0)/find_pom_value.py $pomfile $attribute
-}
-
-deploy_library "$@"
diff --git a/util/deploy-to-maven-central.sh b/util/deploy-to-maven-central.sh
index de2b49c..1f721a1 100755
--- a/util/deploy-to-maven-central.sh
+++ b/util/deploy-to-maven-central.sh
@@ -6,69 +6,50 @@
   echo "usage $0 <ssl-key> <version-name> [<param> ...]"
   exit 1;
 fi
-readonly KEY=$1
-readonly VERSION_NAME=$2
+key=$1
+version_name=$2
 shift 2
 
-if [[ ! "$VERSION_NAME" =~ ^2\. ]]; then
+if [[ ! "$version_name" =~ ^2\. ]]; then
   echo 'Version name must begin with "2."'
   exit 2
 fi
 
-if [[ "$VERSION_NAME" =~ " " ]]; then
+if [[ "$version_name" =~ " " ]]; then
   echo "Version name must not have any spaces"
   exit 3
 fi
 
-bash $(dirname $0)/run-local-tests.sh
+bazel test //...
 
-# Note: we detach from head before making any sed changes to avoid commiting
-# a particular version to master. This sed change used to be done at the very
-# end of the script, but with the introduction of "-alpha" to the Hilt
-# artifacts, we need to do the sed replacement before deploying the artifacts to
-# maven. Note, that this sed replacement is only done for versioned releases.
-# HEAD-SNAPSHOT and LOCAL_SNAPSHOT versions of Hilt artifacts do not contain
-# "-alpha".
-git checkout --detach
-
-# Set the version string that is used as a tag in all of our libraries. If
-# another repo depends on a versioned tag of Dagger, their java_library.tags
-# should match the versioned release.
-sed -i s/'#ALPHA_POSTFIX'/'+ "-alpha"'/g build_defs.bzl
-sed -i s/'${project.version}'/"${VERSION_NAME}"/g build_defs.bzl
-
-bash $(dirname $0)/deploy-dagger.sh \
+bash $(dirname $0)/execute-deploy.sh \
   "gpg:sign-and-deploy-file" \
-  "$VERSION_NAME" \
+  "$version_name" \
   "-DrepositoryId=sonatype-nexus-staging" \
   "-Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/" \
-  "-Dgpg.keyname=${KEY}"
-
-bash $(dirname $0)/deploy-hilt.sh \
-  "gpg:sign-and-deploy-file" \
-  "${VERSION_NAME}-alpha" \
-  "-DrepositoryId=sonatype-nexus-staging" \
-  "-Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/" \
-  "-Dgpg.keyname=${KEY}"
-
-# Note: We avoid commiting until after deploying in case deploying fails and
-# we need to run the script again.
-git commit -m "${VERSION_NAME} release" build_defs.bzl
-git tag -a -m "Dagger ${VERSION_NAME}" dagger-"${VERSION_NAME}"
-git push origin tag dagger-"${VERSION_NAME}"
-
-# Switch back to the original HEAD
-git checkout -
+  "-Dgpg.keyname=${key}"
 
 # Publish javadocs to gh-pages
 bazel build //:user-docs.jar
 git clone --quiet --branch gh-pages \
     https://github.com/google/dagger gh-pages > /dev/null
 cd gh-pages
-unzip ../bazel-bin/user-docs.jar -d api/$VERSION_NAME
-rm -rf api/$VERSION_NAME/META-INF/
-git add api/$VERSION_NAME
-git commit -m "$VERSION_NAME docs"
+unzip ../bazel-bin/user-docs.jar -d api/$version_name
+rm -rf api/$version_name/META-INF/
+git add api/$version_name
+git commit -m "$version_name docs"
 git push origin gh-pages
 cd ..
 rm -rf gh-pages
+
+git checkout --detach
+# Set the version string that is used as a tag in all of our libraries. If another repo depends on
+# a versioned tag of Dagger, their java_library.tags should match the versioned release.
+sed -i s/'${project.version}'/"${version_name}"/g tools/maven.bzl
+git commit -m "${version_name} release" tools/maven.bzl
+
+git tag -a -m "Dagger ${version_name}" dagger-"${version_name}"
+git push origin tag dagger-"${version_name}"
+
+# Switch back to the original HEAD
+git checkout -
diff --git a/util/execute-deploy.sh b/util/execute-deploy.sh
new file mode 100755
index 0000000..1153468
--- /dev/null
+++ b/util/execute-deploy.sh
@@ -0,0 +1,110 @@
+#!/bin/bash
+
+set -eu
+
+readonly MVN_GOAL="$1"
+readonly VERSION_NAME="$2"
+shift 2
+readonly EXTRA_MAVEN_ARGS=("$@")
+
+bazel_output_file() {
+  local library=$1
+  local output_file=bazel-bin/$library
+  if [[ ! -e $output_file ]]; then
+     output_file=bazel-genfiles/$library
+  fi
+  if [[ ! -e $output_file ]]; then
+    echo "Could not find bazel output file for $library"
+    exit 1
+  fi
+  echo -n $output_file
+}
+
+deploy_library() {
+  local library=$1
+  local srcjar=$2
+  local javadoc=$3
+  local pomfile=$4
+  bazel build --define=pom_version="$VERSION_NAME" \
+    $library $srcjar $javadoc $pomfile
+
+  mvn $MVN_GOAL \
+    -Dfile=$(bazel_output_file $library) \
+    -Djavadoc=$(bazel_output_file $javadoc) \
+    -DpomFile=$(bazel_output_file $pomfile) \
+    -Dsources=$(bazel_output_file $srcjar) \
+    "${EXTRA_MAVEN_ARGS[@]:+${EXTRA_MAVEN_ARGS[@]}}"
+}
+
+deploy_library \
+  java/dagger/libcore.jar \
+  java/dagger/libcore-src.jar \
+  java/dagger/core-javadoc.jar \
+  java/dagger/pom.xml
+
+deploy_library \
+  gwt/libgwt.jar \
+  gwt/libgwt.jar \
+  gwt/libgwt.jar \
+  gwt/pom.xml
+
+deploy_library \
+  shaded_compiler.jar \
+  shaded_compiler_src.jar \
+  java/dagger/internal/codegen/codegen-javadoc.jar \
+  java/dagger/internal/codegen/pom.xml
+
+deploy_library \
+  java/dagger/producers/libproducers.jar \
+  java/dagger/producers/libproducers-src.jar \
+  java/dagger/producers/producers-javadoc.jar \
+  java/dagger/producers/pom.xml
+
+deploy_library \
+  shaded_spi.jar \
+  shaded_spi_src.jar \
+  spi-javadoc.jar \
+  java/dagger/spi/pom.xml
+
+deploy_library \
+  java/dagger/android/android.aar \
+  java/dagger/android/libandroid-src.jar \
+  java/dagger/android/android-javadoc.jar \
+  java/dagger/android/pom.xml
+
+# b/37741866 and https://github.com/google/dagger/issues/715
+deploy_library \
+  java/dagger/android/libandroid.jar \
+  java/dagger/android/libandroid-src.jar \
+  java/dagger/android/android-javadoc.jar \
+  java/dagger/android/jarimpl-pom.xml
+
+deploy_library \
+  java/dagger/android/support/support.aar \
+  java/dagger/android/support/libsupport-src.jar \
+  java/dagger/android/support/support-javadoc.jar \
+  java/dagger/android/support/pom.xml
+
+deploy_library \
+  shaded_android_processor.jar \
+  java/dagger/android/processor/libprocessor-src.jar \
+  java/dagger/android/processor/processor-javadoc.jar \
+  java/dagger/android/processor/pom.xml
+
+deploy_library \
+  java/dagger/grpc/server/libserver.jar \
+  java/dagger/grpc/server/libserver-src.jar \
+  java/dagger/grpc/server/javadoc.jar \
+  java/dagger/grpc/server/server-pom.xml
+
+deploy_library \
+  java/dagger/grpc/server/libannotations.jar \
+  java/dagger/grpc/server/libannotations-src.jar \
+  java/dagger/grpc/server/javadoc.jar \
+  java/dagger/grpc/server/annotations-pom.xml
+
+deploy_library \
+  shaded_grpc_server_processor.jar \
+  java/dagger/grpc/server/processor/libprocessor-src.jar \
+  java/dagger/grpc/server/processor/javadoc.jar \
+  java/dagger/grpc/server/processor/pom.xml
diff --git a/util/find_pom_value.py b/util/find_pom_value.py
deleted file mode 100644
index c662b0e..0000000
--- a/util/find_pom_value.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""Find value of a Maven pom attribute given a pom file.
-
-   Usage:
-   python find_pom_value.py <pom-file> <pom-attribute>
-"""
-import sys
-import xml.etree.ElementTree as Xml
-
-
-def main(argv):
-  pom_file = argv[1]
-  pom_attribute = argv[2]
-  print(
-      Xml.ElementTree(file=pom_file).findtext(
-          "{http://maven.apache.org/POM/4.0.0}%s" % pom_attribute))
-
-
-if __name__ == "__main__":
-  main(sys.argv)
diff --git a/util/generate-latest-docs.sh b/util/generate-latest-docs.sh
index c5f71fd..8e9304c 100755
--- a/util/generate-latest-docs.sh
+++ b/util/generate-latest-docs.sh
@@ -1,35 +1,30 @@
-set -eux
+# see http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/ for details
 
-if [ "$GITHUB_REPOSITORY" == "google/dagger" ] && \
-   [ "$GITHUB_EVENT_NAME" == "push" ] && \
-   [ "$GITHUB_REF" == "refs/heads/master" ]; then
+set -eu
+
+if [ "$TRAVIS_REPO_SLUG" == "google/dagger" ] && \
+   [ "$TRAVIS_JDK_VERSION" == "$JDK_FOR_PUBLISHING" ] && \
+   [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
+   [ "$TRAVIS_BRANCH" == "master" ]; then
   echo -e "Publishing javadoc...\n"
   bazel build //:user-docs.jar
   JAVADOC_JAR="$(pwd)/bazel-bin/user-docs.jar"
 
   cd $HOME
-  git clone --quiet --branch=gh-pages https://x-access-token:${GH_TOKEN}@github.com/google/dagger gh-pages > /dev/null
+  git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/google/dagger gh-pages > /dev/null
 
   cd gh-pages
-  git config --global user.email "dagger-dev+github@google.com"
-  git config --global user.name "Dagger Team"
+  git config --global user.email "travis@travis-ci.org"
+  git config --global user.name "travis-ci"
   git rm -rf api/latest
   mkdir -p api
   unzip "$JAVADOC_JAR" -d api/latest
   rm -rf api/latest/META-INF/
   git add -f api/latest
+  git commit -m "Latest javadoc on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages"
+  git push -fq origin gh-pages > /dev/null
 
-  # Check if there are any changes before committing, otherwise attempting
-  # to commit will fail the build (https://stackoverflow.com/a/2659808).
-  if [[ $(git diff-index --quiet HEAD --) || $? == 1 ]]; then
-    # The exist status is 1, meaning there are changes to commit
-    git commit -m "Latest javadoc on successful Github build $GITHUB_WORKFLOW/$GITHUB_RUN_ID auto-pushed to gh-pages"
-    git push -fq origin gh-pages > /dev/null
-    echo -e "Published Javadoc to gh-pages.\n"
-  else
-    # The exist status is 0, meaning there are no changes to commit
-    echo -e "Skipping publishing docs since no changes were detected."
-  fi
+  echo -e "Published Javadoc to gh-pages.\n"
 else
-  echo -e "Not publishing docs for branch=${$GITHUB_REF}"
+  echo -e "Not publishing docs for jdk=${TRAVIS_JDK_VERSION} and branch=${TRAVIS_BRANCH}"
 fi
diff --git a/util/install-local-snapshot.sh b/util/install-local-snapshot.sh
index be6030c..8f77a41 100755
--- a/util/install-local-snapshot.sh
+++ b/util/install-local-snapshot.sh
@@ -4,43 +4,8 @@
 
 echo -e "Installing maven snapshot locally...\n"
 
-bash $(dirname $0)/deploy-dagger.sh \
-  "install:install-file" \
-  "LOCAL-SNAPSHOT"
-
-bash $(dirname $0)/deploy-hilt.sh \
+bash $(dirname $0)/execute-deploy.sh \
   "install:install-file" \
   "LOCAL-SNAPSHOT"
 
 echo -e "Installed local snapshot"
-
-verify_version_file() {
-  local m2_repo=$(mvn help:evaluate -Dexpression=settings.localRepository -q -DforceStdout)
-  local group_path=com/google/dagger
-  local artifact_id=$1
-  local type=$2
-  local version="LOCAL-SNAPSHOT"
-  local temp_dir=$(mktemp -d)
-  local content
-  if [ $type = "jar" ]; then
-    unzip $m2_repo/$group_path/$artifact_id/$version/$artifact_id-$version.jar \
-      META-INF/com.google.dagger_$artifact_id.version \
-      -d $temp_dir
-  elif [ $type = "aar" ]; then
-    unzip $m2_repo/$group_path/$artifact_id/$version/$artifact_id-$version.aar \
-      classes.jar \
-      -d $temp_dir
-    unzip $temp_dir/classes.jar \
-      META-INF/com.google.dagger_$artifact_id.version \
-      -d $temp_dir
-  fi
-  local content=$(cat $temp_dir/META-INF/com.google.dagger_${artifact_id}.version)
-  if [[ $content != $version ]]; then
-    echo "Version file failed verification for artifact: $artifact_id"
-    exit 1
-  fi
-}
-
-# Verify tracking version file in Dagger and Dagger Android
-verify_version_file "dagger" "jar"
-verify_version_file "dagger-android" "aar"
diff --git a/util/publish-snapshot-on-commit.sh b/util/publish-snapshot-on-commit.sh
index 63cc3ea..944a2c3 100755
--- a/util/publish-snapshot-on-commit.sh
+++ b/util/publish-snapshot-on-commit.sh
@@ -1,20 +1,14 @@
 # see https://coderwall.com/p/9b_lfq
 
-set -eux
+set -eu
 
-if [ "$GITHUB_REPOSITORY" == "google/dagger" ] && \
-   [ "$GITHUB_EVENT_NAME" == "push" ] && \
-   [ "$GITHUB_REF" == "refs/heads/master" ]; then
+if [ "$TRAVIS_REPO_SLUG" == "google/dagger" ] && \
+   [ "$TRAVIS_JDK_VERSION" == "$JDK_FOR_PUBLISHING" ] && \
+   [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
+   [ "$TRAVIS_BRANCH" == "master" ]; then
   echo -e "Publishing maven snapshot...\n"
 
-  bash $(dirname $0)/deploy-dagger.sh \
-    "deploy:deploy-file" \
-    "HEAD-SNAPSHOT" \
-    "-DrepositoryId=sonatype-nexus-snapshots" \
-    "-Durl=https://oss.sonatype.org/content/repositories/snapshots" \
-    "--settings=$(dirname $0)/settings.xml"
-
-  bash $(dirname $0)/deploy-hilt.sh \
+  bash $(dirname $0)/execute-deploy.sh \
     "deploy:deploy-file" \
     "HEAD-SNAPSHOT" \
     "-DrepositoryId=sonatype-nexus-snapshots" \
@@ -23,5 +17,5 @@
 
   echo -e "Published maven snapshot"
 else
-  echo -e "Not publishing snapshot for branch=${$GITHUB_REF}"
+  echo -e "Not publishing snapshot for jdk=${TRAVIS_JDK_VERSION} and branch=${TRAVIS_BRANCH}"
 fi
diff --git a/util/run-local-emulator-tests.sh b/util/run-local-emulator-tests.sh
deleted file mode 100755
index 7fc7762..0000000
--- a/util/run-local-emulator-tests.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-readonly GRADLE_PROJECTS=(
-    "javatests/artifacts/hilt-android/simple"
-    "javatests/artifacts/hilt-android/simpleKotlin"
-)
-for project in "${GRADLE_PROJECTS[@]}"; do
-    echo "Running gradle Android emulator tests for $project"
-    ./$project/gradlew -p $project connectedAndroidTest --no-daemon --stacktrace
-done
-
-# Run emulator tests in a project with configuration cache enabled
-# TODO(danysantiago): Once AGP 4.2.0 is stable, remove these project and enable
-# config cache in the other test projects.
-readonly CONFIG_CACHE_PROJECT="javatests/artifacts/hilt-android/gradleConfigCache"
-./$CONFIG_CACHE_PROJECT/gradlew -p $CONFIG_CACHE_PROJECT connectedAndroidTest --no-daemon --stacktrace --configuration-cache
diff --git a/util/run-local-gradle-android-tests.sh b/util/run-local-gradle-android-tests.sh
deleted file mode 100755
index ba51078..0000000
--- a/util/run-local-gradle-android-tests.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-readonly AGP_VERSION_INPUT=$1
-readonly ANDROID_GRADLE_PROJECTS=(
-    "java/dagger/example/gradle/android/simple"
-    "javatests/artifacts/dagger-android/simple"
-    "javatests/artifacts/hilt-android/simple"
-    "javatests/artifacts/hilt-android/simpleKotlin"
-)
-for project in "${ANDROID_GRADLE_PROJECTS[@]}"; do
-    echo "Running gradle tests for $project with AGP $AGP_VERSION_INPUT"
-    AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project buildDebug --no-daemon --stacktrace
-    AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project testDebug --no-daemon --stacktrace
-done
-
-# Run gradle tests in a project with configuration cache enabled
-# TODO(danysantiago): Once AGP 4.2.0 is stable, remove these project and enable
-# config cache in the other test projects.
-readonly CONFIG_CACHE_PROJECT="javatests/artifacts/hilt-android/gradleConfigCache"
-./$CONFIG_CACHE_PROJECT/gradlew -p $CONFIG_CACHE_PROJECT assembleDebug --no-daemon --stacktrace --configuration-cache
diff --git a/util/run-local-gradle-tests.sh b/util/run-local-gradle-tests.sh
deleted file mode 100755
index b88ccab..0000000
--- a/util/run-local-gradle-tests.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-readonly GRADLE_PROJECTS=(
-    "java/dagger/example/gradle/simple"
-    "java/dagger/hilt/android/plugin"
-    "javatests/artifacts/dagger/simple"
-)
-for project in "${GRADLE_PROJECTS[@]}"; do
-    echo "Running gradle tests for $project"
-    ./$project/gradlew -p $project build --no-daemon --stacktrace
-    ./$project/gradlew -p $project test --no-daemon --stacktrace
-done
diff --git a/util/run-local-tests.sh b/util/run-local-tests.sh
deleted file mode 100755
index ea78671..0000000
--- a/util/run-local-tests.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-# These jobs should match .github/workflows/ci.yml. We can't run this script
-# directly in Github since it's too slow for a single job.
-
-# Run local bazel tests
-bazel test --test_output=errors //...
-
-# Install local maven artifacts.
-util/install-local-snapshot.sh
-
-# Run local mvn tests
-pushd examples/maven && mvn compile && popd
-
-# Run local gradle tests
-util/run-local-gradle-tests.sh
-util/run-local-gradle-android-tests.sh "4.1.0"
-util/run-local-gradle-android-tests.sh "4.2.0-beta04"
-
diff --git a/workspace_defs.bzl b/workspace_defs.bzl
deleted file mode 100644
index c017b76..0000000
--- a/workspace_defs.bzl
+++ /dev/null
@@ -1,292 +0,0 @@
-# Copyright (C) 2020 The Google Bazel Common 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.
-
-"""A macro to configure Dagger deps within a workspace"""
-
-load("//:build_defs.bzl", "POM_VERSION", "POM_VERSION_ALPHA")
-
-_DAGGER_VERSION = POM_VERSION
-_HILT_VERSION = POM_VERSION_ALPHA
-
-DAGGER_ARTIFACTS = [
-    "com.google.dagger:dagger:" + _DAGGER_VERSION,
-    "com.google.dagger:dagger-compiler:" + _DAGGER_VERSION,
-    "com.google.dagger:dagger-producers:" + _DAGGER_VERSION,
-    "com.google.dagger:dagger-spi:" + _DAGGER_VERSION,
-]
-
-DAGGER_ANDROID_ARTIFACTS = [
-    "com.google.dagger:dagger-android-processor:" + _DAGGER_VERSION,
-    "com.google.dagger:dagger-android-support:" + _DAGGER_VERSION,
-    "com.google.dagger:dagger-android:" + _DAGGER_VERSION,
-]
-
-HILT_ANDROID_ARTIFACTS = [
-    "androidx.test:core:1.1.0",  # Export for ApplicationProvider
-    "javax.annotation:jsr250-api:1.0",  # Export for @Generated
-    "androidx.annotation:annotation:1.1.0",  # Export for @CallSuper/@Nullable
-    "com.google.dagger:dagger:" + _DAGGER_VERSION,
-    "com.google.dagger:dagger-compiler:" + _DAGGER_VERSION,
-    "com.google.dagger:hilt-android:" + _HILT_VERSION,
-    "com.google.dagger:hilt-android-testing:" + _HILT_VERSION,
-    "com.google.dagger:hilt-android-compiler:" + _HILT_VERSION,
-]
-
-DAGGER_REPOSITORIES = [
-    "https://maven.google.com",
-    "https://repo1.maven.org/maven2",
-]
-
-DAGGER_ANDROID_REPOSITORIES = DAGGER_REPOSITORIES
-
-HILT_ANDROID_REPOSITORIES = DAGGER_REPOSITORIES
-
-# https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#unnamed-macro
-# buildifier: disable=unnamed-macro
-def dagger_rules(repo_name = "@maven"):
-    """Defines the Dagger targets with proper exported dependencies and plugins.
-
-    The targets will be of the form ":<artifact-id>".
-
-    Args:
-      repo_name: The name of the dependency repository (default is "@maven").
-    """
-    native.java_library(
-        name = "dagger",
-        exported_plugins = [":dagger-compiler"],
-        visibility = ["//visibility:public"],
-        exports = [
-            "%s//:com_google_dagger_dagger" % repo_name,
-            "%s//:javax_inject_javax_inject" % repo_name,
-        ],
-    )
-
-    native.java_plugin(
-        name = "dagger-compiler",
-        generates_api = 1,
-        processor_class = "dagger.internal.codegen.ComponentProcessor",
-        deps = [
-            "%s//:com_google_dagger_dagger_compiler" % repo_name,
-        ],
-    )
-
-    native.java_library(
-        name = "dagger-producers",
-        visibility = ["//visibility:public"],
-        exports = [
-            ":dagger",
-            "%s//:com_google_dagger_dagger_producers" % repo_name,
-        ],
-    )
-
-    native.java_library(
-        name = "dagger-spi",
-        visibility = ["//visibility:public"],
-        exports = [
-            "%s//:com_google_dagger_dagger_spi" % repo_name,
-        ],
-    )
-
-# https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#unnamed-macro
-# buildifier: disable=unnamed-macro
-def dagger_android_rules(repo_name = "@maven"):
-    """Defines the Dagger Android targets with proper exported dependencies and plugins.
-
-    The targets will be of the form ":<artifact-id>".
-
-    Args:
-      repo_name: The name of the dependency repository (default is "@maven").
-    """
-
-    # https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#native-android
-    # buildifier: disable=native-android
-    native.android_library(
-        name = "dagger-android",
-        exported_plugins = [":dagger-android-processor"],
-        visibility = ["//visibility:public"],
-        exports = [
-            "%s//:com_google_dagger_dagger_android" % repo_name,
-        ],
-    )
-
-    # https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#native-android
-    # buildifier: disable=native-android
-    native.android_library(
-        name = "dagger-android-support",
-        exported_plugins = [":dagger-android-processor"],
-        visibility = ["//visibility:public"],
-        exports = [
-            ":dagger-android",
-            "%s//:com_google_dagger_dagger_android_support" % repo_name,
-        ],
-    )
-
-    native.java_plugin(
-        name = "dagger-android-processor",
-        generates_api = 1,
-        processor_class = "dagger.android.processor.AndroidProcessor",
-        deps = [
-            "%s//:com_google_dagger_dagger_android_processor" % repo_name,
-        ],
-    )
-
-# https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#unnamed-macro
-# buildifier: disable=unnamed-macro
-def hilt_android_rules(repo_name = "@maven"):
-    """Defines the Hilt Android targets with proper exported dependencies and plugins.
-
-    The targets will be of the form ":<artifact-id>".
-
-    Args:
-      repo_name: The name of the dependency repository (default is "@maven").
-    """
-
-    # https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#native-android
-    # buildifier: disable=native-android
-    native.android_library(
-        name = "hilt-android",
-        exported_plugins = [
-            ":hilt_dagger_compiler",
-            ":hilt_android_entry_point_processor",
-            ":hilt_aggregated_deps_processor",
-            ":hilt_alias_of_processor",
-            ":hilt_define_component_processor",
-            ":hilt_generates_root_input_processor",
-            ":hilt_originating_element_processor",
-            ":hilt_root_processor",
-            ":hilt_view_model_processor",
-        ],
-        visibility = ["//visibility:public"],
-        exports = [
-            "%s//:com_google_dagger_dagger" % repo_name,  # For Dagger APIs
-            "%s//:javax_inject_javax_inject" % repo_name,  # For @Inject
-            "%s//:androidx_annotation_annotation" % repo_name,  # For @CallSuper
-            "%s//:com_google_dagger_hilt_android" % repo_name,
-            "%s//:javax_annotation_jsr250_api" % repo_name,  # For @Generated
-        ],
-    )
-
-    # This target is same as dagger-compiler, but we're redefining it here
-    # so that users don't have to call dagger_rules() first.
-    native.java_plugin(
-        name = "hilt_dagger_compiler",
-        generates_api = 1,
-        processor_class = "dagger.internal.codegen.ComponentProcessor",
-        deps = [
-            "%s//:com_google_dagger_dagger_compiler" % repo_name,
-        ],
-    )
-
-    native.java_plugin(
-        name = "hilt_android_entry_point_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.android.processor.internal.androidentrypoint.AndroidEntryPointProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_aggregated_deps_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.processor.internal.aggregateddeps.AggregatedDepsProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_alias_of_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.processor.internal.aliasof.AliasOfProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_define_component_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.processor.internal.definecomponent.DefineComponentProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_generates_root_input_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.processor.internal.generatesrootinput.GeneratesRootInputProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_originating_element_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.processor.internal.originatingelement.OriginatingElementProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_root_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.processor.internal.root.RootProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_view_model_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.android.processor.internal.viewmodel.ViewModelProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    # https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#native-android
-    # buildifier: disable=native-android
-    native.android_library(
-        name = "hilt-android-testing",
-        testonly = 1,
-        exported_plugins = [
-            ":hilt_bind_value_processor",
-            ":hilt_custom_test_application_processor",
-            ":hilt_testroot_processor",
-            ":hilt_uninstall_modules_processor",
-        ],
-        visibility = ["//visibility:public"],
-        exports = [
-            ":hilt-android",
-            "%s//:androidx_test_core" % repo_name,  # For ApplicationProvider
-            "%s//:com_google_dagger_hilt_android_testing" % repo_name,
-        ],
-    )
-
-    native.java_plugin(
-        name = "hilt_bind_value_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.android.processor.internal.bindvalue.BindValueProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_custom_test_application_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.android.processor.internal.customtestapplication.CustomTestApplicationProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_testroot_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.android.processor.internal.testroot.TestRootProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )
-
-    native.java_plugin(
-        name = "hilt_uninstall_modules_processor",
-        generates_api = 1,
-        processor_class = "dagger.hilt.android.processor.internal.uninstallmodules.UninstallModulesProcessor",
-        deps = ["%s//:com_google_dagger_hilt_android_compiler" % repo_name],
-    )