Skip to content

Commit

Permalink
Clear compilation warnings (#3618)
Browse files Browse the repository at this point in the history
  • Loading branch information
kciesielski committed Mar 16, 2024
1 parent 1726333 commit ba35f6b
Show file tree
Hide file tree
Showing 19 changed files with 40 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ object TupleOps {
trait BinaryPolyFunc {
def at[A, B] = new CaseBuilder[A, B]
class CaseBuilder[A, B] {
def apply[R](f: (A, B) R) = new BinaryPolyFunc.Case[A, B, BinaryPolyFunc.this.type] {
def apply[R](f: (A, B) => R) = new BinaryPolyFunc.Case[A, B, BinaryPolyFunc.this.type] {
type Out = R
def apply(a: A, b: B) = f(a, b)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ trait SchemaMagnoliaDerivation {
}

override def split[T](ctx: SealedTrait[Schema, T]): Schema[T] = {
val annotations = mergeAnnotations(ctx.annotations, ctx.inheritedAnnotations)
withCache(ctx.typeInfo, ctx.annotations) {
val subtypesByName =
ctx.subtypes.toList
Expand Down
28 changes: 13 additions & 15 deletions core/src/main/scala-3/sttp/tapir/internal/AnnotationsMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package sttp.tapir.internal

import sttp.tapir._
import sttp.tapir.CodecFormat.TextPlain
import sttp.tapir.internal.{CaseClass, CaseClassField}
import sttp.tapir.typelevel.ParamConcat
import sttp.model.{QueryParams, Header, StatusCode}
import sttp.model.headers.{Cookie, CookieWithMeta, CookieValueWithMeta}

import scala.collection.mutable
import scala.quoted.*
import scala.deriving.Mirror

private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
import quotes.reflect.*
Expand Down Expand Up @@ -41,7 +39,7 @@ private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
inputIdxToFieldIdx += (inputIdxToFieldIdx.size -> idx)
wrapInput[f](field, makePathInput[f](field))
case None =>
report.throwError(s"${caseClass.name}.${fieldName} must have the @path annotation, as it is referenced from @endpointInput.")
report.errorAndAbort(s"${caseClass.name}.${fieldName} must have the @path annotation, as it is referenced from @endpointInput.")
}
} else {
makeFixedPath(segment)
Expand All @@ -51,7 +49,7 @@ private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
val (pathFields, nonPathFields) = fieldsWithIndex.partition((f, _) => f.annotated(pathAnnotationSymbol))

if (inputIdxToFieldIdx.size != pathFields.size) {
report.throwError(s"Not all fields of ${caseClass.name} annotated with @path are captured in the path in @endpointInput.")
report.errorAndAbort(s"Not all fields of ${caseClass.name} annotated with @path are captured in the path in @endpointInput.")
}

val nonPathInputs = nonPathFields.map { case (field, fieldIdx) =>
Expand All @@ -77,7 +75,7 @@ private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
.map(makeBasicAuthInput[f](field, field.annotation(securitySchemeNameAnnotationSymbol), _))
)
.getOrElse {
report.throwError(
report.errorAndAbort(
s"All fields of ${caseClass.name} must be annotated with one of the annotations from sttp.tapir.annotations. No annotations for field: ${field.name}."
)
}
Expand Down Expand Up @@ -125,7 +123,7 @@ private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
.orElse(if (field.annotated(cookiesAnnotationSymbol)) Some(makeCookiesIO[f](field)) else None)
.orElse(if (field.annotated(setCookiesAnnotationSymbol)) Some(makeSetCookiesOutput[f](field)) else None)
.getOrElse {
report.throwError(
report.errorAndAbort(
s"All fields of ${caseClass.name} must be annotated with one of the annotations from sttp.tapir.annotations. No annotations for field: ${field.name}."
)
}
Expand Down Expand Up @@ -190,14 +188,14 @@ private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
// util
private def summonCodec[L: Type, H: Type, CF <: CodecFormat: Type](field: CaseClassField[q.type, T]): Expr[Codec[L, H, CF]] =
Expr.summon[Codec[L, H, CF]].getOrElse {
report.throwError(
report.errorAndAbort(
s"Cannot summon codec from: ${Type.show[L]}, to: ${Type.show[H]}, formatted as: ${Type.show[CF]}, for field: ${field.name}."
)
}

private def summonMultipartCodec[H: Type](field: CaseClassField[q.type, T]): Expr[MultipartCodec[H]] =
Expr.summon[MultipartCodec[H]].getOrElse {
report.throwError(
report.errorAndAbort(
s"Cannot summon multipart codec for type: ${Type.show[H]}, for field: ${field.name}."
)
}
Expand Down Expand Up @@ -245,20 +243,20 @@ private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
private def makeQueryParamsInput[f: Type](field: CaseClassField[q.type, T]): Expr[EndpointInput.Basic[f]] = {
summon[Type[f]] match {
case '[QueryParams] => '{ queryParams.asInstanceOf[EndpointInput.Basic[f]] }
case _ => report.throwError(annotationErrorMsg[f, QueryParams]("@params", field))
case _ => report.errorAndAbort(annotationErrorMsg[f, QueryParams]("@params", field))
}
}

private def makeHeadersIO[f: Type](field: CaseClassField[q.type, T]): Expr[EndpointIO.Basic[f]] =
summon[Type[f]] match {
case '[List[Header]] => '{ headers.asInstanceOf[EndpointIO.Basic[f]] }
case _ => report.throwError(annotationErrorMsg[f, List[Header]]("@headers", field))
case _ => report.errorAndAbort(annotationErrorMsg[f, List[Header]]("@headers", field))
}

private def makeCookiesIO[f: Type](field: CaseClassField[q.type, T]): Expr[EndpointIO.Basic[f]] =
summon[Type[f]] match {
case '[List[Cookie]] => '{ cookies.asInstanceOf[EndpointIO.Basic[f]] }
case _ => report.throwError(annotationErrorMsg[f, List[Cookie]]("@cookies", field))
case _ => report.errorAndAbort(annotationErrorMsg[f, List[Cookie]]("@cookies", field))
}

private def makePathInput[f: Type](field: CaseClassField[q.type, T]): Expr[EndpointInput.Basic[f]] = {
Expand All @@ -271,22 +269,22 @@ private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
private def makeStatusCodeOutput[f: Type](field: CaseClassField[q.type, T]): Expr[EndpointOutput.Basic[f]] = {
summon[Type[f]] match {
case '[StatusCode] => '{ statusCode.asInstanceOf[EndpointOutput.Basic[f]] }
case _ => report.throwError(annotationErrorMsg[f, StatusCode]("@statusCode", field))
case _ => report.errorAndAbort(annotationErrorMsg[f, StatusCode]("@statusCode", field))
}
}

private def makeSetCookieOutput[f: Type](field: CaseClassField[q.type, T])(altName: Option[String]): Expr[EndpointOutput.Basic[f]] = {
val name = Expr(altName.getOrElse(field.name))
summon[Type[f]] match {
case '[CookieValueWithMeta] => '{ setCookie($name).asInstanceOf[EndpointOutput.Basic[f]] }
case _ => report.throwError(annotationErrorMsg[f, CookieValueWithMeta]("@setCookie", field))
case _ => report.errorAndAbort(annotationErrorMsg[f, CookieValueWithMeta]("@setCookie", field))
}
}

private def makeSetCookiesOutput[f: Type](field: CaseClassField[q.type, T]): Expr[EndpointOutput.Basic[f]] = {
summon[Type[f]] match {
case '[List[CookieWithMeta]] => '{ setCookies.asInstanceOf[EndpointOutput.Basic[f]] }
case _ => report.throwError(annotationErrorMsg[f, List[CookieWithMeta]]("@setCookies", field))
case _ => report.errorAndAbort(annotationErrorMsg[f, List[CookieWithMeta]]("@setCookies", field))
}
}

Expand Down Expand Up @@ -420,7 +418,7 @@ private[tapir] class AnnotationsMacros[T <: Product: Type](using q: Quotes) {
case '[EndpointTransput.Atom[`f`]] =>
'{ $f($transput.asInstanceOf[EndpointTransput.Atom[f]]).asInstanceOf[EndpointTransput.Atom[f]] }
case t =>
report.throwError(
report.errorAndAbort(
s"Schema metadata can only be added to basic inputs/outputs, but got: ${Type.show(using t)}, on field: ${field.name}"
)
}
Expand Down
12 changes: 6 additions & 6 deletions core/src/main/scala-3/sttp/tapir/internal/CaseClass.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ private[tapir] class CaseClass[Q <: Quotes, T: Type](using val q: Q) {
val symbol = tpe.typeSymbol

if !symbol.flags.is(Flags.Case) then
report.throwError(s"CaseClass can be instantiated only for case classes, but got: ${summon[Type[T]]}")
report.errorAndAbort(s"CaseClass can be instantiated only for case classes, but got: ${summon[Type[T]]}")

def name = symbol.name

Expand Down Expand Up @@ -51,7 +51,7 @@ private[tapir] class CaseClass[Q <: Quotes, T: Type](using val q: Q) {
symbol.getAnnotation(annSymbol).map {
case Apply(_, List(Select(_, "$lessinit$greater$default$1"))) => None
case Apply(_, List(Literal(c: Constant))) if c.value.isInstanceOf[String] => Some(c.value.asInstanceOf[String])
case _ => report.throwError(s"Cannot extract annotation: @${annSymbol.name}, from class: ${symbol.name}")
case _ => report.errorAndAbort(s"Cannot extract annotation: @${annSymbol.name}, from class: ${symbol.name}")
}
}
}
Expand All @@ -70,26 +70,26 @@ private[tapir] class CaseClassField[Q <: Quotes, T](using val q: Q, t: Type[T])(
/** Extracts an argument from an annotation with a single string-valued argument. */
def extractStringArgFromAnnotation(annSymbol: Symbol): Option[String] = constructorField.getAnnotation(annSymbol).map {
case Apply(_, List(Literal(c: Constant))) if c.value.isInstanceOf[String] => c.value.asInstanceOf[String]
case _ => report.throwError(s"Cannot extract annotation: @${annSymbol.name}, from field: ${symbol.name}, of type: ${Type.show[T]}")
case _ => report.errorAndAbort(s"Cannot extract annotation: @${annSymbol.name}, from field: ${symbol.name}, of type: ${Type.show[T]}")
}

/** Extracts an optional argument from an annotation with a single string-valued argument with a default value. */
def extractOptStringArgFromAnnotation(annSymbol: Symbol): Option[Option[String]] = {
constructorField.getAnnotation(annSymbol).map {
case Apply(_, List(Select(_, "$lessinit$greater$default$1"))) => None
case Apply(_, List(Literal(c: Constant))) if c.value.isInstanceOf[String] => Some(c.value.asInstanceOf[String])
case _ => report.throwError(s"Cannot extract annotation: @${annSymbol.name}, from field: ${symbol.name}, of type: ${Type.show[T]}")
case _ => report.errorAndAbort(s"Cannot extract annotation: @${annSymbol.name}, from field: ${symbol.name}, of type: ${Type.show[T]}")
}
}

def extractTreeFromAnnotation(annSymbol: Symbol): Option[Tree] = constructorField.getAnnotation(annSymbol).map {
case Apply(_, List(t)) => t
case _ => report.throwError(s"Cannot extract annotation: @${annSymbol.name}, from field: ${symbol.name}, of type: ${Type.show[T]}")
case _ => report.errorAndAbort(s"Cannot extract annotation: @${annSymbol.name}, from field: ${symbol.name}, of type: ${Type.show[T]}")
}

def extractFirstTreeArgFromAnnotation(annSymbol: Symbol): Option[Tree] = constructorField.getAnnotation(annSymbol).map {
case Apply(_, List(t, _*)) => t
case _ => report.throwError(s"Cannot extract annotation: @${annSymbol.name}, from field: ${symbol.name}, of type: ${Type.show[T]}")
case _ => report.errorAndAbort(s"Cannot extract annotation: @${annSymbol.name}, from field: ${symbol.name}, of type: ${Type.show[T]}")
}

def annotated(annSymbol: Symbol): Boolean = annotation(annSymbol).isDefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@ package sttp.tapir.internal

import scala.quoted.*

import scala.deriving.Mirror

private[tapir] object ComplietimeErrors {
inline def reportIncorrectMapping[SOURCE, TARGET] = ${ reportIncorrectMappingImpl[SOURCE, TARGET] }

private def reportIncorrectMappingImpl[SOURCE: Type, TARGET: Type](using Quotes): Expr[Unit] = {
import quotes.reflect.*

if TypeRepr.of[TARGET].typeSymbol.declaredFields.size > 22 then
report.throwError(
report.errorAndAbort(
s"Cannot map to ${Type.show[TARGET]}: arities of up to 22 are supported. If you need more inputs/outputs, map them to classes with less fields, and then combine these classes."
)
else report.throwError(s"Failed to map ${Type.show[SOURCE]} into ${Type.show[TARGET]}")
else report.errorAndAbort(s"Failed to map ${Type.show[SOURCE]} into ${Type.show[TARGET]}")
}

}
3 changes: 1 addition & 2 deletions core/src/main/scala-3/sttp/tapir/macros/CodecMacros.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package sttp.tapir.macros

import sttp.tapir.Codec.PlainCodec
import sttp.tapir.CodecFormat.TextPlain
import sttp.tapir.{Codec, DecodeResult, Schema, SchemaAnnotations, Validator}
import sttp.tapir.{Codec, SchemaAnnotations, Validator}
import sttp.tapir.internal.CodecValueClassMacro

trait CodecMacros {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import sttp.tapir.EndpointInput
import sttp.tapir.internal.AnnotationsMacros

import scala.quoted.*
import scala.deriving.Mirror

trait EndpointInputMacros {

Expand Down
3 changes: 1 addition & 2 deletions core/src/main/scala-3/sttp/tapir/macros/EndpointMacros.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package sttp.tapir.macros

import sttp.tapir.{EndpointErrorOutputsOps, EndpointSecurityInputsOps, EndpointInputsOps, EndpointOutputsOps, EndpointTransput, Mapping}
import sttp.tapir.{EndpointErrorOutputsOps, EndpointSecurityInputsOps, EndpointInputsOps, EndpointOutputsOps}
import sttp.tapir.internal.MappingMacros

import scala.compiletime.erasedValue
import scala.deriving.Mirror

trait EndpointSecurityInputsMacros[A, I, E, O, -R] { this: EndpointSecurityInputsOps[A, I, E, O, R] =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import sttp.tapir.EndpointOutput
import sttp.tapir.internal.AnnotationsMacros

import scala.quoted.*
import scala.deriving.Mirror

trait EndpointOutputMacros {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package sttp.tapir.macros
import sttp.tapir.EndpointTransput
import sttp.tapir.internal.MappingMacros

import scala.compiletime.erasedValue
import scala.deriving.Mirror

trait EndpointTransputMacros[T] { this: EndpointTransput[T] =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package sttp.tapir.macros

import sttp.model.StatusCode
import sttp.tapir.EndpointOutput.OneOfVariant
import sttp.tapir.{EndpointOutput, Tapir}
import sttp.tapir.typelevel.ErasureSameAsType

import scala.quoted.*
Expand All @@ -13,7 +10,6 @@ trait ErasureSameAsTypeMacros {

private[tapir] object ErasureSameAsTypeMacros {
def instanceImpl[T: Type](using Quotes): Expr[ErasureSameAsType[T]] = {
import quotes.reflect._
mustBeEqualToItsErasure[T]
'{ new ErasureSameAsType[T] {} }
}
Expand All @@ -31,7 +27,7 @@ private[tapir] object ErasureSameAsTypeMacros {
}

if (!isAllowed(t)) {
report.throwError(
report.errorAndAbort(
s"Type ${t.show}, $t is not the same as its erasure. Using a runtime-class-based check it won't be possible to verify " +
s"that the input matches the desired type. Use other methods to match the input to the appropriate variant " +
s"instead."
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala-3/sttp/tapir/macros/FormCodecMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private[tapir] object FormCodecMacros {
val encodedNameAnnotationSymbol = TypeTree.of[Schema.annotations.encodedName].tpe.typeSymbol

def summonCodec[f: Type](field: CaseClassField[q.type, T]) = Expr.summon[Codec[List[String], f, CodecFormat.TextPlain]].getOrElse {
report.throwError(s"Cannot find Codec[List[String], T, CodecFormat.TextPlain]] for field: ${field}, of type: ${field.tpe}")
report.errorAndAbort(s"Cannot find Codec[List[String], T, CodecFormat.TextPlain]] for field: ${field}, of type: ${field.tpe}")
}

def encodeDefBody(tTerm: Term): Term = {
Expand Down Expand Up @@ -95,7 +95,7 @@ private[tapir] object FormCodecMacros {
'{
Codec.formSeqUtf8
.mapDecode($decodeExpr)($encodeExpr)
.schema(${ Expr.summon[Schema[T]].getOrElse(report.throwError(s"Cannot find a given Schema[${Type.show[T]}].")) })
.schema(${ Expr.summon[Schema[T]].getOrElse(report.errorAndAbort(s"Cannot find a given Schema[${Type.show[T]}].")) })
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package sttp.tapir.macros

import scala.annotation.compileTimeOnly
import scala.annotation.nowarn
import scala.collection.Factory

trait ModifyMacroSupport extends ModifyMacroFunctorSupport {
Expand All @@ -10,7 +10,7 @@ trait ModifyMacroSupport extends ModifyMacroFunctorSupport {
): ModifyFunctor[F, A] =
new ModifyFunctor[F, A] {}

implicit class ModifyEachMap[F[_, _], K, T](t: F[K, T])(implicit fac: Factory[(K, T), F[K, T]]) {
implicit class ModifyEachMap[F[_, _], K, T](t: F[K, T])(implicit @nowarn fac: Factory[(K, T), F[K, T]]) {
// @compileTimeOnly(canOnlyBeUsedInsideModify("each")) TODO
def each: T = sys.error("")
}
Expand Down
13 changes: 3 additions & 10 deletions core/src/main/scala-3/sttp/tapir/macros/MultipartCodecMacros.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package sttp.tapir.macros

import sttp.tapir.{AnyPart, Codec, CodecFormat, DecodeResult, FileRange, MultipartCodec, PartCodec, RawBodyType, Schema}
import sttp.tapir.{Codec, CodecFormat, FileRange, MultipartCodec, PartCodec, RawBodyType, Schema}
import sttp.tapir.generic.Configuration
import sttp.tapir.internal.{CaseClass, CaseClassField}
import sttp.model.Part
Expand Down Expand Up @@ -44,7 +44,7 @@ private[tapir] object MultipartCodecMacros {
@tailrec
def firstNotEmpty(c: List[() => Option[Expr[PartCodec[_, _]]]]): Expr[PartCodec[_, _]] = c match {
case Nil =>
report.throwError(s"Cannot find a codec between a List[Part[T]] for some basic type T and: ${field.tpe}")
report.errorAndAbort(s"Cannot find a codec between a List[Part[T]] for some basic type T and: ${field.tpe}")
case h :: t =>
h() match {
case None => firstNotEmpty(t)
Expand All @@ -71,13 +71,6 @@ private[tapir] object MultipartCodecMacros {
'{ ListMap(${ Varargs(partCodecPairs) }: _*) }
}

def termMethodByNameUnsafe(term: Term, name: String): Symbol = term.tpe.typeSymbol.memberMethod(name).head

def getter(term: Term, name: String, skipArgList: Boolean = false): Term = {
val base = term.select(termMethodByNameUnsafe(term, name))
if (skipArgList) base else base.appliedToNone
}

def encodeDefBody(tTerm: Term): Term = {
val fieldsEncode = caseClass.fields.map { field =>
val fieldValue = field.tpe.asType match
Expand Down Expand Up @@ -135,7 +128,7 @@ private[tapir] object MultipartCodecMacros {
Codec
.multipart($partCodecs, None)
.map($decodeExpr)($encodeExpr)
.schema(${ Expr.summon[Schema[T]].getOrElse(report.throwError(s"Cannot find a given Schema[${Type.show[T]}].")) })
.schema(${ Expr.summon[Schema[T]].getOrElse(report.errorAndAbort(s"Cannot find a given Schema[${Type.show[T]}].")) })
}
}
}
Loading

0 comments on commit ba35f6b

Please sign in to comment.