All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pipez.internal.PlatformAnyValCaseGeneration.scala Maven / Gradle / Ivy

There is a newer version: 0.5.1
Show newest version
package pipez.internal

import pipez.internal.Definitions.{ Context, Result }

import scala.annotation.nowarn
import scala.util.chaining.*
import scala.language.existentials

private[internal] trait PlatformAnyValCaseGeneration[Pipe[_, _], In, Out] extends AnyValCaseGeneration[Pipe, In, Out] {
  self: PlatformDefinitions[Pipe, In, Out] & PlatformGenerators[Pipe, In, Out] =>

  import c.universe.*

  final def isAnyVal[A: Type]: Boolean =
    isSubtype[A, AnyVal]

  final def isPrimitive[A: Type]: Boolean =
    isSubtype[A, Boolean] || isSubtype[A, Byte] || isSubtype[A, Char] || isSubtype[A, Int] || isSubtype[A, Long] ||
      isSubtype[A, Short] || isSubtype[A, Double] || isSubtype[A, Float] || isSubtype[A, String]

  final def extractAnyValInData(settings: Settings): DerivationResult[AnyValInData[AnyValType]] =
    if (isAnyVal[In])
      DerivationResult.fromOption(
        In.decls
          .to(List)
          .filterNot(isGarbage)
          .filter(field => field.isMethod && field.asMethod.isGetter)
          .headOption
          .map { getter =>
            val name     = getter.name.toString
            val termName = getter.asMethod.name.toTermName
            AnyValInData.InAnyVal(
              tpe = returnTypeOf(In, getter).asInstanceOf[Type[AnyValType]],
              get =
                if (getter.asMethod.paramLists.isEmpty) (in: Expr[In]) => c.Expr[AnyValType](q"$in.$termName")
                else (in: Expr[In]) => c.Expr[AnyValType](q"$in.$termName()"),
              path = Path.Field(Path.Root, name)
            )
          }
      )(DerivationError.InvalidInput("Couldn't found a valid getter to extract value from AnyVal"))
    else
      DerivationResult.pure(AnyValInData.InPrimitive(typeOf[In].asInstanceOf[Type[AnyValType]]))

  final def extractAnyValOutData(settings: Settings): DerivationResult[AnyValOutData[AnyValType]] =
    if (isAnyVal[Out])
      DerivationResult
        .fromOption(
          Out.decls
            .to(List)
            .filterNot(isGarbage)
            .find(m => m.isPublic && m.isConstructor && m.asMethod.paramLists.flatten.size == 1)
        )(DerivationError.MissingPublicConstructor)
        .map { primaryConstructor =>
          val arg = primaryConstructor.asMethod.paramLists.flatten.head
          AnyValOutData.OutAnyVal(
            tpe = arg.typeSignature.asInstanceOf[Type[AnyValType]],
            put = (value: Expr[AnyValType]) => c.Expr[Out](q"new $Out($value)")
          )
        }
    else
      DerivationResult.pure(AnyValOutData.OutPrimitive(typeOf[Out].asInstanceOf[Type[AnyValType]]))

  final def generateAnyValCode(generatorData: AnyValGeneratorData): DerivationResult[Expr[Pipe[In, Out]]] = {
    val in = c.freshName(TermName("in"))
    DerivationResult.pure(
      lift[In, Out](c.Expr(q"""($in: $In, _: $Context) => ${pureResult(generatorData.repack(c.Expr(q"$in")))}"""))
    )
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy