Repository: square/AssistedInject (kotlin)

Issue:
Feature Request: Distinguish between type/name mismatch in constructor vs factory interface
Summary: Currently, the AssistedInject compiler does not inform the user whether the name/type mismatch occurs at the interface/factory or during usage in the assist-injected constructor. 

Example:
```kotlin 
interface ListenableWorkerFactory {
    fun create(context: Context, params: WorkerParameters): RxWorker
}
```

Constructor Usage: 
```kotlin
class ConversationOperationWorker
@AssistedInject constructor(@Assisted context: Context,
                            @Assisted params2: WorkerParameters, //note, should be `params`
                            private val client: ConversationActionClient,
                            private val gson: Gson) : RxWorker(context, params2){ //note, should be `params`

    @AssistedInject.Factory
    interface Factory : ListenableWorkerFactory
    
    //... body
}
````

The compiler error's stacktrace was as follows:
```
e: error: Factory method parameters do not match constructor @Assisted parameters.
  Missing:
   * android.content.Context context
   * androidx.work.WorkerParameters params2
  Unknown:
   * android.content.Context arg0
   * androidx.work.WorkerParameters arg1
```


Although the compiler was correct in that the `ListenableWorkerFactory`'s params were not being matched, it did not tell me _where_ they weren't being matched. 

Now, admittedly, there was user-error here, and it was twofold:
1. I didn't use the same names everywhere
2. I didn't read the error closely enough to realize that it was telling me the incorrect name usage (e.g. `params2`)

That being said, having the compiler point to the erroneous usage would be nice:

1.  the error message should pass the offending element so that `javac` highlights it like a compiler error, with the little snippet + shark-fin ^^ underneath. 

2. Noting _at which site_ the element resides (e.g. constructor vs. factory vs. inherited factory interface), so that the error would say something like `"${paramName} Declared in constructor but missing from factory"` or `"${paramName} present in factory but  but missing from constructor"` 

This happens on the latest `0.5.0` binary.

Pull request:
Closes #113

Patch:
diff --git a/assisted-inject-processor/src/main/java/com/squareup/inject/assisted/processor/AssistedInjectProcessor.kt b/assisted-inject-processor/src/main/java/com/squareup/inject/assisted/processor/AssistedInjectProcessor.kt
index 0c8772d..9f8e447 100644
--- a/assisted-inject-processor/src/main/java/com/squareup/inject/assisted/processor/AssistedInjectProcessor.kt
+++ b/assisted-inject-processor/src/main/java/com/squareup/inject/assisted/processor/AssistedInjectProcessor.kt
@@ -241,15 +241,18 @@ class AssistedInjectProcessor : AbstractProcessor() {
     val keys = factoryKeys.sorted()
     if (keys != expectedKeys) {
       val message = buildString {
-        append("Factory method parameters do not match constructor @Assisted parameters.")
+        append("Factory method parameters do not match constructor @Assisted parameters. ")
+        append("Both parameter type and name must match.")
 
         val missingKeys = expectedKeys - keys
         if (missingKeys.isNotEmpty()) {
-          append(missingKeys.joinToString("\n * ", prefix = "\nMissing:\n * "))
+          append(missingKeys.joinToString("\n * ",
+              prefix = "\nDeclared by constructor, unmatched in factory method:\n * "))
         }
         val unknownKeys = keys - expectedKeys
         if (unknownKeys.isNotEmpty()) {
-          append(unknownKeys.joinToString("\n * ", prefix = "\nUnknown:\n * "))
+          append(unknownKeys.joinToString("\n * ",
+              prefix = "\nDeclared by factory method, unmatched in constructor:\n * "))
         }
       }
       error(message,


Test patch:
diff --git a/assisted-inject-processor/src/test/java/com/squareup/inject/assisted/processor/AssistedInjectProcessorTest.kt b/assisted-inject-processor/src/test/java/com/squareup/inject/assisted/processor/AssistedInjectProcessorTest.kt
index f8c2a08..d9448dc 100644
--- a/assisted-inject-processor/src/test/java/com/squareup/inject/assisted/processor/AssistedInjectProcessorTest.kt
+++ b/assisted-inject-processor/src/test/java/com/squareup/inject/assisted/processor/AssistedInjectProcessorTest.kt
@@ -409,10 +409,10 @@ class AssistedInjectProcessorTest {
         .processedWith(AssistedInjectProcessor())
         .failsToCompile()
         .withErrorContaining("""
-          Factory method parameters do not match constructor @Assisted parameters.
-            Missing:
+          Factory method parameters do not match constructor @Assisted parameters. Both parameter type and name must match.
+            Declared by constructor, unmatched in factory method:
              * java.lang.String baz
-            Unknown:
+            Declared by factory method, unmatched in constructor:
              * java.lang.String fizz
         """.trimIndent())
         .`in`(input).onLine(13)
@@ -441,10 +441,10 @@ class AssistedInjectProcessorTest {
         .processedWith(AssistedInjectProcessor())
         .failsToCompile()
         .withErrorContaining("""
-          Factory method parameters do not match constructor @Assisted parameters.
-            Missing:
+          Factory method parameters do not match constructor @Assisted parameters. Both parameter type and name must match.
+            Declared by constructor, unmatched in factory method:
              * java.lang.String foo
-            Unknown:
+            Declared by factory method, unmatched in constructor:
              * java.lang.String baz
         """.trimIndent())
         .`in`(input).onLine(13)
@@ -864,10 +864,10 @@ class AssistedInjectProcessorTest {
         .processedWith(AssistedInjectProcessor())
         .failsToCompile()
         .withErrorContaining("""
-          Factory method parameters do not match constructor @Assisted parameters.
-            Missing:
+          Factory method parameters do not match constructor @Assisted parameters. Both parameter type and name must match.
+            Declared by constructor, unmatched in factory method:
              * java.lang.String bar
-            Unknown:
+            Declared by factory method, unmatched in constructor:
              * java.lang.Long bar
         """.trimIndent())
         .`in`(input).onLine(13)
@@ -899,10 +899,10 @@ class AssistedInjectProcessorTest {
         .processedWith(AssistedInjectProcessor())
         .failsToCompile()
         .withErrorContaining("""
-          Factory method parameters do not match constructor @Assisted parameters.
-            Missing:
+          Factory method parameters do not match constructor @Assisted parameters. Both parameter type and name must match.
+            Declared by constructor, unmatched in factory method:
              * java.lang.String bar
-            Unknown:
+            Declared by factory method, unmatched in constructor:
              * java.lang.Long bar
         """.trimIndent())
         .`in`(input).onLine(9)
@@ -935,10 +935,10 @@ class AssistedInjectProcessorTest {
         .processedWith(AssistedInjectProcessor())
         .failsToCompile()
         .withErrorContaining("""
-          Factory method parameters do not match constructor @Assisted parameters.
-            Missing:
+          Factory method parameters do not match constructor @Assisted parameters. Both parameter type and name must match.
+            Declared by constructor, unmatched in factory method:
              * java.lang.String bar
-            Unknown:
+            Declared by factory method, unmatched in constructor:
              * @test.Id java.lang.String bar
         """.trimIndent())
         .`in`(input).onLine(14)
@@ -971,10 +971,10 @@ class AssistedInjectProcessorTest {
         .processedWith(AssistedInjectProcessor())
         .failsToCompile()
         .withErrorContaining("""
-          Factory method parameters do not match constructor @Assisted parameters.
-            Missing:
+          Factory method parameters do not match constructor @Assisted parameters. Both parameter type and name must match.
+            Declared by constructor, unmatched in factory method:
              * @test.Id java.lang.String bar
-            Unknown:
+            Declared by factory method, unmatched in constructor:
              * java.lang.String bar
         """.trimIndent())
         .`in`(input).onLine(14)