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

scala.meta.internal.trees.quasiquote.scala Maven / Gradle / Ivy

Go to download

Bag of private and public helpers used in scala.meta's APIs and implementations

The newest version!
package scala.meta
package internal
package trees

import org.scalameta.internal.MacroHelpers

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context

// Generates quasiquote definition boilerplate for a given interpolator
// and then injects it into the annottee.
// See usage examples in the `quasiquotes` project.
class quasiquote[T](qname: String) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro QuasiquoteMacros.impl
}

class QuasiquoteMacros(val c: Context) extends MacroHelpers {
  import c.universe._
  val ReificationMacros = q"_root_.scala.meta.internal.quasiquotes.ReificationMacros"
  def impl(annottees: c.Tree*): c.Tree = annottees.transformAnnottees(new ImplTransformer {
    val q"new $_[..$qtypes](${qname: String}).macroTransform(..$_)" = c.macroApplication
    override def transformClass(cdef: ClassDef, mdef: ModuleDef): List[ImplDef] = {
      val q"$mods class $name[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" =
        cdef
      val q"$mmods object $mname extends { ..$mearlydefns } with ..$mparents { $mself => ..$mstats }" =
        mdef
      val mmods1 = Modifiers(mmods.flags, TypeName("meta"), mmods.annotations)
      if (stats.nonEmpty) c.abort(cdef.pos, "@quasiquote classes must have empty bodies")
      val qmodule = {
        val qtypesLub = lub(qtypes.map(_.duplicate).map { qtype =>
          try c.typecheck(qtype, c.TYPEmode).tpe
          catch {
            case c.TypecheckException(pos, msg) => c.abort(pos.asInstanceOf[c.Position], msg)
          }
        })
        q"""
          object ${TermName(qname)} {
            import scala.language.experimental.macros
            def apply[T >: Any](args: T*)(implicit dialect: _root_.scala.meta.Dialect): $qtypesLub = macro $ReificationMacros.apply
            def unapply(scrutinee: Any)(implicit dialect: _root_.scala.meta.Dialect): Any = macro $ReificationMacros.unapply
          }
        """
      }
      val qparser = {
        val qmonadicResults = qtypes.map(qtype =>
          q"""
          type Parse[T] = _root_.scala.meta.parsers.Parse[T]
          val parse = _root_.scala.Predef.implicitly[Parse[$qtype]]
          parse(input, dialect)
        """
        )
        val qmonadicResult = qmonadicResults.reduce((acc, curr) => q"$acc.orElse($curr)")
        val qresult = q"""
          $qmonadicResult match {
            case x: _root_.scala.meta.parsers.Parsed.Success[_] => x.tree
            case x: _root_.scala.meta.parsers.Parsed.Error => throw x.details
          }
        """
        q"private[meta] def parse(input: _root_.scala.meta.inputs.Input, dialect: _root_.scala.meta.Dialect) = $qresult"
      }
      val stats1 = stats :+ qmodule
      val mstats1 = mstats :+ qparser
      val cdef1 =
        q"$mods class $name[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats1 }"
      val mdef1 =
        q"$mmods1 object $mname extends { ..$mearlydefns } with ..$mparents { $mself => ..$mstats1 }"
      List(cdef1, mdef1)
    }
  })
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy