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

tethys.derivation.impl.builder.WriterBuilderCommons.scala Maven / Gradle / Ivy

package tethys.derivation.impl.builder

import tethys.derivation.builder.{WriterBuilder, WriterDerivationConfig, WriterDescription}

import scala.reflect.macros.blackbox

trait WriterBuilderCommons extends WriteBuilderUtils {
  val c: blackbox.Context
  import c.universe._

  protected def convertWriterBuilder[A: WeakTypeTag](builder: Expr[WriterBuilder[A]]): Expr[WriterDescription[A]] = {
    val description = extractSimpleDescription(builder.tree)
    checkOperations(description.operations)
    c.Expr[WriterDescription[A]] {
      c.untypecheck {
        q"$description"
      }
    }
  }

  protected lazy val emptyWriterConfig: Expr[WriterDerivationConfig] = c.Expr[WriterDerivationConfig](c.untypecheck(
    q"tethys.derivation.builder.WriterDerivationConfig.empty"
  ))

  private def extractSimpleDescription(tree: Tree): MacroWriteDescription = tree match {
    // ===== ROOT =====
    case q"WriterBuilder.apply[${tpe: Tree}]" =>
      MacroWriteDescription(tpe.tpe, emptyWriterConfig, Seq())

    case q"$_.WriterBuilder.apply[${tpe: Tree}]" =>
      MacroWriteDescription(tpe.tpe, emptyWriterConfig, Seq())

    // ===== remove =====
    case q"${rest: Tree}.remove[${tpe: Tree}](${f: BuilderField})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.Remove(description.tpe, f.name)
      )

    // ===== rename =====
    case q"${rest: Tree}.rename[${a: Tree}](${f: BuilderField})(${rename: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.Update(description.tpe, f.name, Some(c.Expr(rename)), q"identity[${a.tpe}]", a.tpe, a.tpe)
      )

    // ===== update =====
    case q"${rest: Tree}.update[${a: Tree}](${f: BuilderField}).apply[${b: Tree}](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.Update(description.tpe, f.name, None, updater, a.tpe, b.tpe)
      )

    // ===== update with rename =====
    case q"${rest: Tree}.update[${a: Tree}](${f: BuilderField}).withRename(${rename: Tree}).apply[${b: Tree}](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.Update(description.tpe, f.name, Some(c.Expr(rename)), updater, a.tpe, b.tpe)
      )

    // ===== update from root =====
    case q"${rest: Tree}.update[$_](${f: BuilderField}).fromRoot[${b: Tree}](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.UpdateFromRoot(description.tpe, f.name, None, updater, b.tpe)
      )

    // ===== update from root with rename =====
    case q"${rest: Tree}.update[$_](${f: BuilderField}).withRename(${rename: Tree}).fromRoot[${b: Tree}](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.UpdateFromRoot(description.tpe, f.name, Some(c.Expr(rename)), updater, b.tpe)
      )

    // ===== add =====
    case q"${rest: Tree}.add(${f: Tree}).apply[${a: Tree}](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.Add(description.tpe, c.Expr(f), updater, a.tpe)
      )

    // ===== update partial =====
    case q"${rest: Tree}.updatePartial[${a: Tree}](${f: BuilderField}).apply[$_](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.UpdatePartial(description.tpe, f.name, None, updater, a.tpe)
      )

    // ===== update partial with rename =====
    case q"${rest: Tree}.updatePartial[${a: Tree}](${f: BuilderField}).withRename(${rename: Tree}).apply[$_](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.UpdatePartial(description.tpe, f.name, Some(c.Expr(rename)), updater, a.tpe)
      )

    // ===== update partial from root =====
    case q"${rest: Tree}.updatePartial[${a: Tree}](${f: BuilderField}).fromRoot[$_](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.UpdatePartialFromRoot(description.tpe, f.name, None, updater)
      )

    // ===== update partial from root with rename =====
    case q"${rest: Tree}.updatePartial[${a: Tree}](${f: BuilderField}).withRename(${rename: Tree}).fromRoot[$_](${updater: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(operations = description.operations :+
        BuilderMacroOperation.UpdatePartialFromRoot(description.tpe, f.name, Some(c.Expr(rename)), updater)
      )

    // ===== FieldStyle =====
    case q"${rest: Tree}.fieldStyle(${style: Tree})" =>
      val description = extractSimpleDescription(rest)
      description.copy(config = c.Expr[WriterDerivationConfig](
        q"${description.config.tree}.withFieldStyle($style)"
      ))

    // ===== NOPE =====
    case _ => abort(s"unknown tree: ${show(tree)}")
  }

  private def checkOperations(operations: Seq[BuilderMacroOperation]): Unit = {
    //TODO
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy