Repository: cjbooms/fabrikt (kotlin)

Issue:
Incorrect generation of OpenFeign client
Dear fabrikt mainteners,

I've faced a bug during OpenFeign client generation.

Having openapi called api.yaml file like this:

```openapi: "3.0.0"
info:
  title: "API Example"
  version: "1.0"
paths:
  /example-path-1:
    get:
      summary: "GET example path 1"
      parameters:
        - $ref: "#/components/parameters/QueryParam4"
        - $ref: "#/components/parameters/QueryParam5"
      responses:
        200:
          description: "successful operation"
          content:
            application/text:
              schema:
                $ref: "#/components/schemas/QueryResult"
components:
  parameters:
    QueryParam4:
      name: "query_param4"
      in: "header"
      schema:
        type: string
      required: false
    QueryParam5:
      name: "query_param5"
      in: "header"
      schema:
        type: string
      required: false
  schemas:
    QueryResult:
      type: "object"
```

and running fabrikt command:

```
java -jar fabrikt.jar \
             --output-directory '/tmp' \
             --base-package 'com.example' \
             --api-file 'api.yaml' \
             --targets 'client' \
             --targets 'http_models' \
             --http-client-opts 'SUSPEND_MODIFIER' \
           --http-client-target 'OPEN_FEIGN'
```


Leads to generation of following client code (which is incorrect because of newline after  "Accept:)


```
package com.example.client

import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
import feign.HeaderMap
import feign.Headers
import feign.Param
import feign.RequestLine
import kotlin.Any
import kotlin.String
import kotlin.Suppress
import kotlin.collections.Map

@Suppress("unused")
interface ExamplePath1Client {
  /**
   * GET example path 1
   *
   * @param queryParam4
   * @param queryParam5
   */
  @RequestLine("GET /example-path-1")
  @Headers(value = ["query_param4: {queryParam4}", "query_param5: {queryParam5}", "Accept:
      application/text"])
  suspend fun getExamplePath1(
    @Param("queryParam4") queryParam4: String? = null,
    @Param("queryParam5") queryParam5: String? = null,
    @HeaderMap additionalHeaders: Map<String, String> = emptyMap()
  ): Map<String, Any>
}
```

Could you please fix it?
Thanks in advance!

Pull request:
Closes #232 

Fix incorrect header parameters generation for OpenFeignClient where a new line was causing compilation errors

Patch:
diff --git a/src/main/kotlin/com/cjbooms/fabrikt/generators/client/OpenFeignInterfaceGenerator.kt b/src/main/kotlin/com/cjbooms/fabrikt/generators/client/OpenFeignInterfaceGenerator.kt
index 9a5a66ff..eedf4298 100644
--- a/src/main/kotlin/com/cjbooms/fabrikt/generators/client/OpenFeignInterfaceGenerator.kt
+++ b/src/main/kotlin/com/cjbooms/fabrikt/generators/client/OpenFeignInterfaceGenerator.kt
@@ -211,10 +211,9 @@ class OpenFeignInterfaceGenerator(
             }
 
             return if (headersValueParts.isNotEmpty()) {
-                val format = if (headersValueParts.size == 1) "%L" else "value = [%L]"
-                OpenFeignAnnotations.headersBuilder()
-                    .addMember(format, headersValueParts.joinToString(", "))
-                    .build()
+                val headersBuilder = OpenFeignAnnotations.headersBuilder()
+                headersValueParts.forEach { headersBuilder.addMember("%S", it) }
+                return headersBuilder.build()
             } else {
                 null
             }
@@ -241,7 +240,7 @@ class OpenFeignInterfaceGenerator(
                     "{${parameter.name}}"
                 }
             return buildCodeBlock {
-                add("%S", "${parameter.originalName}: $parameterValue")
+                add("%L", "${parameter.originalName}: $parameterValue")
             }.toString()
         }
 
@@ -249,7 +248,7 @@ class OpenFeignInterfaceGenerator(
             return operation.getPrimaryContentMediaType()?.key?.let { mediaType ->
                 buildCodeBlock {
                     add(
-                        "%S",
+                        "%L",
                         "${ClientGeneratorUtils.ACCEPT_HEADER_NAME}: $mediaType",
                     )
                 }.toString()


Test patch:
diff --git a/src/test/resources/examples/multiMediaType/client/OpenFeignClient.kt b/src/test/resources/examples/multiMediaType/client/OpenFeignClient.kt
index eafcd534..910f19a1 100644
--- a/src/test/resources/examples/multiMediaType/client/OpenFeignClient.kt
+++ b/src/test/resources/examples/multiMediaType/client/OpenFeignClient.kt
@@ -24,7 +24,10 @@ interface ExamplePath1Client {
      * @param acceptHeader
      */
     @RequestLine("GET /example-path-1?explode_list_query_param={explodeListQueryParam}&query_param2={queryParam2}")
-    @Headers(value = ["Accept: {acceptHeader}", "Accept: application/vnd.custom.media+xml"])
+    @Headers(
+        "Accept: {acceptHeader}",
+        "Accept: application/vnd.custom.media+xml"
+    )
     fun getExamplePath1(
         @Param("explodeListQueryParam") explodeListQueryParam: List<String>? = null,
         @Param("queryParam2") queryParam2: Int? = null,
@@ -43,7 +46,10 @@ interface ExamplePath2Client {
      * @param accept the content type accepted by the client
      */
     @RequestLine("GET /example-path-2?explode_list_query_param={explodeListQueryParam}&query_param2={queryParam2}")
-    @Headers(value = ["Accept: {accept}", "Accept: application/vnd.custom.media+xml"])
+    @Headers(
+        "Accept: {accept}",
+        "Accept: application/vnd.custom.media+xml"
+    )
     fun getExamplePath2(
         @Param("explodeListQueryParam") explodeListQueryParam: List<String>? = null,
         @Param("queryParam2") queryParam2: Int? = null,
@@ -60,7 +66,10 @@ interface MultipleResponseSchemasClient {
      * @param accept the content type accepted by the client
      */
     @RequestLine("GET /multiple-response-schemas")
-    @Headers(value = ["Accept: {accept}", "Accept: application/json"])
+    @Headers(
+        "Accept: {accept}",
+        "Accept: application/json"
+    )
     fun getMultipleResponseSchemas(
         @Param("accept") accept: ContentType? = null,
         @HeaderMap
diff --git a/src/test/resources/examples/openFeignClient/api.yaml b/src/test/resources/examples/openFeignClient/api.yaml
index cb3bff0a..d02ebe42 100644
--- a/src/test/resources/examples/openFeignClient/api.yaml
+++ b/src/test/resources/examples/openFeignClient/api.yaml
@@ -9,6 +9,8 @@ paths:
       parameters:
         - $ref: "#/components/parameters/ListQueryParamExploded"
         - $ref: "#/components/parameters/QueryParam2"
+        - $ref: "#/components/parameters/HeaderParam1"
+        - $ref: "#/components/parameters/HeaderParam2"
       responses:
         200:
           description: "successful operation"
@@ -169,6 +171,19 @@ components:
       schema:
         type: boolean
       required: false
+    HeaderParam1:
+      name: "header_param1"
+      in: "header"
+      schema:
+        type: string
+      required: false
+    HeaderParam2:
+      name: "header_param2"
+      in: "header"
+      schema:
+        type: string
+      required: false
+
 
   headers:
     Location:
diff --git a/src/test/resources/examples/openFeignClient/client/OpenFeignClient.kt b/src/test/resources/examples/openFeignClient/client/OpenFeignClient.kt
index 583b93ce..7c0b3b66 100644
--- a/src/test/resources/examples/openFeignClient/client/OpenFeignClient.kt
+++ b/src/test/resources/examples/openFeignClient/client/OpenFeignClient.kt
@@ -21,12 +21,20 @@ interface ExamplePath1Client {
      *
      * @param explodeListQueryParam
      * @param queryParam2
+     * @param headerParam1
+     * @param headerParam2
      */
     @RequestLine("GET /example-path-1?explode_list_query_param={explodeListQueryParam}&query_param2={queryParam2}")
-    @Headers("Accept: application/vnd.custom.media+json")
+    @Headers(
+        "header_param1: {headerParam1}",
+        "header_param2: {headerParam2}",
+        "Accept: application/vnd.custom.media+json"
+    )
     fun getExamplePath1(
         @Param("explodeListQueryParam") explodeListQueryParam: List<String>? = null,
         @Param("queryParam2") queryParam2: Int? = null,
+        @Param("headerParam1") headerParam1: String? = null,
+        @Param("headerParam2") headerParam2: String? = null,
         @HeaderMap additionalHeaders: Map<String, String> = emptyMap()
     ): QueryResult
 
@@ -55,7 +63,10 @@ interface ExamplePath2Client {
      * @param ifNoneMatch The RFC7232 If-None-Match header field
      */
     @RequestLine("GET /example-path-2/{pathParam}?limit={limit}&query_param2={queryParam2}")
-    @Headers(value = ["If-None-Match: {ifNoneMatch}", "Accept: application/json"])
+    @Headers(
+        "If-None-Match: {ifNoneMatch}",
+        "Accept: application/json"
+    )
     fun getExamplePath2PathParam(
         @Param("pathParam") pathParam: String,
         @Param("limit") limit: Int = 500,
diff --git a/src/test/resources/examples/openFeignClient/client/SuspendableOpenFeignClient.kt b/src/test/resources/examples/openFeignClient/client/SuspendableOpenFeignClient.kt
index f4146ccc..99d70c67 100644
--- a/src/test/resources/examples/openFeignClient/client/SuspendableOpenFeignClient.kt
+++ b/src/test/resources/examples/openFeignClient/client/SuspendableOpenFeignClient.kt
@@ -21,12 +21,20 @@ interface ExamplePath1Client {
      *
      * @param explodeListQueryParam
      * @param queryParam2
+     * @param headerParam1
+     * @param headerParam2
      */
     @RequestLine("GET /example-path-1?explode_list_query_param={explodeListQueryParam}&query_param2={queryParam2}")
-    @Headers("Accept: application/vnd.custom.media+json")
+    @Headers(
+        "header_param1: {headerParam1}",
+        "header_param2: {headerParam2}",
+        "Accept: application/vnd.custom.media+json"
+    )
     suspend fun getExamplePath1(
         @Param("explodeListQueryParam") explodeListQueryParam: List<String>? = null,
         @Param("queryParam2") queryParam2: Int? = null,
+        @Param("headerParam1") headerParam1: String? = null,
+        @Param("headerParam2") headerParam2: String? = null,
         @HeaderMap additionalHeaders: Map<String, String> = emptyMap()
     ): QueryResult
 
@@ -55,7 +63,10 @@ interface ExamplePath2Client {
      * @param ifNoneMatch The RFC7232 If-None-Match header field
      */
     @RequestLine("GET /example-path-2/{pathParam}?limit={limit}&query_param2={queryParam2}")
-    @Headers(value = ["If-None-Match: {ifNoneMatch}", "Accept: application/json"])
+    @Headers(
+        "If-None-Match: {ifNoneMatch}",
+        "Accept: application/json"
+    )
     suspend fun getExamplePath2PathParam(
         @Param("pathParam") pathParam: String,
         @Param("limit") limit: Int = 500,