Implement HiltViewModelProcessor

Add code generation to the processor. Two sources are generated per
ViewModel whose constructor is annotated with @ViewModelInject. One
class is a ViewModelAssistedFactory implementation for doing assisted
construction of a ViewModel who might have requested a SavedStateHandle.
The second class is a Dagger module with Hilt's InstallIn for adding
the generated ViewModelAssistedFactory to the multibinding map used by
the runtime Hilt module ViewModelFactoryModule.

Test: Manual via integration app
Change-Id: I1582f9d9d651a5a6a17bb457c60ee4fe301ec729
diff --git a/hilt/integration-tests/viewmodelapp/build.gradle b/hilt/integration-tests/viewmodelapp/build.gradle
new file mode 100644
index 0000000..3319ac1
--- /dev/null
+++ b/hilt/integration-tests/viewmodelapp/build.gradle
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.application")
+    id("kotlin-android")
+    id("kotlin-kapt")
+    id("dagger.hilt.android.plugin")
+}
+
+dependencies {
+    implementation(project(":activity:activity"))
+    implementation(project(":fragment:fragment-ktx"))
+    implementation(project(":lifecycle:lifecycle-viewmodel-hilt"))
+    kapt(project(":lifecycle:lifecycle-viewmodel-hilt-compiler"))
+    implementation(KOTLIN_STDLIB)
+    implementation(DAGGER)
+    kapt(DAGGER_COMPILER)
+    implementation(HILT_ANDROID)
+    kapt(HILT_ANDROID_COMPILER)
+}
\ No newline at end of file
diff --git a/hilt/integration-tests/viewmodelapp/src/main/AndroidManifest.xml b/hilt/integration-tests/viewmodelapp/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..09eb5c4
--- /dev/null
+++ b/hilt/integration-tests/viewmodelapp/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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="androidx.hilt.integration.viewmodelapp">
+    <application
+        android:name=".App">
+        <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/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/App.kt b/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/App.kt
new file mode 100644
index 0000000..fc3b2da
--- /dev/null
+++ b/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/App.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.hilt.integration.viewmodelapp
+
+import android.app.Application
+import dagger.hilt.GenerateComponents
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+@GenerateComponents
+class App : Application()
\ No newline at end of file
diff --git a/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleActivity.kt b/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleActivity.kt
new file mode 100644
index 0000000..85102af
--- /dev/null
+++ b/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleActivity.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.hilt.integration.viewmodelapp
+
+import android.os.Bundle
+import android.util.Log
+import androidx.activity.viewModels
+import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.hilt.ActivityViewModelFactory
+import androidx.lifecycle.hilt.ViewModelFactory
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class SimpleActivity : FragmentActivity() {
+
+    // TODO(danysantiago): Should be declared in Hilt gen class
+    @Inject
+    @ActivityViewModelFactory
+    lateinit var viewModelFactory: ViewModelFactory
+
+    val simpleViewModel by viewModels<SimpleViewModel>()
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        setContentView(R.layout.activity_main)
+
+        Log.d("SimpleActivity", simpleViewModel.hi())
+
+        if (savedInstanceState == null) {
+            supportFragmentManager.beginTransaction()
+                .add(R.id.container, SimpleFragment())
+                .commit()
+        }
+    }
+
+    // TODO(danysantiago): Should be overridden by Hilt gen class
+    override fun getDefaultViewModelProviderFactory() = viewModelFactory
+}
\ No newline at end of file
diff --git a/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleFragment.kt b/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleFragment.kt
new file mode 100644
index 0000000..d71bdc7
--- /dev/null
+++ b/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleFragment.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.hilt.integration.viewmodelapp
+
+import android.os.Bundle
+import android.util.Log
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.hilt.FragmentViewModelFactory
+import androidx.lifecycle.hilt.ViewModelFactory
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class SimpleFragment : Fragment() {
+    // TODO(danysantiago): Should be declared in Hilt gen class
+    @Inject
+    @FragmentViewModelFactory
+    lateinit var viewModelFactory: ViewModelFactory
+
+    val simpleViewModel by viewModels<SimpleViewModel>()
+    val activitySimpleViewModel by activityViewModels<SimpleViewModel>()
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        Log.d("SimpleFragment", simpleViewModel.hi())
+        Log.d("SimpleFragment", activitySimpleViewModel.hi())
+    }
+
+    // TODO(danysantiago): Should be overridden by Hilt gen class
+    override fun getDefaultViewModelProviderFactory() = viewModelFactory
+}
\ No newline at end of file
diff --git a/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleViewModel.kt b/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleViewModel.kt
new file mode 100644
index 0000000..739eace
--- /dev/null
+++ b/hilt/integration-tests/viewmodelapp/src/main/java/androidx/hilt/integration/viewmodelapp/SimpleViewModel.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.hilt.integration.viewmodelapp
+
+import androidx.lifecycle.SavedStateHandle
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.hilt.ViewModelInject
+import javax.inject.Inject
+
+@Suppress("UNUSED_PARAMETER")
+class SimpleViewModel @ViewModelInject constructor(
+    mngr: MyManager,
+    savedState: SavedStateHandle
+) : ViewModel() {
+    fun hi() = "$this - hi"
+}
+
+class MyManager @Inject constructor()
diff --git a/hilt/integration-tests/viewmodelapp/src/main/res/layout/activity_main.xml b/hilt/integration-tests/viewmodelapp/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..4e53f8a
--- /dev/null
+++ b/hilt/integration-tests/viewmodelapp/src/main/res/layout/activity_main.xml
@@ -0,0 +1,24 @@
+<?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:id="@+id/container"
+  android:layout_width="match_parent"
+  android:layout_height="match_parent"
+  android:background="@android:color/background_light">
+
+</RelativeLayout>
diff --git a/lifecycle/lifecycle-viewmodel-hilt-compiler/build.gradle b/lifecycle/lifecycle-viewmodel-hilt-compiler/build.gradle
index af2d212..bddf735 100644
--- a/lifecycle/lifecycle-viewmodel-hilt-compiler/build.gradle
+++ b/lifecycle/lifecycle-viewmodel-hilt-compiler/build.gradle
@@ -40,6 +40,8 @@
     implementation(AUTO_COMMON)
     implementation(JAVAPOET)
 
+    testImplementation(JUNIT)
+    testImplementation(TRUTH)
     testImplementation(GOOGLE_COMPILE_TESTING)
 }
 
diff --git a/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/ClassNames.kt b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/ClassNames.kt
index a99f10a..9310102 100644
--- a/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/ClassNames.kt
+++ b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/ClassNames.kt
@@ -18,13 +18,19 @@
 
 import com.squareup.javapoet.ClassName
 
-object ClassNames {
-    val ACTIVITY_COMPONENT = ClassName.get("dagger.hilt.android.component", "ActivityComponent")
+internal object ClassNames {
+    val ACTIVITY_RETAINED_COMPONENT =
+        ClassName.get("dagger.hilt.android.components", "ActivityRetainedComponent")
     val BINDS = ClassName.get("dagger", "Binds")
+    val NON_NULL = ClassName.get("androidx.annotation", "NonNull")
     val INJECT = ClassName.get("javax.inject", "Inject")
     val INSTALL_IN = ClassName.get("dagger.hilt", "InstallIn")
     val INTO_MAP = ClassName.get("dagger.multibindings", "IntoMap")
     val MODULE = ClassName.get("dagger", "Module")
     val PROVIDER = ClassName.get("javax.inject", "Provider")
+    val VIEW_MODEL_ASSISTED_FACTORY =
+        ClassName.get("androidx.lifecycle.hilt", "ViewModelAssistedFactory")
+    val VIEW_MODEL = ClassName.get("androidx.lifecycle", "ViewModel")
     val VIEW_MODEL_KEY = ClassName.get("androidx.lifecycle.hilt", "ViewModelKey")
+    val SAVED_STATE_HANDLE = ClassName.get("androidx.lifecycle", "SavedStateHandle")
 }
diff --git a/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelElements.kt b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelElements.kt
new file mode 100644
index 0000000..3adfd45
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelElements.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle.hilt
+
+import com.google.auto.common.MoreElements
+import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.ParameterizedTypeName
+import javax.lang.model.element.ExecutableElement
+import javax.lang.model.element.TypeElement
+
+/**
+ * Data class that represents a Hilt injected ViewModel
+ */
+internal data class HiltViewModelElements(
+    val typeElement: TypeElement,
+    val constructorElement: ExecutableElement
+) {
+    val className = ClassName.get(typeElement)
+
+    // TODO(danysantiago): Handle nested classes
+    val factoryClassName = ClassName.get(
+        MoreElements.getPackage(typeElement).qualifiedName.toString(),
+        "${typeElement.simpleName}_AssistedFactory")
+
+    val factorySuperTypeName = ParameterizedTypeName.get(
+        ClassNames.VIEW_MODEL_ASSISTED_FACTORY,
+        className)
+
+    // TODO(danysantiago): Handle nested classes
+    val moduleClassName = ClassName.get(
+        MoreElements.getPackage(typeElement).qualifiedName.toString(),
+        "${typeElement.simpleName}_HiltModule")
+}
\ No newline at end of file
diff --git a/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelGenerator.kt b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelGenerator.kt
new file mode 100644
index 0000000..aa6a85e
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelGenerator.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle.hilt
+
+import com.squareup.javapoet.AnnotationSpec
+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.ParameterizedTypeName
+import com.squareup.javapoet.TypeName
+import com.squareup.javapoet.TypeSpec
+import com.squareup.javapoet.WildcardTypeName
+import javax.annotation.processing.ProcessingEnvironment
+import javax.lang.model.element.Modifier
+
+/**
+ * Source generator to support Hilt injection of ViewModels.
+ *
+ * Should generate:
+ * ```
+ * @Module
+ * @InstallIn(ActivityRetainedComponent.class)
+ * public interface $_HiltModule {
+ *   @Binds
+ *   @IntoMap
+ *   @ViewModelKey($.class)
+ *   ViewModelAssistedFactory<?> bind($_AssistedFactory f)
+ * }
+ * ```
+ * and
+ * ```
+ * public final class $_AssistedFactory extends ViewModelAssistedFactory<$> {
+ *
+ *   private final Provider<Dep1> dep1;
+ *   private final Provider<Dep2> dep2;
+ *   ...
+ *
+ *   @Inject
+ *   $_AssistedFactory(Provider<Dep1> dep1, Provider<Dep2> dep2, ...) {
+ *     this.dep1 = dep1;
+ *     this.dep2 = dep2;
+ *     ...
+ *   }
+ *
+ *   @Overrides
+ *   @NonNull
+ *   public $ create(@NonNull SavedStateHandle handle) {
+ *     return new $(dep1.get(), dep2.get(), ..., handle);
+ *   }
+ * }
+ * ```
+ */
+internal class HiltViewModelGenerator(
+    private val processingEnv: ProcessingEnvironment,
+    private val viewModelElements: HiltViewModelElements
+) {
+    fun generate() {
+        val fieldsSpecs = getFieldSpecs(viewModelElements)
+        val constructorSpec = getConstructorMethodSpec(fieldsSpecs)
+        val createMethodSpec = getCreateMethodSpec(viewModelElements)
+        val factoryTypeSpec = TypeSpec.classBuilder(viewModelElements.factoryClassName)
+            .addOriginatingElement(viewModelElements.typeElement)
+            .addSuperinterface(viewModelElements.factorySuperTypeName)
+            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+            .addGeneratedAnnotation(processingEnv.elementUtils, processingEnv.sourceVersion)
+            .addFields(fieldsSpecs)
+            .addMethod(constructorSpec)
+            .addMethod(createMethodSpec)
+            .build()
+        JavaFile.builder(viewModelElements.factoryClassName.packageName(), factoryTypeSpec)
+            .build()
+            .writeTo(processingEnv.filer)
+
+        val hiltModuleTypeSpec = TypeSpec.interfaceBuilder(viewModelElements.moduleClassName)
+            .addOriginatingElement(viewModelElements.typeElement)
+            .addGeneratedAnnotation(processingEnv.elementUtils, processingEnv.sourceVersion)
+            .addAnnotation(ClassNames.MODULE)
+            .addAnnotation(
+                AnnotationSpec.builder(ClassNames.INSTALL_IN)
+                    .addMember("value", "$T.class", ClassNames.ACTIVITY_RETAINED_COMPONENT)
+                    .build())
+            .addMethod(
+                MethodSpec.methodBuilder("bind")
+                    .addAnnotation(ClassNames.BINDS)
+                    .addAnnotation(ClassNames.INTO_MAP)
+                    .addAnnotation(
+                        AnnotationSpec.builder(ClassNames.VIEW_MODEL_KEY)
+                            .addMember("value", "$T.class", viewModelElements.className)
+                            .build())
+                    .addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
+                    .returns(
+                        ParameterizedTypeName.get(
+                            ClassNames.VIEW_MODEL_ASSISTED_FACTORY,
+                            WildcardTypeName.subtypeOf(ClassNames.VIEW_MODEL)))
+                    .addParameter(viewModelElements.factoryClassName, "factory")
+                    .build())
+            .build()
+        JavaFile.builder(viewModelElements.moduleClassName.packageName(), hiltModuleTypeSpec)
+            .build()
+            .writeTo(processingEnv.filer)
+    }
+
+    private fun getFieldSpecs(viewModelElements: HiltViewModelElements) =
+        viewModelElements.constructorElement.parameters.mapNotNull { parameter ->
+            val paramTypeName = TypeName.get(parameter.asType())
+            if (paramTypeName == ClassNames.SAVED_STATE_HANDLE) {
+                // Skip SavedStateHandle since it is assisted injected.
+                return@mapNotNull null
+            }
+            // TODO(danysantiago): Handle qualifiers
+            // TODO(danysantiago): Don't wrap params that are already a Provider
+            FieldSpec.builder(
+                ParameterizedTypeName.get(ClassNames.PROVIDER, paramTypeName),
+                "${parameter.simpleName}Provider",
+                Modifier.PRIVATE, Modifier.FINAL)
+                .build()
+        }
+
+    private fun getConstructorMethodSpec(fieldsSpecs: List<FieldSpec>) =
+        MethodSpec.constructorBuilder()
+            .addAnnotation(ClassNames.INJECT)
+            .apply {
+                fieldsSpecs.forEach { field ->
+                    addParameter(field.type, field.name)
+                    addStatement("this.$1N = $1N", field)
+                }
+            }
+            .build()
+
+    private fun getCreateMethodSpec(viewModelElements: HiltViewModelElements): MethodSpec {
+        val constructorArgs = viewModelElements.constructorElement.parameters.map { param ->
+            val paramTypeName = TypeName.get(param.asType())
+            val paramLiteral = if (paramTypeName == ClassNames.SAVED_STATE_HANDLE) {
+                "handle"
+            } else {
+                // TODO(danysantiago): Consider using the field specs?
+                "${param.simpleName}Provider.get()"
+            }
+            CodeBlock.of(L, paramLiteral)
+        }
+        return MethodSpec.methodBuilder("create")
+            .addAnnotation(Override::class.java)
+            .addAnnotation(ClassNames.NON_NULL)
+            .addModifiers(Modifier.PUBLIC)
+            .returns(viewModelElements.className)
+            .addParameter(
+                ParameterSpec.builder(ClassNames.SAVED_STATE_HANDLE, "handle")
+                    .addAnnotation(ClassNames.NON_NULL)
+                    .build())
+            .addStatement("return new $T($L)",
+                viewModelElements.className, CodeBlock.join(constructorArgs, ",$W"))
+            .build()
+    }
+}
\ No newline at end of file
diff --git a/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelProcessor.kt b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelProcessor.kt
index 785586e..e61373f 100644
--- a/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelProcessor.kt
+++ b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/HiltViewModelProcessor.kt
@@ -17,62 +17,50 @@
 package androidx.lifecycle.hilt
 
 import com.google.auto.common.BasicAnnotationProcessor
+import com.google.auto.common.MoreElements
 import com.google.auto.service.AutoService
 import com.google.common.collect.SetMultimap
 import net.ltgt.gradle.incap.IncrementalAnnotationProcessor
 import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING
+import javax.annotation.processing.ProcessingEnvironment
 import javax.annotation.processing.Processor
+import javax.lang.model.SourceVersion
 import javax.lang.model.element.Element
+import javax.lang.model.element.ExecutableElement
 
 /**
- * Should generate:
- * ```
- * @Module
- * @InstallIn(ActivityComponent.class)
- * public abstract class $_HiltModule {
- *   @Binds
- *   @IntoMap
- *   @ViewModelKey($.class)
- *   public bind($_AssistedFactory f): ViewModelAssistedFactory<?>
- * }
- * ```
- * and
- * ```
- * class $_AssistedFactory extends ViewModelAssistedFactory<$> {
- *
- *   private final Provider<Dep1> dep1;
- *   private final Provider<Dep2> dep2;
- *   ...
- *
- *   @Inject
- *   $_AssistedFactory(Provider<Dep1> dep1, Provider<Dep2> dep2, ...) {
- *     this.dep1 = dep1;
- *     this.dep2 = dep2;
- *     ...
- *   }
- *
- *   @Overrides
- *   @NonNull
- *   public $ create(@NonNull SavedStateHandle handle) {
- *     return new $(dep1.get(), dep2.get(), ..., handle);
- *   }
- * }
- * ```
+ * Annotation processor that generates code enabling assisted injection of ViewModels using Hilt.
  */
 @AutoService(Processor::class)
 @IncrementalAnnotationProcessor(ISOLATING)
 class HiltViewModelProcessor : BasicAnnotationProcessor() {
-    override fun initSteps() = listOf(ViewModelInjectStep())
+    override fun initSteps() = listOf(ViewModelInjectStep(processingEnv))
 
-    class ViewModelInjectStep : ProcessingStep {
+    override fun getSupportedSourceVersion() = SourceVersion.latest()
+}
 
-        override fun annotations() = setOf(ViewModelInject::class.java)
+class ViewModelInjectStep(
+    private val processingEnv: ProcessingEnvironment
+) : BasicAnnotationProcessor.ProcessingStep {
 
-        override fun process(
-            elementsByAnnotation: SetMultimap<Class<out Annotation>, Element>
-        ): MutableSet<out Element> {
-            // TODO(danysantiago): Implement this...
-            return mutableSetOf()
+    override fun annotations() = setOf(ViewModelInject::class.java)
+
+    override fun process(
+        elementsByAnnotation: SetMultimap<Class<out Annotation>, Element>
+    ): MutableSet<out Element> {
+        elementsByAnnotation[ViewModelInject::class.java].forEach { element ->
+            val constructorElement = MoreElements.asExecutable(element)
+            parse(constructorElement)?.let { viewModel ->
+                HiltViewModelGenerator(processingEnv, viewModel).generate()
+            }
         }
+        return mutableSetOf()
+    }
+
+    private fun parse(constructorElement: ExecutableElement): HiltViewModelElements? {
+        val typeElement = MoreElements.asType(constructorElement.enclosingElement)
+        // TODO(danysantiago): Validate type extends ViewModel
+        // TODO(danysantiago): Validate only one constructor is annotated
+        return HiltViewModelElements(typeElement, constructorElement)
     }
 }
\ No newline at end of file
diff --git a/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/JavaPoetExt.kt b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/JavaPoetExt.kt
new file mode 100644
index 0000000..669b6b7
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-hilt-compiler/src/main/kotlin/androidx/lifecycle/hilt/JavaPoetExt.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle.hilt
+
+import com.google.auto.common.GeneratedAnnotationSpecs
+import com.squareup.javapoet.TypeSpec
+import javax.lang.model.SourceVersion
+import javax.lang.model.util.Elements
+
+const val L = "\$L"
+const val T = "\$T"
+const val N = "\$N"
+const val S = "\$S"
+const val W = "\$W"
+
+internal fun TypeSpec.Builder.addGeneratedAnnotation(
+    elements: Elements,
+    sourceVersion: SourceVersion
+) = apply {
+    GeneratedAnnotationSpecs.generatedAnnotationSpec(
+        elements,
+        sourceVersion,
+        HiltViewModelProcessor::class.java
+    ).ifPresent { generatedAnnotation ->
+        addAnnotation(generatedAnnotation)
+    }
+}
\ No newline at end of file
diff --git a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ActivityViewModelFactory.java b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ActivityViewModelFactory.java
new file mode 100644
index 0000000..4e4e8d2
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ActivityViewModelFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle.hilt;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for requesting the activity level {@link ViewModelFactory}
+ */
+@Target({METHOD, PARAMETER, FIELD})
+@Retention(RUNTIME)
+@Qualifier
+public @interface ActivityViewModelFactory {
+}
diff --git a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/FragmentViewModelFactory.java b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/FragmentViewModelFactory.java
new file mode 100644
index 0000000..49dddc3
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/FragmentViewModelFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle.hilt;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for requesting the fragment level {@link ViewModelFactory}
+ */
+@Target({METHOD, PARAMETER, FIELD})
+@Retention(RUNTIME)
+@Qualifier
+public @interface FragmentViewModelFactory {
+}
diff --git a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelFactory.java b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelFactory.java
index 49f1318..6a35805 100644
--- a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelFactory.java
+++ b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelFactory.java
@@ -27,18 +27,22 @@
 
 import java.util.Map;
 
+import javax.inject.Provider;
+
 /**
  * View Model Provider Factory for the Hilt Extension.
  */
 public final class ViewModelFactory extends AbstractSavedStateViewModelFactory {
 
-    private final Map<Class<? extends ViewModel>, ViewModelAssistedFactory<?>> mViewModelFactories;
+    private final Map<
+            Class<? extends ViewModel>,
+            Provider<ViewModelAssistedFactory<? extends ViewModel>>> mViewModelFactories;
 
     ViewModelFactory(
             @NonNull SavedStateRegistryOwner owner,
             @Nullable Bundle defaultArgs,
             @NonNull Map<Class<? extends ViewModel>,
-                    ViewModelAssistedFactory<?>> viewModelFactories) {
+                    Provider<ViewModelAssistedFactory<? extends ViewModel>>> viewModelFactories) {
         super(owner, defaultArgs);
         this.mViewModelFactories = viewModelFactories;
     }
@@ -50,6 +54,6 @@
             @NonNull SavedStateHandle handle) {
         // TODO(danysantiago): What to do with 'key' ???
         // TODO(danysantiago): Better exception for missing class
-        return (T) mViewModelFactories.get(modelClass).create(handle);
+        return (T) mViewModelFactories.get(modelClass).get().create(handle);
     }
 }
diff --git a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelFactoryModules.java b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelFactoryModules.java
new file mode 100644
index 0000000..74da3d7a
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelFactoryModules.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle.hilt;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import androidx.activity.ComponentActivity;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModel;
+import androidx.savedstate.SavedStateRegistryOwner;
+
+import java.util.Map;
+
+import javax.inject.Provider;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.hilt.InstallIn;
+import dagger.hilt.android.components.ActivityComponent;
+import dagger.hilt.android.components.FragmentComponent;
+import dagger.multibindings.Multibinds;
+
+/**
+ * Hilt Modules for providing ViewModel factories.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+public final class ViewModelFactoryModules {
+
+    /**
+     * Hilt Modules for providing the activity level ViewModelFactory
+     */
+    @Module
+    @InstallIn(ActivityComponent.class)
+    public abstract static class ActivityModule {
+
+        @NonNull
+        @Multibinds
+        abstract Map<Class<? extends ViewModel>,
+                ViewModelAssistedFactory<? extends ViewModel>> viewModelFactoriesMap();
+
+        @Provides
+        @NonNull
+        @ActivityViewModelFactory
+        static ViewModelFactory provideFactory(
+                @NonNull Activity activity,
+                @NonNull Map<Class<? extends ViewModel>,
+                        Provider<ViewModelAssistedFactory<? extends ViewModel>>>
+                        viewModelFactories) {
+            // Hilt guarantees concrete activity is a subclass of ComponentActivity.
+            SavedStateRegistryOwner owner = (ComponentActivity) activity;
+            Bundle defaultArgs = activity.getIntent().getExtras();
+            return new ViewModelFactory(owner, defaultArgs, viewModelFactories);
+        }
+    }
+
+    /**
+     * Hilt Modules for providing the fragment level ViewModelFactory
+     */
+    @Module
+    @InstallIn(FragmentComponent.class)
+    public static final class FragmentModule {
+
+        @Provides
+        @NonNull
+        @FragmentViewModelFactory
+        static ViewModelFactory provideFactory(
+                @NonNull Fragment fragment,
+                @NonNull Map<Class<? extends ViewModel>,
+                        Provider<ViewModelAssistedFactory<? extends ViewModel>>>
+                        viewModelFactories) {
+            Bundle defaultArgs = fragment.getArguments();
+            return new ViewModelFactory(fragment, defaultArgs, viewModelFactories);
+        }
+
+        private FragmentModule() {
+        }
+    }
+
+    private ViewModelFactoryModules() {
+    }
+}
diff --git a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelKey.java b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelKey.java
index 09207ab..8f1ad82 100644
--- a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelKey.java
+++ b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelKey.java
@@ -27,18 +27,19 @@
 import dagger.MapKey;
 
 /**
- * Dagger multibinding key for View Models
+ * Dagger multibinding key for ViewModels
  *
  * @hide
  */
 @MapKey
 @Target(ElementType.METHOD)
-@Retention(RetentionPolicy.CLASS)
+@Retention(RetentionPolicy.RUNTIME)
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public @interface ViewModelKey {
     /**
      * The ViewModel class used as key.
      * @return the class.
      */
+    // TODO(danysantiago): Change to use strings and add optimizer rule to avoid class loading.
     Class<? extends ViewModel> value();
 }
diff --git a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelModule.java b/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelModule.java
deleted file mode 100644
index c14787d..0000000
--- a/lifecycle/lifecycle-viewmodel-hilt/src/main/java/androidx/lifecycle/hilt/ViewModelModule.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.lifecycle.hilt;
-
-import android.app.Activity;
-
-import androidx.activity.ComponentActivity;
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.lifecycle.ViewModel;
-
-import java.util.Map;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.hilt.InstallIn;
-import dagger.hilt.android.components.ActivityComponent;
-import dagger.multibindings.Multibinds;
-
-/**
- * Hilt Module for the View Model Provider Factory
- *
- * @hide
- */
-@Module
-@InstallIn(ActivityComponent.class)
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-abstract class ViewModelModule {
-
-    @Multibinds
-    abstract Map<Class<? extends ViewModel>, ViewModelAssistedFactory<?>> viewModelFactoriesMap();
-
-    @Provides
-    @NonNull
-    static ViewModelFactory provideFactory(
-            @NonNull Activity activity,
-            @NonNull Map<Class<? extends ViewModel>,
-                    ViewModelAssistedFactory<?>> viewModelFactories) {
-        // TODO(danysantiago): Validate activity instanceof ComponentActivity
-        return new ViewModelFactory(
-                (ComponentActivity) activity,
-                activity.getIntent().getExtras(),
-                viewModelFactories);
-    }
-}
diff --git a/settings.gradle b/settings.gradle
index 0cf2b52..05af43f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -133,6 +133,7 @@
 includeProject(":fakeannotations", "fakeannotations")
 includeProject(":gridlayout:gridlayout", "gridlayout/gridlayout")
 includeProject(":heifwriter:heifwriter", "heifwriter/heifwriter")
+includeProject(":hilt:integration-tests:hilt-testapp-viewmodel", "hilt/integration-tests/viewmodelapp")
 includeProject(":inspection:inspection", "inspection/inspection")
 includeProject(":inspection:inspection-gradle-plugin", "inspection/inspection-gradle-plugin")
 includeProject(":inspection:inspection-testing", "inspection/inspection-testing")