Repository: square/anvil
Issue: Couldn't resolve fqName

I've successfully converted one of the gradle modules to use Anvil, but still using kapt for code generation. After I remove kapt and enable Anvil's  Dagger class generation, I get the following exception:

```
com.squareup.anvil.compiler.api.AnvilCompilationException: Back-end (JVM) Internal error: Couldn't resolve fqName.
File being compiled: (54,39) in <redacted>/android/lmv/ui/toolbar/LmvToolbarMobius.kt

	at com.squareup.anvil.compiler.internal.reference.TypeReference$Psi.requireTypeName$requireTypeName(TypeReference.kt:222)
	at com.squareup.anvil.compiler.internal.reference.TypeReference$Psi.requireTypeName(TypeReference.kt:292)
	at com.squareup.anvil.compiler.internal.reference.TypeReference$Psi.access$requireTypeName(TypeReference.kt:106)
	at com.squareup.anvil.compiler.internal.reference.TypeReference$Psi$typeName$2.invoke(TypeReference.kt:115)
	at com.squareup.anvil.compiler.internal.reference.TypeReference$Psi$typeName$2.invoke(TypeReference.kt:114)
	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
	at com.squareup.anvil.compiler.internal.reference.TypeReference$Psi.getTypeName(TypeReference.kt:114)
	at com.squareup.anvil.compiler.internal.reference.TypeReference.asTypeName(TypeReference.kt:78)
	at com.squareup.anvil.compiler.codegen.dagger.DaggerGenerationUtilsKt.toConstructorParameter(DaggerGenerationUtils.kt:58)
	at com.squareup.anvil.compiler.codegen.dagger.DaggerGenerationUtilsKt.mapToConstructorParameters(DaggerGenerationUtils.kt:40)
	at com.squareup.anvil.compiler.codegen.dagger.InjectConstructorFactoryGenerator.generateFactoryClass(InjectConstructorFactoryGenerator.kt:65)
	at com.squareup.anvil.compiler.codegen.dagger.InjectConstructorFactoryGenerator.generateCodePrivate(InjectConstructorFactoryGenerator.kt:50)
	at com.squareup.anvil.compiler.codegen.PrivateCodeGenerator.generateCode(PrivateCodeGenerator.kt:21)
	at com.squareup.anvil.compiler.codegen.CodeGenerationExtension.analysisCompleted$generateCode(CodeGenerationExtension.kt:104)
	at com.squareup.anvil.compiler.codegen.CodeGenerationExtension.analysisCompleted(CodeGenerationExtension.kt:151)
	at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:115)
	at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:125)
	at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:99)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:301)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:55)
	at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:113)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:292)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:102)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:60)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:172)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:54)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:91)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:43)
	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:93)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1623)
	at jdk.internal.reflect.GeneratedMethodAccessor105.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829)
```

Changed files:
compiler/src/test/java/com/squareup/anvil/compiler/dagger/InjectConstructorFactoryGeneratorTest.kt
compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt
compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/PsiUtils.kt

diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/PsiUtils.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/PsiUtils.kt
index 779cecd..d77654a 100644
--- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/PsiUtils.kt
+++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/PsiUtils.kt
@@ -267,6 +267,12 @@ public fun PsiElement.requireFqName(
   findClassReferenceInSuperTypes(classReference, importPaths, module)
     ?.let { return it.fqName }
 
+  // Check if it's an inner class in the hierarchy.
+  parents.filterIsInstance<KtClassOrObject>()
+    .map { FqName("${it.requireFqName()}.$classReference") }
+    .firstOrNull { it.canResolveFqName(module) }
+    ?.let { return it }
+
   // Check if it's a named import.
   containingKtFile.importDirectives
     .firstOrNull { classReference == it.importPath?.importedName?.asString() }
diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt
index ddd979e..0d2ea8d 100644
--- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt
+++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt
@@ -214,13 +214,20 @@ public sealed class TypeReference {
       fun KtTypeElement.requireTypeName(): TypeName {
         return when (this) {
           is KtUserType -> {
-            val className = fqNameOrNull(module)?.asClassName(module)
-              ?: if (isTypeParameter()) {
+            val className = try {
+              requireFqName(module).asClassName(module)
+            } catch (e: Exception) {
+              if (isTypeParameter()) {
                 val bounds = findExtendsBound().map { it.asClassName(module) }
                 return TypeVariableName(text, bounds)
               } else {
-                throw AnvilCompilationException("Couldn't resolve fqName.", element = this)
+                throw AnvilCompilationException(
+                  message = "Couldn't resolve fqName.",
+                  element = this,
+                  cause = e
+                )
               }
+            }
 
             val typeArgumentList = typeArgumentList
             if (typeArgumentList != null) {
diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/InjectConstructorFactoryGeneratorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/InjectConstructorFactoryGeneratorTest.kt
index 52fd45e..9c99064 100644
--- a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/InjectConstructorFactoryGeneratorTest.kt
+++ b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/InjectConstructorFactoryGeneratorTest.kt
@@ -23,7 +23,6 @@ import org.junit.runners.Parameterized.Parameters
 import java.io.File
 import javax.inject.Provider
 
-@Suppress("UNCHECKED_CAST")
 @RunWith(Parameterized::class)
 class InjectConstructorFactoryGeneratorTest(
   private val useDagger: Boolean
@@ -233,6 +232,7 @@ public final class InjectClass_Factory implements Factory<InjectClass> {
 }
      */
 
+    @Suppress("EqualsOrHashCode")
     compile(
       """
       package com.squareup.test
@@ -336,6 +336,7 @@ public final class InjectClass_Factory implements Factory<InjectClass> {
 }
      */
 
+    @Suppress("EqualsOrHashCode")
     compile(
       """
       package com.squareup.test
@@ -426,6 +427,7 @@ public final class InjectClass_Factory implements Factory<InjectClass> {
 }
      */
 
+    @Suppress("EqualsOrHashCode")
     compile(
       """
       package com.squareup.test
@@ -890,6 +892,7 @@ public final class InjectClass_Factory implements Factory<InjectClass> {
 }
      */
 
+    @Suppress("ClassName")
     compile(
       """
       package com.squareup.test
@@ -1451,6 +1454,7 @@ public final class InjectClass_Factory implements Factory<InjectClass> {
 }
      */
 
+    @Suppress("ClassName")
     compile(
       """
       package com.squareup.test
@@ -1640,6 +1644,7 @@ public final class MyClass_Factory implements Factory<MyClass> {
 }
      */
 
+    @Suppress("ClassName")
     compile(
       """
       package com.squareup.test
@@ -2022,7 +2027,7 @@ public final class InjectClass_Factory<T> implements Factory<InjectClass<T>> {
       package com.squareup.test
       
       import javax.inject.Inject
-      import javax.inject.Provider;
+      import javax.inject.Provider
       
       class InjectClass<T> @Inject constructor(prov: Provider<T>)
       """
@@ -2135,7 +2140,7 @@ public final class InjectClass_Factory implements Factory<InjectClass> {
       package com.squareup.test
       
       import javax.inject.Inject
-      import javax.inject.Provider;
+      import javax.inject.Provider
       
       class InjectClass @Inject constructor(
         map: Map<Class<out CharSequence>, @JvmSuppressWildcards Provider<String>>
@@ -2667,6 +2672,33 @@ public final class InjectClass_Factory implements Factory<InjectClass> {
     }
   }
 
+  @Test fun `nested inner classes are supported`() {
+    compile(
+      """
+      package com.squareup.test
+
+      import kotlin.LazyThreadSafetyMode.NONE
+      import kotlin.LazyThreadSafetyMode.SYNCHRONIZED 
+      import kotlin.reflect.KClass      
+      import javax.inject.Inject
+      import javax.inject.Named
+      import javax.inject.Qualifier
+      
+      class A {
+        class Factory @Inject constructor(
+          private val innerClassFactory: Achild.Factory
+        )
+      
+        class Achild {
+          class Factory
+        }
+      }
+      """
+    ) {
+      assertThat(classLoader.loadClass("com.squareup.test.A\\$Achild\\$Factory")).isNotNull()
+    }
+  }
+
   private fun compile(
     @Language("kotlin") vararg sources: String,
     previousCompilationResult: Result? = null,