Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sanitize scala doc string for open api gen (#3047) #3071

Merged
merged 1 commit into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion zio-http/shared/src/main/scala/zio/http/Status.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ sealed trait Status extends Product with Serializable { self =>
lazy val text: String = code.toString

/**
* Returns an Routes[Any, Nothing] that responses with this http status code.
* Returns a Routes[Any, Nothing] that responses with this http status code.
*/
def toRoutes(implicit trace: Trace): Routes[Any, Nothing] =
Handler.status(self).toRoutes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ object JsonSchema {
.map(_.name),
)
.deprecated(deprecated(record))
.description(record.annotations.collectFirst { case description(value) => value })
.description(descriptionFromAnnotations(record.annotations))
case collection: Schema.Collection[_, _] =>
collection match {
case Schema.Sequence(elementSchema, _, _, _, _) =>
Expand Down Expand Up @@ -731,6 +731,18 @@ object JsonSchema {

}

private def descriptionFromAnnotations(annotations: Chunk[Any]) = {
def sanitize(str: java.lang.String): java.lang.String =
str.linesIterator
.map(_.trim.stripPrefix("/**").stripPrefix("/*").stripSuffix("*/").stripPrefix("*").trim)
.filterNot(l => l == "\n" || l == "")
.mkString("\n")
annotations.collectFirst {
case description(value) if value.trim.startsWith("/*") => sanitize(value)
case description(value) => value
}
}

sealed trait SchemaStyle extends Product with Serializable
object SchemaStyle {

Expand Down Expand Up @@ -759,7 +771,7 @@ object JsonSchema {
schema.annotations.exists(_.isInstanceOf[scala.deprecated])

private def fieldDoc(schema: Schema.Field[_, _]): Option[java.lang.String] = {
val description0 = schema.annotations.collectFirst { case description(value) => value }
val description0 = descriptionFromAnnotations(schema.annotations)
val defaultValue = schema.annotations.collectFirst { case fieldDefaultValue(value) => value }.map { _ =>
s"${if (description0.isDefined) "\n" else ""}If not set, this field defaults to the value of the default annotation."
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ object Scala3OpenAPIGenSpec extends ZIOSpecDefault {
zio.http.endpoint.openapi.OpenAPIGen.gen(endpoint = testEndpoint)
assertTrue(true)
},
test("scala doc for api doc is sanetized") {
/**
* This is the Input documentation
*/
final case class Input(a: String)

implicit val schema: Schema[Input] = DeriveSchema.gen[Input]

val testEndpoint =
(Endpoint(RoutePattern.POST / "test") ?? Doc.p("This is my 'POST /test' endpoint doc"))
.in[Input]
.out[String](mediaType = MediaType.application.json, doc = Doc.p("this is the output doc"))

val spec: String =
OpenAPIGen.fromEndpoints(
title = "This is my OpenAPI doc title",
version = "0.0.0",
endpoints = List(testEndpoint)
).toJson

assertTrue(spec.contains(""""description":"This is the Input documentation""""))
}
)
)
}
Loading