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

org.scalameta.annotations.quasiquote.scala Maven / Gradle / Ivy

The newest version!
package org.scalameta.annotations

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

class quasiquote[T](qname: scala.Symbol) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro QuasiquoteMacros.impl
}

class QuasiquoteMacros(val c: Context) {
  import c.universe._
  import Flag._
  def impl(annottees: c.Tree*): c.Tree = {
    val q"new $_[$qtype](scala.Symbol(${qname: String})).macroTransform(..$_)" = c.macroApplication
    def transform(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
      if (stats.nonEmpty) c.abort(cdef.pos, "@quasiquote classes must have empty bodies")
      val qmodule = q"""
        object ${TermName(qname)} {
          import scala.language.experimental.macros
          def apply[T](args: T*): _root_.scala.meta.Tree = macro $mname.applyImpl
          def unapply(scrutinee: Any): $qtype = macro ???
        }
      """
      val qparser = TermName("parse" + qname.capitalize)
      val q"..$applyimpls" = q"""
        import scala.reflect.macros.whitebox.Context
        def applyImpl(c: Context)(args: c.Tree*): c.Tree = {
          import _root_.scala.meta.syntactic.parsers.RichOrigin
          val helper = new _root_.scala.meta.syntactic.quasiquotes.Macros[c.type](c)
          helper.apply(c.macroApplication, (s: String) => s.parse[$qtype])
        }
      """
      val cdef1 = q"$mods class $name[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..${qmodule +: stats} }"
      val mdef1 = q"$mmods object $mname extends { ..$mearlydefns } with ..$mparents { $mself => ..${mstats ++ applyimpls} }"
      List(cdef1, mdef1)
    }
    val expanded = annottees match {
      case (cdef: ClassDef) :: (mdef: ModuleDef) :: rest if cdef.mods.hasFlag(IMPLICIT) => transform(cdef, mdef) ++ rest
      case (cdef: ClassDef) :: rest if cdef.mods.hasFlag(IMPLICIT) => transform(cdef, q"object ${cdef.name.toTermName}") ++ rest
      case annottee :: rest => c.abort(annottee.pos, "only implicit classes can be @quasiquote")
    }
    q"{ ..$expanded; () }"
  }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy