-
Notifications
You must be signed in to change notification settings - Fork 421
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement support for iron types (#3038)
- Loading branch information
Showing
10 changed files
with
629 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
core/src/main/scala-3/sttp/tapir/typelevel/IntersectionTypeMirror.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package sttp.tapir.typelevel | ||
import scala.quoted.Quotes | ||
|
||
import scala.annotation.implicitNotFound | ||
import scala.quoted.* | ||
import scala.collection.View.Empty | ||
|
||
trait IntersectionTypeMirror[A] { | ||
|
||
type ElementTypes <: Tuple | ||
} | ||
|
||
// Building a class is more convenient to instantiate using macros | ||
class IntersectionTypeMirrorImpl[A, T <: Tuple] extends IntersectionTypeMirror[A] { | ||
override type ElementTypes = T | ||
} | ||
|
||
object IntersectionTypeMirror { | ||
|
||
transparent inline given derived[A]: IntersectionTypeMirror[A] = ${ derivedImpl[A] } | ||
|
||
private def derivedImpl[A](using Quotes, Type[A]): Expr[IntersectionTypeMirror[A]] = { | ||
import quotes.reflect.* | ||
|
||
val tplPrependType = TypeRepr.of[? *: ?] | ||
val tplConcatType = TypeRepr.of[Tuple.Concat] | ||
|
||
def prependTypes(head: TypeRepr, tail: TypeRepr): TypeRepr = | ||
AppliedType(tplPrependType, List(head, tail)) | ||
|
||
def concatTypes(left: TypeRepr, right: TypeRepr): TypeRepr = | ||
AppliedType(tplConcatType, List(left, right)) | ||
|
||
def rec(tpe: TypeRepr): TypeRepr = { | ||
tpe.dealias match | ||
case AndType(left, right) => concatTypes(rec(left), rec(right)) | ||
case t => prependTypes(t, TypeRepr.of[EmptyTuple]) | ||
} | ||
val tupled = | ||
TypeRepr.of[A].dealias match { | ||
case and: AndType => rec(and).asType.asInstanceOf[Type[Elems]] | ||
case tpe => report.errorAndAbort(s"${tpe.show} is not an intersection type") | ||
} | ||
type Elems | ||
|
||
given Type[Elems] = tupled | ||
|
||
Apply( // Passing the type using quotations causes the type to not be inlined | ||
TypeApply( | ||
Select.unique( | ||
New( | ||
Applied( | ||
TypeTree.of[IntersectionTypeMirrorImpl], | ||
List( | ||
TypeTree.of[A], | ||
TypeTree.of[Elems] | ||
) | ||
) | ||
), | ||
"<init>" | ||
), | ||
List( | ||
TypeTree.of[A], | ||
TypeTree.of[Elems] | ||
) | ||
), | ||
Nil | ||
).asExprOf[IntersectionTypeMirror[A]] | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
core/src/main/scala-3/sttp/tapir/typelevel/UnionTypeMirror.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package sttp.tapir.typelevel | ||
|
||
import scala.quoted.Quotes | ||
|
||
import scala.annotation.implicitNotFound | ||
import scala.quoted.* | ||
import scala.collection.View.Empty | ||
|
||
trait UnionTypeMirror[A] { | ||
|
||
type ElementTypes <: Tuple | ||
} | ||
|
||
// Building a class is more convenient to instantiate using macros | ||
class UnionTypeMirrorImpl[A, T <: Tuple] extends UnionTypeMirror[A] { | ||
|
||
override type ElementTypes = T | ||
} | ||
|
||
object UnionTypeMirror { | ||
transparent inline given derived[A]: UnionTypeMirror[A] = ${ derivedImpl[A] } | ||
|
||
private def derivedImpl[A](using Quotes, Type[A]): Expr[UnionTypeMirror[A]] = { | ||
import quotes.reflect.* | ||
|
||
val tplPrependType = TypeRepr.of[? *: ?] | ||
val tplConcatType = TypeRepr.of[Tuple.Concat] | ||
|
||
def prependTypes(head: TypeRepr, tail: TypeRepr): TypeRepr = | ||
AppliedType(tplPrependType, List(head, tail)) | ||
|
||
def concatTypes(left: TypeRepr, right: TypeRepr): TypeRepr = | ||
AppliedType(tplConcatType, List(left, right)) | ||
|
||
def rec(tpe: TypeRepr): TypeRepr = | ||
tpe.dealias match { | ||
case OrType(left, right) => concatTypes(rec(left), rec(right)) | ||
case t => prependTypes(t, TypeRepr.of[EmptyTuple]) | ||
} | ||
val tupled = | ||
TypeRepr.of[A].dealias match { | ||
case or: OrType => rec(or).asType.asInstanceOf[Type[Elems]] | ||
case tpe => report.errorAndAbort(s"${tpe.show} is not a union type") | ||
} | ||
|
||
type Elems | ||
|
||
given Type[Elems] = tupled | ||
|
||
Apply( // Passing the type using quotations causes the type to not be inlined | ||
TypeApply( | ||
Select.unique( | ||
New( | ||
Applied( | ||
TypeTree.of[UnionTypeMirrorImpl], | ||
List( | ||
TypeTree.of[A], | ||
TypeTree.of[Elems] | ||
) | ||
) | ||
), | ||
"<init>" | ||
), | ||
List( | ||
TypeTree.of[A], | ||
TypeTree.of[Elems] | ||
) | ||
), | ||
Nil | ||
).asExprOf[UnionTypeMirror[A]] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.