Skip to content

Commit

Permalink
Merge pull request #1874 from blast-hardcheese/breaking-resolved-from…
Browse files Browse the repository at this point in the history
…-lazy-protocol-objects

Breaking `Resolved[L]` out from lazy protocol objects
  • Loading branch information
blast-hardcheese authored Nov 17, 2023
2 parents 8b8af67 + 920b5f0 commit 0416ad4
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 192 deletions.
130 changes: 69 additions & 61 deletions modules/core/src/main/scala/dev/guardrail/core/ResolvedType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,31 @@ case class LiteralRawType(rawType: Option[String], rawFormat: Option[String]) ex
case class VectorRawType(items: ReifiedRawType) extends ReifiedRawType
case class MapRawType(items: ReifiedRawType) extends ReifiedRawType

sealed trait ResolvedType[L <: LA]
case class Resolved[L <: LA](tpe: L#Type, classDep: Option[L#TermName], defaultValue: Option[L#Term], rawType: ReifiedRawType) extends ResolvedType[L]
sealed trait LazyResolvedType[L <: LA] extends ResolvedType[L] { def value: String }
case class Resolved[L <: LA](tpe: L#Type, classDep: Option[L#TermName], defaultValue: Option[L#Term], rawType: ReifiedRawType)
sealed trait LazyResolvedType[L <: LA] extends { def value: String }
case class Deferred[L <: LA](value: String) extends LazyResolvedType[L]
case class DeferredArray[L <: LA](value: String, containerTpe: Option[L#Type]) extends LazyResolvedType[L]
case class DeferredMap[L <: LA](value: String, containerTpe: Option[L#Type]) extends LazyResolvedType[L]

object ResolvedType {
def resolveReferences[L <: LA, F[_]: Monad](
values: List[(String, ResolvedType[L])]
values: List[(String, Either[LazyResolvedType[L], Resolved[L]])]
)(implicit Sc: LanguageTerms[L, F], Cl: CollectionsLibTerms[L, F], Sw: OpenAPITerms[L, F]): F[List[(String, Resolved[L])]] =
Sw.log.function("resolveReferences") {
import Cl._
import Sw._
val (lazyTypes, resolvedTypes) = Foldable[List].partitionEither(values) {
case (clsName, x: Resolved[L]) => Right((clsName, x))
case (clsName, x: LazyResolvedType[L]) => Left((clsName, x))
case (clsName, Right(x: Resolved[L])) => Right((clsName, x))
case (clsName, Left(x: LazyResolvedType[L])) => Left((clsName, x))
}

def lookupTypeName(clsName: String, tpeName: String, resolvedTypes: List[(String, Resolved[L])])(
def lookupTypeName(tpeName: String, resolvedTypes: List[(String, Resolved[L])])(
f: L#Type => F[L#Type]
): F[Option[(String, Resolved[L])]] =
): F[Option[Resolved[L]]] =
resolvedTypes
.find(_._1 == tpeName)
.map(_._2)
.traverse(x => f(x.tpe).map(tpe => (clsName, x.copy(tpe = tpe))))
.traverse(x => f(x.tpe).map(tpe => x.copy(tpe = tpe)))

type Continue = (List[(String, LazyResolvedType[L])], List[(String, Resolved[L])])
type Stop = List[(String, Resolved[L])]
Expand All @@ -57,11 +56,17 @@ object ResolvedType {
lazyTypes
.partitionEitherM {
case x @ (clsName, Deferred(tpeName)) =>
lookupTypeName(clsName, tpeName, resolvedTypes)(_.pure[F]).map(Either.fromOption(_, x))
lookupTypeName(tpeName, resolvedTypes)(_.pure[F])
.map(_.map((clsName, _)))
.map(Either.fromOption(_, x))
case x @ (clsName, DeferredArray(tpeName, containerTpe)) =>
lookupTypeName(clsName, tpeName, resolvedTypes)(liftVectorType(_, containerTpe)).map(Either.fromOption(_, x))
lookupTypeName(tpeName, resolvedTypes)(liftVectorType(_, containerTpe))
.map(_.map((clsName, _)))
.map(Either.fromOption(_, x))
case x @ (clsName, DeferredMap(tpeName, containerTpe)) =>
lookupTypeName(clsName, tpeName, resolvedTypes)(liftMapType(_, containerTpe)).map(Either.fromOption(_, x))
lookupTypeName(tpeName, resolvedTypes)(liftMapType(_, containerTpe))
.map(_.map((clsName, _)))
.map(Either.fromOption(_, x))
}
.map { case (newLazyTypes, newResolvedTypes) =>
Left((newLazyTypes, resolvedTypes ++ newResolvedTypes))
Expand All @@ -71,59 +76,62 @@ object ResolvedType {
}

def resolve[L <: LA, F[_]: Monad](
value: ResolvedType[L],
value: Either[LazyResolvedType[L], Resolved[L]],
protocolElems: List[StrictProtocolElems[L]]
)(implicit Sc: LanguageTerms[L, F], Cl: CollectionsLibTerms[L, F], Sw: OpenAPITerms[L, F]): F[Resolved[L]] = {
import Sc._
import Cl._
import Sw._
log.debug(s"value: ${value} in ${protocolElems.length} protocol elements") >> (value match {
case x @ Resolved(_, _, _, _) => x.pure[F]
case Deferred(name) =>
for {
formattedName <- formatTypeName(name)
resolved <- resolveType(formattedName, protocolElems)
.flatMap {
case RandomType(name, tpe) =>
Resolved[L](tpe, None, None, ReifiedRawType.unsafeEmpty).pure[F]
case ClassDefinition(name, _, fullType, cls, _, _) =>
Resolved[L](fullType, None, None, ReifiedRawType.unsafeEmpty).pure[F]
case EnumDefinition(name, _, fullType, _, cls, _) =>
Resolved[L](fullType, None, None, ReifiedRawType.of(Some("string"), None)).pure[F]
case ADT(_, _, fullType, _, _) =>
Resolved[L](fullType, None, None, ReifiedRawType.unsafeEmpty).pure[F]
}
} yield resolved
case DeferredArray(name, containerTpe) =>
for {
formattedName <- formatTypeName(name)
resolved <- resolveType(formattedName, protocolElems)
.flatMap {
case RandomType(name, tpe) =>
liftVectorType(tpe, containerTpe).map(Resolved[L](_, None, None, VectorRawType(ReifiedRawType.unsafeEmpty)))
case ClassDefinition(name, _, fullType, cls, _, _) =>
liftVectorType(fullType, containerTpe).map(Resolved[L](_, None, None, VectorRawType(ReifiedRawType.unsafeEmpty)))
case EnumDefinition(name, _, fullType, _, cls, _) =>
liftVectorType(fullType, containerTpe).map(Resolved[L](_, None, None, VectorRawType(ReifiedRawType.unsafeEmpty)))
case ADT(_, _, fullType, _, _) =>
liftVectorType(fullType, containerTpe).map(Resolved[L](_, None, None, VectorRawType(ReifiedRawType.unsafeEmpty)))
}
} yield resolved
case DeferredMap(name, containerTpe) =>
for {
formattedName <- formatTypeName(name)
resolved <- resolveType(formattedName, protocolElems)
.flatMap {
case RandomType(name, tpe) =>
liftMapType(tpe, containerTpe).map(Resolved[L](_, None, None, MapRawType(ReifiedRawType.unsafeEmpty)))
case ClassDefinition(_, _, fullType, _, _, _) =>
liftMapType(fullType, containerTpe).map(Resolved[L](_, None, None, MapRawType(ReifiedRawType.unsafeEmpty)))
case EnumDefinition(_, _, fullType, _, _, _) =>
liftMapType(fullType, containerTpe).map(Resolved[L](_, None, None, MapRawType(ReifiedRawType.unsafeEmpty)))
case ADT(_, _, fullType, _, _) =>
liftMapType(fullType, containerTpe).map(Resolved[L](_, None, None, MapRawType(ReifiedRawType.unsafeEmpty)))
}
} yield resolved
})
for {
_ <- log.debug(s"value: ${value} in ${protocolElems.length} protocol elements")
res <- value match {
case Right(x @ Resolved(_, _, _, _)) => x.pure[F]
case Left(Deferred(name)) =>
for {
formattedName <- formatTypeName(name)
resolved <- resolveType(formattedName, protocolElems)
.flatMap {
case RandomType(name, tpe) =>
Resolved[L](tpe, None, None, ReifiedRawType.unsafeEmpty).pure[F]
case ClassDefinition(name, _, fullType, cls, _, _) =>
Resolved[L](fullType, None, None, ReifiedRawType.unsafeEmpty).pure[F]
case EnumDefinition(name, _, fullType, _, cls, _) =>
Resolved[L](fullType, None, None, ReifiedRawType.of(Some("string"), None)).pure[F]
case ADT(_, _, fullType, _, _) =>
Resolved[L](fullType, None, None, ReifiedRawType.unsafeEmpty).pure[F]
}
} yield resolved
case Left(DeferredArray(name, containerTpe)) =>
for {
formattedName <- formatTypeName(name)
resolved <- resolveType(formattedName, protocolElems)
.flatMap {
case RandomType(name, tpe) =>
liftVectorType(tpe, containerTpe).map(Resolved[L](_, None, None, VectorRawType(ReifiedRawType.unsafeEmpty)))
case ClassDefinition(name, _, fullType, cls, _, _) =>
liftVectorType(fullType, containerTpe).map(Resolved[L](_, None, None, VectorRawType(ReifiedRawType.unsafeEmpty)))
case EnumDefinition(name, _, fullType, _, cls, _) =>
liftVectorType(fullType, containerTpe).map(Resolved[L](_, None, None, VectorRawType(ReifiedRawType.unsafeEmpty)))
case ADT(_, _, fullType, _, _) =>
liftVectorType(fullType, containerTpe).map(Resolved[L](_, None, None, VectorRawType(ReifiedRawType.unsafeEmpty)))
}
} yield resolved
case Left(DeferredMap(name, containerTpe)) =>
for {
formattedName <- formatTypeName(name)
resolved <- resolveType(formattedName, protocolElems)
.flatMap {
case RandomType(name, tpe) =>
liftMapType(tpe, containerTpe).map(Resolved[L](_, None, None, MapRawType(ReifiedRawType.unsafeEmpty)))
case ClassDefinition(_, _, fullType, _, _, _) =>
liftMapType(fullType, containerTpe).map(Resolved[L](_, None, None, MapRawType(ReifiedRawType.unsafeEmpty)))
case EnumDefinition(_, _, fullType, _, _, _) =>
liftMapType(fullType, containerTpe).map(Resolved[L](_, None, None, MapRawType(ReifiedRawType.unsafeEmpty)))
case ADT(_, _, fullType, _, _) =>
liftMapType(fullType, containerTpe).map(Resolved[L](_, None, None, MapRawType(ReifiedRawType.unsafeEmpty)))
}
} yield resolved
}
} yield res
}
}
Loading

0 comments on commit 0416ad4

Please sign in to comment.