Skip to content

Commit

Permalink
Fix exhaustive matching
Browse files Browse the repository at this point in the history
  • Loading branch information
987Nabil committed Oct 14, 2023
1 parent f8581d1 commit c4c8ecc
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 106 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package zio.http.endpoint.cli

import scala.annotation.tailrec
import scala.language.implicitConversions
import scala.util.Try

Expand Down Expand Up @@ -310,9 +311,10 @@ private[cli] object HttpOptions {
}

private[cli] def optionsFromSegment(segment: SegmentCodec[_]): Options[String] = {
@tailrec
def fromSegment[A](segment: SegmentCodec[A]): Options[String] =
segment match {
case SegmentCodec.UUID(name) =>
case SegmentCodec.UUID(name) =>
Options
.text(name)
.mapOrFail(str =>
Expand All @@ -324,13 +326,14 @@ private[cli] object HttpOptions {
},
)
.map(_.toString)
case SegmentCodec.Text(name) => Options.text(name)
case SegmentCodec.IntSeg(name) => Options.integer(name).map(_.toInt).map(_.toString)
case SegmentCodec.LongSeg(name) => Options.integer(name).map(_.toInt).map(_.toString)
case SegmentCodec.BoolSeg(name) => Options.boolean(name).map(_.toString)
case SegmentCodec.Literal(value) => Options.Empty.map(_ => value)
case SegmentCodec.Trailing => Options.none.map(_.toString)
case SegmentCodec.Empty => Options.none.map(_.toString)
case SegmentCodec.Text(name) => Options.text(name)
case SegmentCodec.IntSeg(name) => Options.integer(name).map(_.toInt).map(_.toString)
case SegmentCodec.LongSeg(name) => Options.integer(name).map(_.toInt).map(_.toString)
case SegmentCodec.BoolSeg(name) => Options.boolean(name).map(_.toString)
case SegmentCodec.Literal(value) => Options.Empty.map(_ => value)
case SegmentCodec.Trailing => Options.none.map(_.toString)
case SegmentCodec.Empty => Options.none.map(_.toString)
case SegmentCodec.Annotated(codec, _) => fromSegment(codec)
}

fromSegment(segment)
Expand Down
21 changes: 13 additions & 8 deletions zio-http-cli/src/test/scala/zio/http/endpoint/cli/CommandGen.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package zio.http.endpoint.cli

import scala.annotation.tailrec

import zio.cli._
import zio.test._

Expand All @@ -18,17 +20,20 @@ import zio.http.endpoint.cli.EndpointGen._
object CommandGen {

def getSegment(segment: SegmentCodec[_]): (String, String) = {
@tailrec
def fromSegment[A](segment: SegmentCodec[A]): (String, String) =
segment match {
case SegmentCodec.UUID(name) => (name, "text")
case SegmentCodec.Text(name) => (name, "text")
case SegmentCodec.IntSeg(name) => (name, "integer")
case SegmentCodec.LongSeg(name) => (name, "integer")
case SegmentCodec.BoolSeg(name) => (name, "boolean")
case SegmentCodec.Literal(_) => ("", "")
case SegmentCodec.Trailing => ("", "")
case SegmentCodec.Empty => ("", "")
case SegmentCodec.UUID(name) => (name, "text")
case SegmentCodec.Text(name) => (name, "text")
case SegmentCodec.IntSeg(name) => (name, "integer")
case SegmentCodec.LongSeg(name) => (name, "integer")
case SegmentCodec.BoolSeg(name) => (name, "boolean")
case SegmentCodec.Literal(_) => ("", "")
case SegmentCodec.Trailing => ("", "")
case SegmentCodec.Empty => ("", "")
case SegmentCodec.Annotated(codec, _) => fromSegment(codec)
}

fromSegment(segment)
}

Expand Down
25 changes: 13 additions & 12 deletions zio-http/src/main/scala/zio/http/codec/PathCodec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@

package zio.http.codec

import scala.annotation.tailrec
import scala.collection.immutable.ListMap
import scala.language.implicitConversions

import zio.stacktracer.TracingImplicits.disableAutoTrace
import zio.{Chunk, NonEmptyChunk}
import zio._

import zio.http.Path

Expand Down Expand Up @@ -266,14 +264,15 @@ sealed trait PathCodec[A] { self =>
pattern match {
case PathCodec.Segment(segment) =>
Chunk(segment.asInstanceOf[SegmentCodec[_]] match {
case SegmentCodec.Empty => Opt.Unit
case SegmentCodec.Literal(value) => Opt.Match(value)
case SegmentCodec.IntSeg(_) => Opt.IntOpt
case SegmentCodec.LongSeg(_) => Opt.LongOpt
case SegmentCodec.Text(_) => Opt.StringOpt
case SegmentCodec.UUID(_) => Opt.UUIDOpt
case SegmentCodec.BoolSeg(_) => Opt.BoolOpt
case SegmentCodec.Trailing => Opt.TrailingOpt
case SegmentCodec.Empty => Opt.Unit
case SegmentCodec.Literal(value) => Opt.Match(value)
case SegmentCodec.IntSeg(_) => Opt.IntOpt
case SegmentCodec.LongSeg(_) => Opt.LongOpt
case SegmentCodec.Text(_) => Opt.StringOpt
case SegmentCodec.UUID(_) => Opt.UUIDOpt
case SegmentCodec.BoolSeg(_) => Opt.BoolOpt
case SegmentCodec.Trailing => Opt.TrailingOpt
case SegmentCodec.Annotated(codec, _) => loop(PathCodec.Segment(codec)).head
})

case Concat(left, right, combiner, _) =>
Expand Down Expand Up @@ -305,14 +304,16 @@ sealed trait PathCodec[A] { self =>
loop(self)
}

def renderIgnoreTrailing: String = {
private[zio] def renderIgnoreTrailing: String = {
def loop(path: PathCodec[_]): String = path match {
case PathCodec.Concat(left, right, _, _) =>
loop(left) + loop(right)

case PathCodec.Segment(SegmentCodec.Trailing) => ""

case PathCodec.Segment(segment) => segment.render

case PathCodec.TransformOrFail(api, _, _) => loop(api)
}

loop(self)
Expand Down
35 changes: 30 additions & 5 deletions zio-http/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala
Original file line number Diff line number Diff line change
Expand Up @@ -292,22 +292,47 @@ object JsonSchema {
case TextCodec.Constant(string) => JsonSchema.Enum(Chunk(EnumValue.Str(string)))
case TextCodec.StringCodec => JsonSchema.String
case TextCodec.IntCodec => JsonSchema.Integer(JsonSchema.IntegerFormat.Int32)
case TextCodec.LongCodec => JsonSchema.Integer(JsonSchema.IntegerFormat.Int64)
case TextCodec.BooleanCodec => JsonSchema.Boolean
case TextCodec.UUIDCodec => JsonSchema.String
}

def fromSegmentCodec(codec: SegmentCodec[_]): JsonSchema =
codec match {
case SegmentCodec.BoolSeg(_) => JsonSchema.Boolean
case SegmentCodec.IntSeg(_) => JsonSchema.Integer(JsonSchema.IntegerFormat.Int32)
case SegmentCodec.LongSeg(_) => JsonSchema.Integer(JsonSchema.IntegerFormat.Int64)
case SegmentCodec.Text(_) => JsonSchema.String
case SegmentCodec.UUID(_) => JsonSchema.String
case SegmentCodec.BoolSeg(_) => JsonSchema.Boolean
case SegmentCodec.IntSeg(_) => JsonSchema.Integer(JsonSchema.IntegerFormat.Int32)
case SegmentCodec.LongSeg(_) => JsonSchema.Integer(JsonSchema.IntegerFormat.Int64)
case SegmentCodec.Text(_) => JsonSchema.String
case SegmentCodec.UUID(_) => JsonSchema.String
case SegmentCodec.Annotated(codec, annotations) =>
fromSegmentCodec(codec).description(segmentDoc(annotations)).examples(segmentExamples(codec, annotations))
case SegmentCodec.Literal(_) => throw new IllegalArgumentException("Literal segment is not supported.")
case SegmentCodec.Empty => throw new IllegalArgumentException("Empty segment is not supported.")
case SegmentCodec.Trailing => throw new IllegalArgumentException("Trailing segment is not supported.")
}

private def segmentDoc(annotations: Chunk[SegmentCodec.MetaData[_]]) =
annotations.collect { case SegmentCodec.MetaData.Documented(doc) => doc }.reduceOption(_ + _).map(_.toCommonMark)

private def segmentExamples(codec: SegmentCodec[_], annotations: Chunk[SegmentCodec.MetaData[_]]) =
Chunk.fromIterable(
annotations.collect { case SegmentCodec.MetaData.Examples(example) => example.values }.flatten.map { value =>
codec match {
case SegmentCodec.Empty => throw new IllegalArgumentException("Empty segment is not supported.")
case SegmentCodec.Literal(_) => throw new IllegalArgumentException("Literal segment is not supported.")
case SegmentCodec.BoolSeg(_) => Json.Bool(value.asInstanceOf[Boolean])
case SegmentCodec.IntSeg(_) => Json.Num(value.asInstanceOf[Int])
case SegmentCodec.LongSeg(_) => Json.Num(value.asInstanceOf[Long])
case SegmentCodec.Text(_) => Json.Str(value.asInstanceOf[String])
case SegmentCodec.UUID(_) => Json.Str(value.asInstanceOf[java.util.UUID].toString)
case SegmentCodec.Trailing =>
throw new IllegalArgumentException("Trailing segment is not supported.")
case SegmentCodec.Annotated(_, _) =>
throw new IllegalStateException("Annotated SegmentCodec should never be nested.")
}
},
)

def fromZSchema(schema: Schema[_], refType: SchemaStyle = SchemaStyle.Inline): JsonSchema =
schema match {
case enum0: Schema.Enum[_] if refType != SchemaStyle.Inline && nominal(enum0).isDefined =>
Expand Down
82 changes: 41 additions & 41 deletions zio-http/src/main/scala/zio/http/endpoint/openapi/OpenAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -445,21 +445,21 @@ object OpenAPI {
* path.
* @param description
* A description, intended to apply to all operations in this path.
* @param getOp
* @param get
* A definition of a GET operation on this path.
* @param putOp
* @param put
* A definition of a PUT operation on this path.
* @param postOp
* @param post
* A definition of a POST operation on this path.
* @param deleteOp
* @param delete
* A definition of a DELETE operation on this path.
* @param optionsOp
* @param options
* A definition of a OPTIONS operation on this path.
* @param headOp
* @param head
* A definition of a HEAD operation on this path.
* @param patchOp
* @param patch
* A definition of a PATCH operation on this path.
* @param traceOp
* @param trace
* A definition of a TRACE operation on this path.
* @param servers
* An alternative server List to service all operations in this path.
Expand All @@ -474,35 +474,35 @@ object OpenAPI {
@fieldName("$ref") ref: Option[String],
summary: Option[String],
description: Option[Doc],
getOp: Option[Operation],
putOp: Option[Operation],
postOp: Option[Operation],
deleteOp: Option[Operation],
optionsOp: Option[Operation],
headOp: Option[Operation],
patchOp: Option[Operation],
traceOp: Option[Operation],
get: Option[Operation],
put: Option[Operation],
post: Option[Operation],
delete: Option[Operation],
options: Option[Operation],
head: Option[Operation],
patch: Option[Operation],
trace: Option[Operation],
servers: List[Server] = List.empty,
parameters: Set[ReferenceOr[Parameter]] = Set.empty,
) {
def get(operation: Operation): PathItem = copy(getOp = Some(operation))
def put(operation: Operation): PathItem = copy(putOp = Some(operation))
def post(operation: Operation): PathItem = copy(postOp = Some(operation))
def delete(operation: Operation): PathItem = copy(deleteOp = Some(operation))
def options(operation: Operation): PathItem = copy(optionsOp = Some(operation))
def head(operation: Operation): PathItem = copy(headOp = Some(operation))
def patch(operation: Operation): PathItem = copy(patchOp = Some(operation))
def trace(operation: Operation): PathItem = copy(traceOp = Some(operation))
def any(operation: Operation): PathItem =
def addGet(operation: Operation): PathItem = copy(get = Some(operation))
def addPut(operation: Operation): PathItem = copy(put = Some(operation))
def addPost(operation: Operation): PathItem = copy(post = Some(operation))
def addDelete(operation: Operation): PathItem = copy(delete = Some(operation))
def addOptions(operation: Operation): PathItem = copy(options = Some(operation))
def addHead(operation: Operation): PathItem = copy(head = Some(operation))
def addPatch(operation: Operation): PathItem = copy(patch = Some(operation))
def addTrace(operation: Operation): PathItem = copy(trace = Some(operation))
def any(operation: Operation): PathItem =
copy(
getOp = Some(operation),
putOp = Some(operation),
postOp = Some(operation),
deleteOp = Some(operation),
optionsOp = Some(operation),
headOp = Some(operation),
patchOp = Some(operation),
traceOp = Some(operation),
get = Some(operation),
put = Some(operation),
post = Some(operation),
delete = Some(operation),
options = Some(operation),
head = Some(operation),
patch = Some(operation),
trace = Some(operation),
)
}

Expand All @@ -514,14 +514,14 @@ object OpenAPI {
ref = None,
summary = None,
description = None,
getOp = None,
putOp = None,
postOp = None,
deleteOp = None,
optionsOp = None,
headOp = None,
patchOp = None,
traceOp = None,
get = None,
put = None,
post = None,
delete = None,
options = None,
head = None,
patch = None,
trace = None,
servers = List.empty,
parameters = Set.empty,
)
Expand Down
Loading

0 comments on commit c4c8ecc

Please sign in to comment.