Repository: square/anvil (kotlin)

Issue:
Factory generation: overloaded Provides functions
If a module has multiple overloaded `@Provides` functions with the same, only one Factory gets generated. 
Dagger gives an error `Cannot have more than one binding method with the same name in a single module` for such modules.

```
@Module
object MyModule {
    @Provides fun s(): String = ""
    @Provides fun s(s: String): Int = 1
}
```

Pull request:
Throw an error if provider method names clash and Anvil is supposed to generate Dagger factories. Dagger throws the same error.

Fixes #99

Patch:
diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/ProvidesMethodFactoryGenerator.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/ProvidesMethodFactoryGenerator.kt
index 47e4c6914..32696523d 100644
--- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/ProvidesMethodFactoryGenerator.kt
+++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/dagger/ProvidesMethodFactoryGenerator.kt
@@ -1,5 +1,6 @@
 package com.squareup.anvil.compiler.codegen.dagger
 
+import com.squareup.anvil.compiler.AnvilCompilationException
 import com.squareup.anvil.compiler.codegen.CodeGenerator.GeneratedFile
 import com.squareup.anvil.compiler.codegen.PrivateCodeGenerator
 import com.squareup.anvil.compiler.codegen.addGeneratedByComment
@@ -55,6 +56,20 @@ internal class ProvidesMethodFactoryGenerator : PrivateCodeGenerator() {
               .functions(includeCompanionObjects = true)
               .asSequence()
               .filter { it.hasAnnotation(daggerProvidesFqName) }
+              .also { functions ->
+                // Check for duplicate function names.
+                val duplicateFunctions = functions
+                    .groupBy { it.requireFqName() }
+                    .filterValues { it.size > 1 }
+
+                if (duplicateFunctions.isNotEmpty()) {
+                  throw AnvilCompilationException(
+                      element = clazz,
+                      message = "Cannot have more than one binding method with the same name in " +
+                          "a single module: ${duplicateFunctions.keys.joinToString()}"
+                  )
+                }
+              }
               .forEach { function ->
                 generateFactoryClass(codeGenDir, module, clazz, function)
               }


Test patch:
diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/ProvidesMethodFactoryGeneratorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/ProvidesMethodFactoryGeneratorTest.kt
index a1c29b194..9943c7ca1 100644
--- a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/ProvidesMethodFactoryGeneratorTest.kt
+++ b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/ProvidesMethodFactoryGeneratorTest.kt
@@ -6,6 +6,7 @@ import com.squareup.anvil.compiler.daggerModule1
 import com.squareup.anvil.compiler.innerModule
 import com.squareup.anvil.compiler.isStatic
 import com.squareup.anvil.compiler.moduleFactoryClass
+import com.tschuchort.compiletesting.KotlinCompilation.ExitCode.COMPILATION_ERROR
 import com.tschuchort.compiletesting.KotlinCompilation.Result
 import dagger.Lazy
 import dagger.internal.Factory
@@ -2156,6 +2157,31 @@ public final class DaggerComponentInterface implements ComponentInterface {
     }
   }
 
+  @Test fun `an error is thrown for overloaded provider methods`() {
+    compile(
+        """
+        package com.squareup.test
+        
+        import dagger.Module
+        import dagger.Provides
+        import dagger.multibindings.ElementsIntoSet
+        
+        typealias StringList = List<String>
+        
+        @Module
+        object DaggerModule1 {
+            @Provides fun provideString(): String = ""
+            @Provides fun provideString(s: String): Int = 1
+        }
+        """
+    ) {
+      assertThat(exitCode).isEqualTo(COMPILATION_ERROR)
+      assertThat(messages).contains(
+          "Cannot have more than one binding method with the same name in a single module"
+      )
+    }
+  }
+
   private fun compile(
     source: String,
     block: Result.() -> Unit = { }