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

org.scalameta.internal.ImplTransformers.scala Maven / Gradle / Ivy

Go to download

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

There is a newer version: 4.12.2
Show newest version
package org.scalameta
package internal

import scala.reflect.macros.blackbox.Context

trait ImplTransformers {
  val c: Context

  import c.universe.Flag._
  import c.universe._

  implicit class XtensionAnnotteeTransformer(annottees: Seq[Tree]) {
    def transformAnnottees(transformer: ImplTransformer): Tree = transformer.transform(annottees: _*)
  }

  class ImplTransformer {
    def transformClass(cdef: ClassDef, mdef: ModuleDef): List[ImplDef] = ???
    def transformTrait(cdef: ClassDef, mdef: ModuleDef): List[ImplDef] = ???
    def transformModule(mdef: ModuleDef): ModuleDef = ???

    def transform(annottees: Tree*): Tree = {
      def isImplemented(body: => Any): Boolean =
        try { body; true }
        catch { case _: NotImplementedError => false; case _: Throwable => true }
      val allowClasses = isImplemented(transformClass(null, null))
      val allowTraits = isImplemented(transformTrait(null, null))
      val allowModules = isImplemented(transformModule(null))
      if (!allowClasses && !allowTraits && !allowModules) sys.error("invalid ImplTransformer")

      def failUexpectedAnnottees() = {
        var allowed = List[String]()
        if (allowClasses) allowed :+= "classes"
        if (allowTraits) allowed :+= "traits"
        if (allowModules) allowed :+= "modules"
        val s_allowed =
          if (allowed.length > 1) allowed.dropRight(1).mkString(", ") + " and " + allowed.last
          else allowed.mkString
        val q"new $s_name(...$_).macroTransform(..$_)" = c.macroApplication
        c.abort(annottees.head.pos, s"only $s_allowed can be $s_name")
      }

      val expanded = annottees match {
        case (cdef @ ClassDef(mods, _, _, _)) :: (mdef: ModuleDef) :: rest =>
          if (!mods.hasFlag(TRAIT)) {
            if (!allowClasses) failUexpectedAnnottees()
            transformClass(cdef, mdef) ++ rest
          } else {
            if (!allowTraits) failUexpectedAnnottees()
            transformTrait(cdef, mdef) ++ rest
          }
        case (cdef @ ClassDef(mods, name, _, _)) :: rest =>
          val syntheticMdef = q"object ${name.toTermName}"
          if (!mods.hasFlag(TRAIT)) {
            if (!allowClasses) failUexpectedAnnottees()
            transformClass(cdef, syntheticMdef) ++ rest
          } else {
            if (!allowTraits) failUexpectedAnnottees()
            transformTrait(cdef, syntheticMdef) ++ rest
          }
        case (mdef @ ModuleDef(_, _, _)) :: rest =>
          if (!allowModules) failUexpectedAnnottees()
          transformModule(mdef) +: rest
        case annottee :: rest => failUexpectedAnnottees()
      }
      q"{ ..$expanded; () }"
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy