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

scala.pickling.generator.Macros.scala Maven / Gradle / Ivy

package scala.pickling
package generator

private[pickling] object PicklingMacros {
  import scala.language.experimental.macros
  def genPickler[T]: Pickler[T] with Generated = macro scala.pickling.generator.Compat.genPickler_impl[T]
  def genUnpickler[T]: Unpickler[T] with Generated = macro scala.pickling.generator.Compat.genUnpickler_impl[T]
  def genPicklerUnpickler[T]: AbstractPicklerUnpickler[T] with Generated = macro scala.pickling.generator.Compat.genPicklerUnpickler_impl[T]
}
private[pickling] trait PicklingMacros extends Macro with SourceGenerator with TypeAnalysis {
  import c.universe._
  val symbols = new IrScalaSymbols[c.universe.type, c.type](c.universe, tools)
  // TODO - We should have more customization than this
  val handleCaseClassSubclasses = !configOption(typeOf[IsIgnoreCaseClassSubclasses])
  val generator =
    if(isStaticOnly) {
      PicklingAlgorithm.aggregate(Seq(
        new CaseClassPickling(allowReflection = false, careAboutSubclasses = handleCaseClassSubclasses),
        AdtPickling,
        ScalaSingleton))
    } else {
      PicklingAlgorithm.aggregate(Seq(
        new CaseClassPickling(allowReflection = true, careAboutSubclasses = handleCaseClassSubclasses),
        AdtPickling,
        ScalaSingleton,
        new ExternalizablePickling,
        WillRobinsonPickling))
    }

  object logger extends AlgorithmLogger {
    def warn(msg: String): Unit = c.warning(c.enclosingPosition, msg)
    def debug(msg: String): Unit =
    // These are enabled when -verbose is enabled.
      c.info(c.enclosingPosition, msg, force=false)
    def abort(msg: String): Nothing = c.abort(c.enclosingPosition, msg)
    def error(msg: String): Unit = c.error(c.enclosingPosition, msg)
  }

  def checkClassType(tpe: c.Type, isUnpickle: Boolean = true): Unit = {
    import definitions._
    tpe.normalize match {
      case NothingTpe =>
        c.abort(c.enclosingPosition, "cannot generate pickling logic for type Nothing")
      case RefinedType(parents, decls) =>
        c.abort(c.enclosingPosition, "cannot generate pickling logic for refined type")
      case _ if tpe.isEffectivelyPrimitive || tpe.typeSymbol == StringClass =>
        c.abort(c.enclosingPosition, s"cannot generate pickling logic for primitive type: $tpe")
      case tpe1 if tpe1.typeSymbol.isClass =>
        ()  // This case is fine.
      case _ =>
        c.abort(c.enclosingPosition, s"cannot generate pickling logic for non-class type $tpe")
    }
  }

  def genPickler[T: c.WeakTypeTag]: c.Tree = preferringAlternativeImplicits {
    val tpe = computeType[T]
    checkClassType(tpe)
    val sym = symbols.newClass(tpe)
    val impl = PicklingAlgorithm.run(generator)(sym, logger)
    val tree2 = impl map {
      case PickleUnpickleImplementation(alg2, alg) => generatePicklerClass[T](alg2)
    }
    tree2 match {
      case None =>
        c.error(c.enclosingPosition, s"Failed to generate pickler for $tpe")
        ???
      case Some(tree) =>
        //System.err.println(s" --=== $tpe ===--\n$tree\n --=== / $tpe ===--")
        tree
    }
  }
  def genUnPickler[T: c.WeakTypeTag]: c.Tree = preferringAlternativeImplicits {
    val tpe = computeType[T]
    checkClassType(tpe)
    val sym = symbols.newClass(tpe)
    val impl = PicklingAlgorithm.run(generator)(sym, logger)
    val tree2 = impl map {
      case PickleUnpickleImplementation(alg2, alg) => generateUnpicklerClass[T](alg)
    }
    tree2 match {
      case None =>
        c.error(c.enclosingPosition, s"Failed to generate unpickler for $tpe")
        ???
      case Some(tree) =>
        //System.err.println(s" --=== $tpe ===--\n$tree\n --=== / $tpe ===--")
        tree
    }
  }
  def genPicklerUnpickler[T: c.WeakTypeTag]: c.Tree = preferringAlternativeImplicits {
    val tpe = computeType[T]
    checkClassType(tpe)
    val sym = symbols.newClass(tpe)
    val impl = PicklingAlgorithm.run(generator)(sym, logger)
    //System.err.println(impl)
    val tree2 = impl map generatePicklerUnpicklerClass[T]
    tree2 match {
      case None =>
        c.error(c.enclosingPosition, s"Failed to generate pickler/unpickler for $tpe")
        ???
      case Some(tree) =>
        //System.err.println(s" --=== $tpe ===--\n$tree\n --=== / $tpe ===--")
        tree
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy