Repository: square/kotlinpoet
Issue: Potential bug when using lambdas, annotation & collections

Firstly, thank you for even creating this library! I'm very grateful as it makes generating code super easy to do! 

I was using this library to generate the following code
```
val map: Map<String, @CustomAnnotation()() -> Unit>
```
Here's the KotlinPoet code that I used

```
val customAnnotationClassName = ClassName("package_path", "Annotation")
val customAnnotation = AnnotationSpec.builder(customAnnotationClassName).build()
val predicate = LambdaTypeName.get(returnType = UNIT).copy(annotations = arrayListOf(customAnnotation))
val mapType = Map::class.asClassName().parameterizedBy(String::class.asTypeName(), predicate)
val mapProperty = PropertySpec.builder("map", mapType).build()
```

and here's the code that it generated

```
val map: Map<String, @CustomAnnotation() @CustomAnnotation() -> Unit>
```

There are a couple issues here:
- It's showing the name of the annotation twice
- Instead of the annotation showing up twice, I need the round brackets to show up twice`@CustomAnnotation()() -> Unit`

Is there a better way to generate this code? 

Changed files:
kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt, kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeAliasSpecTest.kt, kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt, kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt, kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt, kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt

diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt
index c54e4b42..fa141b86 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt
+++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt
@@ -519,8 +519,6 @@ class LambdaTypeName private constructor(
   }
 
   override fun emit(out: CodeWriter): CodeWriter {
-    emitAnnotations(out)
-
     if (isNullable) {
       out.emit("(")
     }
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt
index f93f025a..6abcad68 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt
+++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt
@@ -769,4 +769,40 @@ class FunSpecTest {
       |}
       |""".trimMargin())
   }
+
+  @Test fun annotatedLambdaReceiverType() {
+    val annotation = AnnotationSpec.builder(ClassName("com.squareup.tacos", "Annotation")).build()
+    val type = LambdaTypeName.get(returnType = UNIT).copy(annotations = listOf(annotation))
+    val spec = FileSpec.builder("com.squareup.tacos", "Taco")
+        .addFunction(FunSpec.builder("foo")
+            .receiver(type)
+            .build())
+        .build()
+    assertThat(spec.toString()).isEqualTo("""
+      |package com.squareup.tacos
+      |
+      |import kotlin.Unit
+      |
+      |fun (@Annotation () -> Unit).foo() {
+      |}
+      |""".trimMargin())
+  }
+
+  @Test fun annotatedLambdaReturnType() {
+    val annotation = AnnotationSpec.builder(ClassName("com.squareup.tacos", "Annotation")).build()
+    val type = LambdaTypeName.get(returnType = UNIT).copy(annotations = listOf(annotation))
+    val spec = FileSpec.builder("com.squareup.tacos", "Taco")
+        .addFunction(FunSpec.builder("foo")
+            .returns(type)
+            .build())
+        .build()
+    assertThat(spec.toString()).isEqualTo("""
+      |package com.squareup.tacos
+      |
+      |import kotlin.Unit
+      |
+      |fun foo(): @Annotation () -> Unit {
+      |}
+      |""".trimMargin())
+  }
 }
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt
index 28968be7..a5ae88d3 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt
+++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt
@@ -103,4 +103,22 @@ class ParameterSpecTest {
       |}
       |""".trimMargin())
   }
+
+  @Test fun annotatedLambdaType() {
+    val annotation = AnnotationSpec.builder(ClassName("com.squareup.tacos", "Annotation")).build()
+    val type = LambdaTypeName.get(returnType = UNIT).copy(annotations = listOf(annotation))
+    val spec = FileSpec.builder("com.squareup.tacos", "Taco")
+        .addFunction(FunSpec.builder("foo")
+            .addParameter("bar", type)
+            .build())
+        .build()
+    assertThat(spec.toString()).isEqualTo("""
+      |package com.squareup.tacos
+      |
+      |import kotlin.Unit
+      |
+      |fun foo(bar: @Annotation () -> Unit) {
+      |}
+      |""".trimMargin())
+  }
 }
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt
index 0b568a75..cbde293c 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt
+++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt
@@ -138,4 +138,13 @@ class ParameterizedTypeNameTest {
   private fun <Param : Closeable> withParam(): Param = throw NotImplementedError("for testing purposes")
 
   private fun <Param : Closeable> withNullableParam(): Param? = throw NotImplementedError("for testing purposes")
+
+  @Test fun annotatedLambdaTypeParameter() {
+    val annotation = AnnotationSpec.builder(ClassName("", "Annotation")).build()
+    val typeName = Map::class.asTypeName()
+        .plusParameter(String::class.asTypeName())
+        .plusParameter(LambdaTypeName.get(returnType = UNIT).copy(annotations = listOf(annotation)))
+    assertThat(typeName.toString())
+        .isEqualTo("kotlin.collections.Map<kotlin.String, @Annotation () -> kotlin.Unit>")
+  }
 }
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt
index f55d6286..25b9c6a3 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt
+++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt
@@ -375,4 +375,19 @@ class PropertySpecTest {
       |const val FOO: String = "This is a long string with a newline\\nin the middle."
       |""".trimMargin())
   }
+
+  @Test fun annotatedLambdaType() {
+    val annotation = AnnotationSpec.builder(ClassName("com.squareup.tacos", "Annotation")).build()
+    val type = LambdaTypeName.get(returnType = UNIT).copy(annotations = listOf(annotation))
+    val spec = FileSpec.builder("com.squareup.tacos", "Taco")
+        .addProperty(PropertySpec.builder("foo", type).build())
+        .build()
+    assertThat(spec.toString()).isEqualTo("""
+      |package com.squareup.tacos
+      |
+      |import kotlin.Unit
+      |
+      |val foo: @Annotation () -> Unit
+      |""".trimMargin())
+  }
 }
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeAliasSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeAliasSpecTest.kt
index 7ec6eca4..26a15f76 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeAliasSpecTest.kt
+++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeAliasSpecTest.kt
@@ -198,6 +198,15 @@ class TypeAliasSpecTest {
       |typealias `fun` = kotlin.String
       |""".trimMargin())
   }
+
+  @Test fun annotatedLambdaType() {
+    val annotation = AnnotationSpec.builder(ClassName("", "Annotation")).build()
+    val type = LambdaTypeName.get(returnType = UNIT).copy(annotations = listOf(annotation))
+    val spec = TypeAliasSpec.builder("lambda", type).build()
+    assertThat(spec.toString()).isEqualTo("""
+      |typealias lambda = @Annotation () -> kotlin.Unit
+      |""".trimMargin())
+  }
 }
 
 @Retention(RUNTIME)