Repository: RBusarow/ModuleCheck (kotlin)

Issue:
class literal references like AppScope::class aren't counted as references
:moduleA declares absolutely nothing but:

```kotlin
abstract class AppScope private constructor()
```

:moduleB references that scope in an annotation, *with a wildcard import*:

```kotlin
import com.foo.moduleA.*

@Module
@ContributesTo(AppScope::class)
object MyModule
```

The type reference visitor isn't catching type references which are inside a class literal expression, so it never sees that `AppScope::class`.  This means that it doesn't get concatenated with `com.foo.moduleA.` and isn't added to the list of possible references.

ModuleCheck will say that `:moduleA` is unused in `:moduleB`, and will recommend removing it.

Pull request:
fixes #176

Patch:
diff --git a/modulecheck-psi/src/main/kotlin/modulecheck/psi/ReferenceVisitor.kt b/modulecheck-psi/src/main/kotlin/modulecheck/psi/ReferenceVisitor.kt
index f9a4258fc7..fe4140fe59 100644
--- a/modulecheck-psi/src/main/kotlin/modulecheck/psi/ReferenceVisitor.kt
+++ b/modulecheck-psi/src/main/kotlin/modulecheck/psi/ReferenceVisitor.kt
@@ -32,6 +32,12 @@ class ReferenceVisitor(
 
   val apiReferences: MutableSet<String> = mutableSetOf()
 
+  override fun visitReferenceExpression(expression: KtReferenceExpression) {
+    super.visitReferenceExpression(expression)
+
+    typeReferences.add(expression.text)
+  }
+
   override fun visitClassOrObject(classOrObject: KtClassOrObject) {
     super.visitClassOrObject(classOrObject)
 


Test patch:
diff --git a/modulecheck-plugin/src/test/kotlin/modulecheck/gradle/UnusedDependenciesTest.kt b/modulecheck-plugin/src/test/kotlin/modulecheck/gradle/UnusedDependenciesTest.kt
index db114fd20b..8da2f562e5 100644
--- a/modulecheck-plugin/src/test/kotlin/modulecheck/gradle/UnusedDependenciesTest.kt
+++ b/modulecheck-plugin/src/test/kotlin/modulecheck/gradle/UnusedDependenciesTest.kt
@@ -748,4 +748,88 @@ class UnusedDependenciesTest : BaseTest() {
 
     build("moduleCheckUnusedDependency").shouldSucceed()
   }
+
+  @Test
+  fun `module with a declaration used via a class reference with wildcard import should not be unused`() {
+    val appProject = ProjectSpec("app") {
+      addBuildSpec(
+        ProjectBuildSpec {
+          addPlugin("""id("com.android.library")""")
+          addPlugin("kotlin(\"android\")")
+          android = true
+          addProjectDependency("api", jvmSub1)
+        }
+      )
+      addSrcSpec(
+        ProjectSrcSpec(Path.of("src/main/java")) {
+          addRawFile(
+            "MyModule.kt",
+            """
+            package com.example.app
+
+            import com.example.lib1.*
+            import com.squareup.anvil.annotations.ContributesTo
+            import dagger.Module
+
+            @Module
+            @ContributesTo(AppScope::class)
+            object MyModule
+            """.trimIndent()
+          )
+        }
+      )
+    }
+
+    ProjectSpec("project") {
+      applyEach(projects) { project ->
+        addSubproject(project)
+      }
+      addSubproject(appProject)
+      addSubproject(
+        ProjectSpec("lib-1") {
+          addSrcSpec(
+            ProjectSrcSpec(Path.of("src/main/java")) {
+              addRawFile(
+                "AppScope.kt",
+                """
+                package com.example.lib1
+
+                import javax.inject.Scope
+                import kotlin.reflect.KClass
+
+                /**
+                 * Maybe this should just be part of Anvil's api?
+                 */
+                abstract class AppScope private constructor()
+
+                @Scope
+                @Retention(AnnotationRetention.RUNTIME)
+                annotation class SingleIn(val clazz: KClass<*>)
+                """.trimIndent()
+              )
+            }
+          )
+          addBuildSpec(
+            ProjectBuildSpec {
+              addPlugin("kotlin(\"jvm\")")
+              addProjectDependency("api", jvmSub1)
+            }
+          )
+        }
+      )
+      addSettingsSpec(projectSettings.build())
+      addBuildSpec(
+        projectBuild
+          .addBlock(
+            """moduleCheck {
+            |  autoCorrect = false
+            |}
+          """.trimMargin()
+          ).build()
+      )
+    }
+      .writeIn(testProjectDir.toPath())
+
+    build("moduleCheckUnusedDependency").shouldSucceed()
+  }
 }