scala.annotation.StaticAnnotation Scala Examples

The following examples show how to use scala.annotation.StaticAnnotation. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: Annotation.scala    From morpheus   with Apache License 2.0 6 votes vote down vote up
package org.opencypher.morpheus.impl.util

import org.opencypher.morpheus.api.io.{Labels, Node, Relationship, RelationshipType}

import scala.annotation.StaticAnnotation
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

private[morpheus] object Annotation {
  def labels[E <: Node: TypeTag]: Set[String] = synchronized {
    get[Labels, E] match {
      case Some(ls) => ls.labels.toSet
      case None     => Set(runtimeClass[E].getSimpleName)
    }
  }

  def relType[E <: Relationship: TypeTag]: String = synchronized {
    get[RelationshipType, E] match {
      case Some(RelationshipType(tpe)) => tpe
      case None                        => runtimeClass[E].getSimpleName.toUpperCase
    }
  }

  def get[A <: StaticAnnotation: TypeTag, E: TypeTag]: Option[A] = synchronized {
    val maybeAnnotation = staticClass[E].annotations.find(_.tree.tpe =:= typeOf[A])
    maybeAnnotation.map { annotation =>
      val tb = typeTag[E].mirror.mkToolBox()
      val instance = tb.eval(tb.untypecheck(annotation.tree)).asInstanceOf[A]
      instance
    }
  }

  private def runtimeClass[E: TypeTag]: Class[E] = synchronized {
    val tag = typeTag[E]
    val mirror = tag.mirror
    val runtimeClass = mirror.runtimeClass(tag.tpe.typeSymbol.asClass)
    runtimeClass.asInstanceOf[Class[E]]
  }

  private def staticClass[E: TypeTag]: ClassSymbol = synchronized {
    val mirror = typeTag[E].mirror
    mirror.staticClass(runtimeClass[E].getCanonicalName)
  }
} 
Example 2
Source File: autoProductNK.scala    From mainecoon   with Apache License 2.0 5 votes vote down vote up
package mainecoon

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.meta._
import autoProductNK._
import Util._

import collection.immutable.Seq


@compileTimeOnly("Cannot expand @autoProductK")
class autoProductNK extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    enrich(defn)(productKInst)
  }
}

object autoProductNK {
  private[mainecoon] def productKInst(cls: TypeDefinition): TypeDefinition = {
    import cls._

    def productMethod(arity: Int): Stat = {
      val range = (1 to arity).map(_.toString)

      // "F1, F2, F3"
      val effectTypeParamsNames = range.map(n => Type.Name("F" + n))

      //Tuple3K
      val productTypeName = Type.Name(s"_root_.mainecoon.Tuple${arity}K")

      val methods = templ.stats.map(_.map {
        case q"def $methodName[..$mTParams](..$params): $f[$resultType]" =>
          val returnItems = range.map { n =>
            q"${Term.Name("af" + n)}.$methodName(..${arguments(params)})"
          }
          q"""def $methodName[..$mTParams](..$params): $productTypeName[..$effectTypeParamsNames]#λ[$resultType] =
           (..$returnItems)"""
        //curried version
        case q"def $methodName[..$mTParams](..$params)(..$params2): $f[$resultType]" =>
          val returnItems = range.map { n =>
            q"${Term.Name("af" + n)}.$methodName(..${arguments(params)})(..${arguments(params2)})"
          }
          q"""def $methodName[..$mTParams](..$params)(..$params2): $productTypeName[..$effectTypeParamsNames]#λ[$resultType] =
           (..$returnItems)"""
        case st => abort(s"autoProductK does not support algebra with such statement: $st")
      }).getOrElse(Nil)

      // tparam"F1[_], F2[_], F3[_]"
      val effectTypeParams: Seq[Type.Param] = range.map(n => typeParam(s"F$n", 1))

      // param"af1: A[F1]"
      def inboundInterpreter(idx: String): Term.Param =
        Term.Param(Nil, Term.Name("af" + idx), Some(Type.Name(s"${name.value}[F"+idx + "]")), None)

      //af1: A[F1], af2: A[F2], af3: A[F3]
      val inboundInterpreters: Seq[Term.Param] = range.map(inboundInterpreter)

      q"""
        def ${Term.Name("product" + arity + "K")}[..$effectTypeParams](..$inboundInterpreters): $name[$productTypeName[..$effectTypeParamsNames]#λ] =
          new ${Ctor.Ref.Name(name.value)}[$productTypeName[..$effectTypeParamsNames]#λ] {
            ..$methods
          }
      """

    }

    val instanceDef = (3 to 9).map(productMethod)

    cls.copy(companion = cls.companion.addStats(instanceDef))
  }
} 
Example 3
Source File: Macros.scala    From seed   with Apache License 2.0 5 votes vote down vote up
import scala.reflect.macros.blackbox
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation

object helloMacro {
  def impl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    import Flag._
    val result = {
      annottees.map(_.tree).toList match {
        case q"object $name extends ..$parents { ..$body }" :: Nil =>
          q"""
            object $name extends ..$parents {
              def hello: ${typeOf[String]} = "hello"
              ..$body
            }
          """
      }
    }
    c.Expr[Any](result)
  }
}

class hello extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro helloMacro.impl
} 
Example 4
Source File: Quotation.scala    From quill   with Apache License 2.0 5 votes vote down vote up
package io.getquill.quotation

import scala.annotation.StaticAnnotation
import scala.reflect.ClassTag
import scala.reflect.macros.whitebox.Context

import io.getquill.ast._
import io.getquill.util.MacroContextExt._
import io.getquill.norm.BetaReduction
import io.getquill.util.EnableReflectiveCalls

case class QuotedAst(ast: Ast) extends StaticAnnotation

trait Quotation extends Liftables with Unliftables with Parsing with ReifyLiftings {
  val c: Context
  import c.universe._

  private val quoted = TermName("quoted")

  def quote[T](body: Tree)(implicit t: WeakTypeTag[T]) = {

    val ast = BetaReduction(astParser(body))

    val id = TermName(s"id${ast.hashCode.abs}")

    val (reifiedAst, liftings) = reifyLiftings(ast)

    val quotation =
      c.untypecheck {
        q"""
          new ${c.prefix}.Quoted[$t] {

            ..${EnableReflectiveCalls(c)}

            @${c.weakTypeOf[QuotedAst]}($reifiedAst)
            def $quoted = ast

            override def ast = $reifiedAst

            def $id() = ()

            $liftings
          }
        """
      }

    if (IsDynamic(ast)) {
      q"$quotation: ${c.prefix}.Quoted[$t]"
    } else {
      quotation
    }
  }

  def doubleQuote[T: WeakTypeTag](body: Expr[Any]) =
    body.tree match {
      case q"null" => c.fail("Can't quote null")
      case tree    => q"${c.prefix}.unquote($tree)"
    }

  def quotedFunctionBody(func: Expr[Any]) =
    func.tree match {
      case q"(..$p) => $b" => q"${c.prefix}.quote((..$p) => ${c.prefix}.unquote($b))"
    }

  protected def unquote[T](tree: Tree)(implicit ct: ClassTag[T]) =
    astTree(tree).flatMap(astUnliftable.unapply).map {
      case ast: T => ast
    }

  private def astTree(tree: Tree) =
    for {
      method <- tree.tpe.decls.find(_.name == quoted)
      annotation <- method.annotations.headOption
      astTree <- annotation.tree.children.lastOption
    } yield astTree
} 
Example 5
Source File: AliasWithLensSpec.scala    From Vegas   with MIT License 5 votes vote down vote up
package vegas.macros

import monocle.Lens
import monocle.macros.GenLens
import org.scalatest.{FlatSpec, Matchers}

import scala.annotation.StaticAnnotation


class AliasWithLensSpec extends FlatSpec with Matchers {

  class ignore_me extends StaticAnnotation
  case class Ex(a: Int)
  val _a = GenLens[Ex](_.a)

  @aliased
  trait Test {

    @alias_with_lens("fnA1", _a)
    private def fnA(a: Lens[Ex, Int])(b: Int, c: String) = (a, b, c)

    @ignore_me
    private def fnB(a: Lens[Ex, Int])(b: Int, c: String) = (a, b, c)

    @alias_with_lens("fnC1", _a)
    @ignore_me
    private def fnC(a: Lens[Ex, Int])(b: Int, c: String) = (a, b, c)
  }

  "alias_with_lens" should "alias the annotated method and partially apply it using the given lens" in {
    val t = new Test { }
    t.fnA1(1, "2") should equal((_a, 1, "2"))
  }

  it should "ignore other annotations" in {
    val t = new Test { }
    t.fnC1(1, "2") should equal((_a, 1, "2"))
  }
} 
Example 6
Source File: AliasWithLens.scala    From Vegas   with MIT License 5 votes vote down vote up
package vegas.macros

import language.experimental.macros
import scala.annotation.{ StaticAnnotation, compileTimeOnly }
import reflect.macros.blackbox.Context
import macrocompat.bundle
import monocle.Lens

class alias_with_lens(name: String, lens: Lens[_,_]) extends StaticAnnotation

@compileTimeOnly("You must enable the macro paradise plugin.")
class aliased extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro AliasMacros.lensAliasMacroImpl
}


@bundle
class AliasMacros(val c: Context) {
  import c.universe._

  def paramsToArgs(params: List[ValDef]): List[Tree] = {
    params.map { case q"$a val $param: $b = $c" => q"$param" }
  }

  def lensAliasMacroImpl(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    val result = annottees map (_.tree) match {

      // Match a trait
      case (traitDef @ q"$mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents { $self => ..$stats }") :: _ => {

        // Loop through all functions with aliases, and great new defs for each using given name and lens
        val aliasedDefs = for {
          q"@..$annots private def $tname[..$tparams](...$paramss): $tpt = $expr" <- stats
          annot <- annots
          Apply(Select(New(Ident(TypeName(aName))), _), annotArgs) = annot if (aName == "alias_with_lens")
        } yield {
          val List(Literal(Constant(name: String)), lens) = annotArgs
          val aliasIdent = TermName(name)
          val args = paramss.tail.map(paramsToArgs)
          q"def $aliasIdent[..$tparams](...${ paramss.tail }): $tpt = $tname(..$lens)(...$args)"
        }

        // Now rewrite trait with additional methods
        if(aliasedDefs.nonEmpty) {
          q"""
            $mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents { $self =>
              ..$stats
              ..$aliasedDefs
            }
          """
        } else traitDef

      }

      case _ => c.abort(c.enclosingPosition, "Invalid annotation target: not a trait")

    }

    c.Expr[Any](result)
  }

} 
Example 7
Source File: Expand.scala    From sansible   with MIT License 5 votes vote down vote up
package ansible

import ansible.AnsibleModule._
import argonaut.Argonaut._
import better.files._

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox

@compileTimeOnly("enable macro paradise to expand macro annotations")
class expand extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro Expander.expand_impl
}

object Expander {
  val tmpDir = System.getProperty("java.io.tmpdir")

  def expand_impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    val gen = new CodeGen(c)

    val files = (tmpDir / "parsed_modules").listRecursively.filter(_.extension.contains(".json")).toList
    val ansibleModules = files.map { f =>
      f.contentAsString.decodeValidation[AnsibleModule].fold(err =>
        throw new Exception(s"Failed reading the json representation of the Ansible module: ${f.path}, error: $err"),
        identity
      )
    }

    def generateModule(m: AnsibleModule): (ModuleDef, ClassDef) = {
      val moduleTypeName = TypeName(camelize(m.name))
      val moduleTermName = TermName(camelize(m.name))
      val sortedOptions  = m.options.sortBy(_.required)(Ordering[Boolean].reverse)

      val (enumTypes, enumValues, fields) =
        sortedOptions.foldLeft((List.empty[ClassDef], List.empty[ModuleDef], Vector.empty[ValDef])) { case ((enumTypes, enumValues, fields), option) =>
          option match {
            case o: BooleanOption =>
              (enumTypes, enumValues, fields :+ gen.boolVal(o).asInstanceOf[ValDef])
            case o: StringOption =>
              (enumTypes, enumValues, fields :+ gen.stringVal(o).asInstanceOf[ValDef])
            case o: EnumOption =>
              (gen.enumClassDef(o).asInstanceOf[ClassDef] :: enumTypes,
                gen.enumObjectDef(o).asInstanceOf[ModuleDef] :: enumValues,
                fields :+ gen.enumVal(o, m.name).asInstanceOf[ValDef])
          }
        }

      val jsonEncoderVal = gen.moduleObjectJsonEncoder(m).asInstanceOf[ValDef]

      val enumSetters = m.enumOptions.map(gen.enumSetterDef(m.name)).asInstanceOf[List[DefDef]]

      val objectDef = q"""
         object $moduleTermName {
           $jsonEncoderVal
           ..$enumTypes
           ..$enumValues
         }
      """.asInstanceOf[ModuleDef]


      val classDef = q"""
        case class $moduleTypeName(..$fields) extends ansible.Module {
          override def call = ModuleCall(this.asJson)
          ..$enumSetters
        }
       """.asInstanceOf[ClassDef]

      (objectDef, classDef)
    }

    annottees.map(_.tree) match {
      case List(q"trait $_") =>
        val (objectDefs, classDefs) = ansibleModules.map(m => generateModule(m)).unzip
        c.Expr[Any](
          q"""
             import argonaut._
             import Argonaut._

             ..$objectDefs
             ..$classDefs
          """)
      case _ =>
        c.abort(c.enclosingPosition, "@expand should annotate a trait")
    }
  }

  private def camelize(str: String): String =
    str.split('_').map { s =>
      if (s.isEmpty)
        ""
      else
        s.head.toUpper.toString + s.tail.toLowerCase
    }.mkString
} 
Example 8
Source File: autoInvariant.scala    From mainecoon   with Apache License 2.0 5 votes vote down vote up
package mainecoon

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.meta._
import Util._

import collection.immutable.Seq


@compileTimeOnly("Cannot expand @autoFunctor")
class autoInvariant extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    enrichAlgebra(defn, higherKinded = false)(autoInvariant.invariantInst)
  }
}

object autoInvariant {
  private[mainecoon] def invariantInst(ad: AlgDefn): TypeDefinition = {
    import ad._
    import cls._

    class ParamParser(params: Seq[Term.Param]) {
      lazy val effParams: Seq[Term.Param] =
        params.collect {
          case p @ Term.Param(_, _, Some(Type.Name(`effectTypeName`)), _) => p
        }

      lazy val newArgs: Seq[Term] =
        params.map {
          case p if effParams.contains(p) => q"mapFunctionFrom(${Term.Name(p.name.value)})"
          case p => Term.Name(p.name.value)
        }

      lazy val newParams: Seq[Term.Param] =
        params.map { p =>
          effParams.find(_ == p).fold(p) { effP =>
            effP.copy(decltpe = Some(Type.Name("TTarget")))
          }
        }
    }

    val methods = templ.stats.toList.flatMap(_.collect {
      //abstract method with return type being effect type
      case q"def $methodName[..$mTParams](...$params): ${Type.Name(`effectTypeName`)}" =>
        val pps = params.map(new ParamParser(_))
        q"""def $methodName[..$mTParams](...${pps.map(_.newParams)}): TTarget =
           mapFunction(delegatee_.$methodName(...${pps.map(_.newArgs)}))"""

      //abstract method with other return type
      case q"def $methodName[..$mTParams](...$params): $targetType" =>
        val pps = params.map(new ParamParser(_))
        q"""def $methodName[..$mTParams](...${pps.map(_.newParams)}): $targetType =
           delegatee_.$methodName(...${pps.map(_.newArgs)})"""
    })

    val instanceDef = Seq(q"""
      implicit def ${Term.Name("invariantFor" + name.value)}[..$extraTParams]: _root_.cats.Invariant[$typeLambdaVaryingEffect] =
        new _root_.cats.Invariant[$typeLambdaVaryingEffect] {
          def imap[T, TTarget](delegatee_ : $name[..${tArgs("T")}])(mapFunction: T => TTarget)(mapFunctionFrom: TTarget => T): $name[..${tArgs("TTarget")}] =
            new ${Ctor.Ref.Name(name.value)}[..${tArgs("TTarget")}] {
              ..$methods
            }
        }""")

    cls.copy(companion = cls.companion.addStats(instanceDef))

  }
} 
Example 9
Source File: autoFunctor.scala    From mainecoon   with Apache License 2.0 5 votes vote down vote up
package mainecoon

import mainecoon.Util._

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.meta._


@compileTimeOnly("Cannot expand @autoFunctor")
class autoFunctor extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    enrichAlgebra(defn, higherKinded = false)(autoFunctor.functorInst)
  }
}


object autoFunctor {
  private[mainecoon] def functorInst(ad: AlgDefn): TypeDefinition = {
    import ad._
    import cls._

    val instanceDef =
      q"""
    implicit def ${Term.Name("functorFor" + name.value)}[..$extraTParams]: _root_.cats.Functor[$typeLambdaVaryingEffect] =
      new _root_.cats.Functor[$typeLambdaVaryingEffect] {
        def map[T, TTarget](delegatee_ : $name[..${tArgs("T")}])(mapFunction: T => TTarget): $name[..${tArgs("TTarget")}] =
          new ${Ctor.Ref.Name(name.value)}[..${tArgs("TTarget")}] {
            ..${autoFlatMap.mapMethods(templ, effectTypeName)}
          }
      }"""

    cls.copy(companion = cls.companion.addStats(Seq(instanceDef)))
  }
} 
Example 10
Source File: finalAlg.scala    From mainecoon   with Apache License 2.0 5 votes vote down vote up
package mainecoon

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import Util._

import scala.meta._
import collection.immutable.Seq

@compileTimeOnly("Cannot expand @finalAlg")
class finalAlg extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {

    def enrich(ad: AlgDefn): TypeDefinition = {
      import ad._
      import cls._

     cls.copy(
        companion = companion.addStats( Seq[Stat](
          q"def apply[..${cls.tparams}](implicit inst: $name[..${tArgs()}]): $name[..${tArgs()}] = inst"
        ))
      )
    }
    enrichAlgebra(defn, false)(enrich)
  }
} 
Example 11
Source File: autoSemigroupalK.scala    From mainecoon   with Apache License 2.0 5 votes vote down vote up
package mainecoon

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.meta._
import autoSemigroupalK._
import Util._

import collection.immutable.Seq


@compileTimeOnly("Cannot expand @autoSemigroupalK")
class autoSemigroupalK extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    enrich(defn)(semigroupalKInst)
  }
}

object autoSemigroupalK {
  private[mainecoon] def semigroupalKInst(cls: TypeDefinition): TypeDefinition = {
    import cls._

    val instanceDef = Seq(q"""
      implicit def ${Term.Name("semigroupalKFor" + name.value)}: _root_.mainecoon.SemigroupalK[$name] =
        new _root_.mainecoon.SemigroupalK[$name] {
          ${semigroupalKMethods(cls)}
        }""")

    cls.copy(companion = cls.companion.addStats(instanceDef))
  }

  private[mainecoon] def semigroupalKMethods(cls: TypeDefinition): Defn = {
    import cls._

    val methods = templ.stats.map(_.map {
      case q"def $methodName[..$mTParams](..$params): $f[$resultType]" =>

        q"""def $methodName[..$mTParams](..$params): _root_.cats.data.Tuple2K[F, G, $resultType] =
           _root_.cats.data.Tuple2K(af.$methodName(..${arguments(params)}), ag.$methodName(..${arguments(params)}))"""
      case q"def $methodName[..$mTParams](..$params)(..$params2): $f[$resultType]" =>

        q"""def $methodName[..$mTParams](..$params)(..$params2): _root_.cats.data.Tuple2K[F, G, $resultType] =
           _root_.cats.data.Tuple2K(af.$methodName(..${arguments(params)})(..${arguments(params2)}), ag.$methodName(..${arguments(params)})(..${arguments(params2)}))"""
      case st => abort(s"autoSemigroupalK does not support algebra with such statement: $st")
    }).getOrElse(Nil)

    q"""
      def productK[F[_], G[_]](af: $name[F], ag: $name[G]): $name[({type λ[A]=_root_.cats.data.Tuple2K[F, G, A]})#λ] =
        new ${Ctor.Ref.Name(name.value)}[({type λ[A]=_root_.cats.data.Tuple2K[F, G, A]})#λ] {
          ..$methods
        }
    """


  }
} 
Example 12
Source File: Macros.scala    From seed   with Apache License 2.0 5 votes vote down vote up
import scala.reflect.macros.blackbox
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation

object helloMacro {
  def impl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    import Flag._
    val result = {
      annottees.map(_.tree).toList match {
        case q"object $name extends ..$parents { ..$body }" :: Nil =>
          q"""
            object $name extends ..$parents {
              def hello: ${typeOf[String]} = "hello"
              ..$body
            }
          """
      }
    }
    c.Expr[Any](result)
  }
}

class hello extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro helloMacro.impl
} 
Example 13
Source File: autoApplyK.scala    From mainecoon   with Apache License 2.0 5 votes vote down vote up
package mainecoon

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.meta._
import Util._

import collection.immutable.Seq


@compileTimeOnly("Cannot expand @autoApplyK")
class autoApplyK(autoDerivation: Boolean) extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    val autoDerivation: Boolean = this match {
      case q"new $_(${Lit.Boolean(arg)})" => arg
      case q"new $_(autoDerivation = ${Lit.Boolean(arg)})" => arg
      case _  => true
    }
    enrichAlgebra(defn)(a => new ApplyKInstanceGenerator(a, autoDerivation).newDef)
  }
}


class ApplyKInstanceGenerator(algDefn: AlgDefn, autoDerivation: Boolean) extends CovariantKMethodsGenerator(algDefn) {
  import algDefn._
  import cls._
  lazy val instanceDef: Seq[Defn] = {
    Seq(
      companionMapKDef,
      q"""
        implicit def ${Term.Name("applyKFor" + name.value)}[..$extraTParams]: _root_.mainecoon.ApplyK[$typeLambdaVaryingHigherKindedEffect] =
          new _root_.mainecoon.ApplyK[$typeLambdaVaryingHigherKindedEffect] {
            $instanceMapKDef
            ${autoSemigroupalK.semigroupalKMethods(cls)}
          }
      """
    )
  }


  lazy val newDef: TypeDefinition = cls.copy(companion = cls.companion.addStats(instanceDef ++  {
    if(autoDerivation)
      Seq(autoDerivationDef)
    else Nil}))
} 
Example 14
Source File: JsonReaderDefaultValue.scala    From tethys   with Apache License 2.0 5 votes vote down vote up
package tethys.readers

import tethys.readers.JsonReaderDefaultValue.ReaderDefaultValue

import scala.annotation.StaticAnnotation

trait JsonReaderDefaultValue[A] {
  def defaultValue: Any
}

object JsonReaderDefaultValue extends LowPriorityDefaultValue {
  def apply[A](implicit dv: JsonReaderDefaultValue[A]): JsonReaderDefaultValue[A] = dv

  //Allows easy access of default value in macro
  class ReaderDefaultValue(value: Any) extends StaticAnnotation

  @ReaderDefaultValue(None)
  class OptionDefaultValue[A] extends JsonReaderDefaultValue[Option[A]] {
    override def defaultValue: Any = None
  }
  private val optionInstance: OptionDefaultValue[Nothing] = new OptionDefaultValue[Nothing]
  implicit def optionDefaultValue[A]: OptionDefaultValue[A] = optionInstance.asInstanceOf[OptionDefaultValue[A]]
}

trait LowPriorityDefaultValue {
  @ReaderDefaultValue(null)
  class NoDefaultValue[A] extends JsonReaderDefaultValue[A] {
    override def defaultValue: Any = null
  }

  private val noDefaultValueInstance: NoDefaultValue[Nothing] = new NoDefaultValue[Nothing]
  implicit def noDefaultValue[A]: NoDefaultValue[A] = noDefaultValueInstance.asInstanceOf[NoDefaultValue[A]]
} 
Example 15
Source File: FieldStyle.scala    From tethys   with Apache License 2.0 5 votes vote down vote up
package tethys.derivation.builder

import java.util.regex.Pattern

import scala.annotation.StaticAnnotation

trait FieldStyle  { self =>
  def applyStyle(field: String): String

  def andThen(that: FieldStyle): FieldStyle = new FieldStyle {
    override def applyStyle(field: String): String = that.applyStyle(self.applyStyle(field))
  }

  def andThen(that: String => String): FieldStyle = new FieldStyle {
    override def applyStyle(field: String): String = that.apply(self.applyStyle(field))
  }

  def >>(that: FieldStyle): FieldStyle = andThen(that)
  def >>(that: String => String): FieldStyle = andThen(that)
}


object FieldStyle {

  def apply(fun: String => String): FieldStyle = new FieldStyle {
    override def applyStyle(field: String): String = fun(field)
  }

  class Ref(fieldStyle: FieldStyle) extends StaticAnnotation
  trait StyleReference extends FieldStyle {
    final override def applyStyle(field: String): String = throw new RuntimeException("StyleReference should not be used at runtime")
  }

  // Names transformations adopted from scala enumeratum
  private val regexp1: Pattern = Pattern.compile("([A-Z]+)([A-Z][a-z])")
  private val regexp2: Pattern = Pattern.compile("([a-z\\d])([A-Z])")
  private val replacement: String = "$1_$2"

  private def splitName(name: String): List[String] = {
    val first = regexp1.matcher(name).replaceAll(replacement)
    regexp2.matcher(first).replaceAll(replacement).split("_").toList
  }

  val snakecase: FieldStyle = new FieldStyle {
    override def applyStyle(field: String): String = splitName(field).mkString("_")
  }

  val lowercase: FieldStyle = new FieldStyle {
    override def applyStyle(field: String): String = field.toLowerCase()
  }

  val uppercase: FieldStyle = new FieldStyle {
    override def applyStyle(field: String): String = field.toUpperCase()
  }

  val lowerSnakecase: FieldStyle = snakecase >> lowercase
  val upperSnakecase: FieldStyle = snakecase >> uppercase
} 
Example 16
Source File: autoInstrument.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoInstrument")
class autoInstrument extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoInstrumentMacros.instrumentInst
}

private[tagless] class autoInstrumentMacros(override val c: whitebox.Context) extends MacroUtils  {
  import c.universe._

  private def generateInstrumentFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("instrumentFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.diagnosis.Instrument[$algebraType]",
      q"_root_.cats.tagless.Derive.instrument[$algebraType]"
    )

  def instrumentInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.FirstHigherKindedTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateInstrumentFor(algebra.name)) :: Nil
    }
} 
Example 17
Source File: autoBifunctor.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoBifunctor")
class autoBifunctor extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoBifunctorMacros.bifunctorInst
}

private[tagless] class autoBifunctorMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateBifunctorFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("bifunctorFor" + algebraName),
      typeParams,
      tq"_root_.cats.Bifunctor[$algebraType]",
      q"_root_.cats.tagless.Derive.bifunctor[$algebraType]"
    )

  def bifunctorInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.TwoLastRegularTypeParams) {
      algebra =>
        algebra.forVaryingEffectType(generateBifunctorFor(algebra.name)) :: Nil
    }
} 
Example 18
Source File: autoProfunctor.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoProfunctor")
class autoProfunctor extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoProfunctorMacros.profunctorInst
}

private[tagless] class autoProfunctorMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateProfunctorFor(
    algebraName: String
  )(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("profunctorFor" + algebraName),
      typeParams,
      tq"_root_.cats.arrow.Profunctor[$algebraType]",
      q"_root_.cats.tagless.Derive.profunctor[$algebraType]"
    )

  def profunctorInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.TwoLastRegularTypeParams) {
      algebra =>
        algebra.forVaryingEffectType(generateProfunctorFor(algebra.name)) :: Nil
    }
} 
Example 19
Source File: autoInvariant.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoInvariant")
class autoInvariant extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoInvariantMacros.invariantInst
}

private[tagless] class autoInvariantMacros(override val c: whitebox.Context) extends MacroUtils  {
  import c.universe._

  private def generateInvariantFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("invariantFor" + algebraName),
      typeParams,
      tq"_root_.cats.Invariant[$algebraType]",
      q"_root_.cats.tagless.Derive.invariant[$algebraType]"
    )

  def invariantInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateInvariantFor(algebra.name)) :: Nil
    }
} 
Example 20
Source File: autoFunctor.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoFunctor")
class autoFunctor extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoFunctorMacros.functorInst
}


private[tagless] class autoFunctorMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateFunctorFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("functorFor" + algebraName),
      typeParams,
      tq"_root_.cats.Functor[$algebraType]",
      q"_root_.cats.tagless.Derive.functor[$algebraType]"
    )

  def functorInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateFunctorFor(algebra.name)) :: Nil
    }
} 
Example 21
Source File: autoContravariantK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoFunctorK")
class autoContravariantK(autoDerivation: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoContravariantKMacros.contravariantKInst
}

private [tagless] class autoContravariantKMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateContravariantKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("contravariantKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.ContravariantK[$algebraType]",
      q"_root_.cats.tagless.Derive.contravariantK[$algebraType]"
    )

  def contravariantKInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList) { algebra =>
      algebra.forVaryingEffectType(generateContravariantKFor(algebra.name)) :: Nil
    }
} 
Example 22
Source File: package.scala    From scala-loci   with Apache License 2.0 5 votes vote down vote up
import loci.communicator._
import loci.language._
import loci.messaging._

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros

package loci {
  @compileTimeOnly("enable macro paradise to use multitier code")
  final class multitier extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro impl.Multitier.annotation
  }

  object multitier {
    def start[P, Inst[P] <: Instance[P]](instance: Inst[P]): Runtime[P] =
      macro impl.Instance.start

    @compileTimeOnly("method can only be invoked in multitier code")
    def running: Boolean = erased

    @compileTimeOnly("method can only be invoked in multitier code")
    def terminate(): Unit = erased
  }

  final class peer extends StaticAnnotation

  sealed trait Single[P] extends Multiple[P]
  sealed trait Optional[P] extends Multiple[P]
  sealed trait Multiple[+P]

  trait Remote[+P] extends Equals
  object Remote extends transmitter.RemoteReference
}

package object loci {
  type Local[T] = T

  type on[T, P] = Placed[T, P] with T
  type per[T, P] = Placed.Subjective[T, P]

  def connect[P](setup: Connector[ConnectionsBase.Protocol]): Connections =
    macro impl.Connections.setup
  def connect[P](factory: ConnectionSetupFactory[ConnectionsBase.Protocol])(
       args: Any*): Connections =
    macro impl.Connections.factory

  def placed: Placement.Placed = erased
  def on: Placement.Select[Placement.Run] = erased
  def on[P]: Placement.On[P] with Placement.Run[P, from] = erased
  def remote: Placement.Narrow with Placement.Select[Placement.Call] with Placement.Call[Nothing, from] with Gateway[Nothing] = erased
  def remote[P]: Placement.Call[P, from] with Gateway[P] = erased
} 
Example 23
Source File: XmlnsDef.scala    From phobos   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.phobos.annotations

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.reflect.macros.blackbox

@compileTimeOnly("enable macro paradise to expand macro annotations")
final class XmlnsDef(uri: String) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro XmlnsDefImpl.impl
}

private final class XmlnsDefImpl(ctx: blackbox.Context) extends CodecAnnotation(ctx) {
  import c.universe._

  def instances(typ: Tree): Seq[Tree] = {
    val pkg = q"ru.tinkoff.phobos"
    val instanceName = TermName(c.freshName("namespaceInstance"))
    val uri = c.prefix.tree match {
      case q"new XmlnsDef($uri)" => uri
    }
    Seq(q"implicit val $instanceName: $pkg.Namespace[$typ] = $pkg.Namespace.mkInstance[$typ]($uri)")
  }

} 
Example 24
Source File: XmlCodec.scala    From phobos   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.phobos.annotations

import ru.tinkoff.phobos.configured.ElementCodecConfig
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.reflect.macros.blackbox

@compileTimeOnly("enable macro paradise to expand macro annotations")
class XmlCodec(localName: String, config: ElementCodecConfig = ElementCodecConfig.default) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro XmlCodecImpl.impl
}

private final class XmlCodecImpl(ctx: blackbox.Context) extends CodecAnnotation(ctx) {
  import c.universe._

  def instances(typ: Tree): Seq[Tree] = {
    val pkg = q"ru.tinkoff.phobos"
    val (localName, config) = c.prefix.tree match {
      case q"new XmlCodec($localName)"          => (localName, defaultConfig.tree)
      case q"new XmlCodec($localName, $config)" => (localName, config)
    }

    Seq(
      q"""
          implicit val ${TermName(c.freshName("elementEncoder"))}: $pkg.encoding.ElementEncoder[$typ] =
            $pkg.derivation.semiauto.deriveElementEncoderConfigured[$typ]($config)
       """,
      q"""
          implicit val ${TermName(c.freshName("elementDecoder"))}: $pkg.decoding.ElementDecoder[$typ] =
            $pkg.derivation.semiauto.deriveElementDecoderConfigured[$typ]($config)
       """,
      q"""
          implicit val ${TermName(c.freshName("xmlEncoder"))}: $pkg.encoding.XmlEncoder[$typ] =
            $pkg.encoding.XmlEncoder.fromElementEncoder[$typ]($localName)
       """,
      q"""
          implicit val ${TermName(c.freshName("xmlDecoder"))}: $pkg.decoding.XmlDecoder[$typ] =
            $pkg.decoding.XmlDecoder.fromElementDecoder[$typ]($localName)
       """
    )
  }

} 
Example 25
Source File: XmlCodecNs.scala    From phobos   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.phobos.annotations

import ru.tinkoff.phobos.Namespace
import ru.tinkoff.phobos.configured.ElementCodecConfig
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.reflect.macros.blackbox

@compileTimeOnly("enable macro paradise to expand macro annotations")
class XmlCodecNs[T: Namespace](localName: String, namespace: T, config: ElementCodecConfig = ElementCodecConfig.default)
    extends StaticAnnotation {
  def namespaceUri: String = Namespace[T].getNamespace
  def macroTransform(annottees: Any*): Any = macro XmlCodecNsImpl.impl
}

private final class XmlCodecNsImpl(ctx: blackbox.Context) extends CodecAnnotation(ctx) {
  import c.universe._

  def instances(typ: Tree): Seq[Tree] = {
    val pkg = q"ru.tinkoff.phobos"
    val (nsInstance, localName, config) = c.prefix.tree match {
      case q"new XmlCodecNs($localName, $nsInstance)"              => (nsInstance, localName, defaultConfig.tree)
      case q"new XmlCodecNs($localName, $nsInstance, $config)"     => (nsInstance, localName, config)
      case q"new XmlCodecNs[$_]($localName, $nsInstance, $config)" => (nsInstance, localName, config)
    }

    Seq(
      q"""
          implicit val ${TermName(c.freshName("elementEncoder"))}: $pkg.encoding.ElementEncoder[$typ] =
            $pkg.derivation.semiauto.deriveElementEncoderConfigured[$typ]($config)
       """,
      q"""
          implicit val ${TermName(c.freshName("elementDecoder"))}: $pkg.decoding.ElementDecoder[$typ] =
            $pkg.derivation.semiauto.deriveElementDecoderConfigured[$typ]($config)
       """,
      q"""
          implicit val ${TermName(c.freshName("xmlEncoder"))}: $pkg.encoding.XmlEncoder[$typ] =
            $pkg.encoding.XmlEncoder.fromElementEncoderNs($localName, $nsInstance)
       """,
      q"""
          implicit val ${TermName(c.freshName("xmlDecoder"))}: $pkg.decoding.XmlDecoder[$typ] =
            $pkg.decoding.XmlDecoder.fromElementDecoderNs($localName, $nsInstance)
       """
    )
  }

} 
Example 26
Source File: ElementCodec.scala    From phobos   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.phobos.annotations

import ru.tinkoff.phobos.configured.ElementCodecConfig
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.reflect.macros.blackbox

@compileTimeOnly("enable macro paradise to expand macro annotations")
final class ElementCodec(config: ElementCodecConfig = ElementCodecConfig.default) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro ElementCodecImpl.impl
}

private final class ElementCodecImpl(ctx: blackbox.Context) extends CodecAnnotation(ctx) {
  import c.universe._

  def instances(typ: Tree): Seq[Tree] = {
    val pkg = q"ru.tinkoff.phobos"

    val config = c.prefix.tree match {
      case q"new ElementCodec"          => defaultConfig.tree
      case q"new ElementCodec($config)" => config
    }

    Seq(
      q"""
          implicit val ${TermName(c.freshName("elementEncoder"))}: $pkg.encoding.ElementEncoder[$typ] =
            $pkg.derivation.semiauto.deriveElementEncoderConfigured[$typ]($config)
       """,
      q"""
          implicit val ${TermName(c.freshName("elementDecoder"))}: $pkg.decoding.ElementDecoder[$typ] =
            $pkg.derivation.semiauto.deriveElementDecoderConfigured[$typ]($config)
       """
    )
  }

} 
Example 27
Source File: SetProperty.scala    From scio   with Apache License 2.0 5 votes vote down vote up
package com.spotify.scio.bigquery.validation

import scala.annotation.{compileTimeOnly, StaticAnnotation}
import scala.reflect.macros.blackbox

// This shouldn't be necessary in most production use cases. However passing System properties from
// Intellij can cause issues. The ideal place to set this system property is in your build.sbt file.
private[validation] object SetProperty {
  @compileTimeOnly(
    "enable macro paradise (2.12) or -Ymacro-annotations (2.13) to expand macro annotations"
  )
  class setProperty extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro setPropertyImpl
  }

  def setSystemProperty(): String =
    System.setProperty(
      "override.type.provider",
      "com.spotify.scio.bigquery.validation.SampleOverrideTypeProvider"
    )

  def setPropertyImpl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    setSystemProperty()
    annottees.head
  }
} 
Example 28
Source File: SysPropsMacros.scala    From scio   with Apache License 2.0 5 votes vote down vote up
package com.spotify.scio

import scala.annotation.{compileTimeOnly, StaticAnnotation}
import scala.reflect.macros.blackbox

@compileTimeOnly(
  "enable macro paradise (2.12) or -Ymacro-annotations (2.13) to expand macro annotations"
)
final class registerSysProps extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro registerSysPropsMacro.impl
}

private object registerSysPropsMacro {
  def impl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    val traitT = tq"_root_.com.spotify.scio.SysProps"

    annottees.map(_.tree) match {
      case List(q"$mod object $name extends ..$parents { ..$body }") =>
        val vars = body.collect {
          case ValDef(_, _, _, rhs) => c.Expr(rhs)
        }

        val propertiesMethod =
          q"""override def properties: List[SysProp] = List(..$vars)"""

        c.Expr[Any](q"""
            $mod object $name extends ..$parents with $traitT {
              $propertiesMethod
              ..$body
            }
            """)
      case t => c.abort(c.enclosingPosition, s"Invalid annotation $t")
    }
  }
} 
Example 29
Source File: TypeProviderIT.scala    From scio   with Apache License 2.0 5 votes vote down vote up
package com.spotify.scio.avro.types

import org.scalatest.Assertion
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import scala.annotation.StaticAnnotation
import scala.reflect.runtime.universe._

class TypeProviderIT extends AnyFlatSpec with Matchers {

  @AvroType.fromSchemaFile("""
      |https://raw.githubusercontent.com/spotify/scio/master/
      |scio-avro/src/test/avro/
      |scio-avro-test.avsc
    """.stripMargin)
  class FromResourceMultiLine
  @AvroType.fromSchemaFile(
    "https://raw.githubusercontent.com/spotify/scio/master/scio-avro/src/test/avro/scio-avro-test.avsc"
  )
  class FromResource

  "AvroType.fromSchemaFile" should "support reading schema from multiline resource" in {
    val r = FromResourceMultiLine(1)
    r.test shouldBe 1
  }

  it should "support reading schema from resource" in {
    val r = FromResource(2)
    r.test shouldBe 2
  }

  class Annotation1 extends StaticAnnotation
  class Annotation2 extends StaticAnnotation

  @Annotation1
  @AvroType.fromSchemaFile(
    "https://raw.githubusercontent.com/spotify/scio/master/scio-avro/src/test/avro/scio-avro-test.avsc"
  )
  @Annotation2
  class FromResourceWithSurroundingAnnotations

  it should "preserve surrounding user defined annotations" in {
    containsAllAnnotTypes[FromResourceWithSurroundingAnnotations]
  }
  @AvroType.fromSchemaFile(
    "https://raw.githubusercontent.com/spotify/scio/master/scio-avro/src/test/avro/scio-avro-test.avsc"
  )
  @Annotation1
  @Annotation2
  class FromResourceWithSequentialAnnotations

  it should "preserve sequential user defined annotations" in {
    containsAllAnnotTypes[FromResourceWithSequentialAnnotations]
  }

  def containsAllAnnotTypes[T: TypeTag]: Assertion =
    typeOf[T].typeSymbol.annotations
      .map(_.tree.tpe)
      .containsSlice(Seq(typeOf[Annotation1], typeOf[Annotation2])) shouldBe true

} 
Example 30
Source File: ToStringObfuscate.scala    From firebase4s   with MIT License 5 votes vote down vote up
package firebase4s.macros

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

@compileTimeOnly("enable macro paradise to expand macro annotations")
class ToStringObfuscate(fieldsToObfuscate: String*) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro ToStringObfuscateImpl.impl
}

object ToStringObfuscateImpl {

  def obfuscateValue(value: String) = "*" * value.length

  def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    def extractAnnotationParameters(tree: Tree): List[c.universe.Tree] = tree match {
      case q"new $name( ..$params )" => params
      case _                         => throw new Exception("ToStringObfuscate annotation must be have at least one parameter.")
    }

    def extractCaseClassesParts(classDecl: ClassDef) = classDecl match {
      case q"case class $className(..$fields) extends ..$parents { ..$body }" =>
        (className, fields, parents, body)
    }

    def replaceCaseClassSensitiveValues(tree: Tree) = tree match {
      case Literal(Constant(field: String)) =>
        q"""
            ${TermName(field)} = firebase4s.macros.ToStringObfuscateImpl.obfuscateValue(this.${TermName(field)})
          """
      case _ => c.abort(c.enclosingPosition, s"[replaceCaseClassSensitiveValues] Match error with $tree")
    }

    val sensitiveFields = extractAnnotationParameters(c.prefix.tree)
    
    val fieldReplacements = sensitiveFields.map(replaceCaseClassSensitiveValues(_))

    def extractNewToString(sensitiveFields: List[Tree]) = q"""
         override def toString: ${typeOf[String]} = {
          scala.runtime.ScalaRunTime._toString(this.copy(..$fieldReplacements))
         }
      """

    def modifiedDeclaration(classDecl: ClassDef) = {
      val (className, fields, parents, body) = extractCaseClassesParts(classDecl)
      val newToString = extractNewToString(sensitiveFields)

      val params = fields.asInstanceOf[List[ValDef]].map { p =>
        p.duplicate
      }

      c.Expr[Any](
        q"""
        case class $className ( ..$params ) extends ..$parents {
          $newToString
          ..$body
        }
      """
      )
    }

    annottees.map(_.tree) toList match {
      case (classDecl: ClassDef) :: Nil => modifiedDeclaration(classDecl)
      case _                            => c.abort(c.enclosingPosition, "Invalid annottee")
    }
  }
} 
Example 31
Source File: macro_impl.scala    From lms-clean   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package lms.experimental

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

import scala.util.matching.Regex

import scala.collection.mutable




object ir_impl {
  def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    println("YOUPI")
    println(c.prefix)
    val List(a) = annottees
    println(a)
    a.tree match {
      case q"def $name[..$t](..$args): $tpe" =>
        val args1 = args map { case ValDef(_,x,_,_) => q"ref($x)" }
        return c.Expr(q"def $name[..$t](..$args): $tpe = reflect[$tpe](${name.toString},..$args1)")
      case q"def $name[..$t](..$args): $tpe = $body" =>
        // TODO: strip by-name type
        val args0 = args map { case ValDef(_,x,_,_) => q"$x" }
        val args1 = args map { case ValDef(_,x,_,_) => q"ref($x)" }
        val name_next = TermName(name.toString + "_next")
        // TODO: what if we have type parameters? just disallow?
        return c.Expr(q"""
          lower((..$args) => 
            Rewrite[$tpe]($name(..$args0), $name_next(..$args0)))
          def $name[..$t](..$args): $tpe = reflect[$tpe](${name.toString},..$args1)
          def $name_next[..$t](..$args): $tpe = $body
        """)
     // TODO class def
      //case t@ClassDef(_,_,_,_) =>
    }
  }
} 
Example 32
Source File: Profiler.scala    From lift   with MIT License 5 votes vote down vote up
package lift.profiler

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

class Profile(extraContext: String = "") extends StaticAnnotation {
  def macroTransform(annottees: Any*) = macro Profile.impl
}

object Profile {
  def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    val ctx: String = c.prefix.tree match {
      case q"new Profile($extraContext)" =>
        c.eval[String](c.Expr[String](extraContext))
      // match for when we have no explicit context (i.e. this allows us to
      // write `@Profile def ...` rather than `@Profile() def ...` which is
      // (in some ways) slightly cleaner
      case _⇒ "nocontext"
    }

    val result = {
      annottees.map(_.tree).toList match {
        case q"$mods def $methodName[..$tpes](...$args): $returnType = { ..$body }" :: Nil => {
          q"""$mods def $methodName[..$tpes](...$args): $returnType =  {
            val start = System.nanoTime()
            val profSpliceResultValueNoConflict = {..$body}
            val end = System.nanoTime()
            println("PROFILING_DATUM: (\""+${methodName.toString}+"\", \"" + ${ctx.toString} + "\", " + (end-start).toDouble/1000000 + ", \"Scala\")")
            profSpliceResultValueNoConflict
          }"""
        }
        case _ => c.abort(c.enclosingPosition, "Annotation @Profile can be used only with methods")
      }
    }
    c.Expr[Any](result)
  }

  def profile[T](name: String, context: String, f: () => T) : T = {
    val start = System.nanoTime()
    val r: T = f()
    val end = System.nanoTime()
    println("PROFILING_DATUM: (\"" + name + "\", \"" + context + "\"," + (end-start).toDouble/1000000 + ", \"Scala\")")
    r
  }
} 
Example 33
Source File: autoFlatMap.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoFlatMap")
class autoFlatMap extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoFlatMapMacros.flatMapInst
}


private[tagless] class autoFlatMapMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateFlatMapFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("flatMapFor" + algebraName),
      typeParams,
      tq"_root_.cats.FlatMap[$algebraType]",
      q"_root_.cats.tagless.Derive.flatMap[$algebraType]"
    )

  def flatMapInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateFlatMapFor(algebra.name)) :: Nil
    }
} 
Example 34
Source File: package.scala    From scala-loci   with Apache License 2.0 5 votes vote down vote up
import loci.communicator._
import loci.language._
import loci.messaging._

import scala.annotation.{StaticAnnotation, compileTimeOnly, showAsInfix}
import scala.language.experimental.macros

package loci {
  @compileTimeOnly("enable macro paradise to use multitier code")
  final class multitier extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro impl.Multitier.annotation
  }

  object multitier {
    def start[P, Inst[P] <: Instance[P]](instance: Inst[P]): Runtime[P] =
      macro impl.Instance.start

    @compileTimeOnly("method can only be invoked in multitier code")
    def running: Boolean = erased

    @compileTimeOnly("method can only be invoked in multitier code")
    def terminate(): Unit = erased
  }

  final class peer extends StaticAnnotation

  sealed trait Single[P] extends Multiple[P]
  sealed trait Optional[P] extends Multiple[P]
  sealed trait Multiple[+P]

  trait Remote[+P] extends Equals
  object Remote extends transmitter.RemoteReference
}

package object loci {
  type Local[T] = T

  @showAsInfix type on[T, P] = Placed[T, P] with T
  @showAsInfix type per[T, P] = Placed.Subjective[T, P]

  def connect[P](setup: Connector[ConnectionsBase.Protocol]): Connections =
    macro impl.Connections.setup
  def connect[P](factory: ConnectionSetupFactory[ConnectionsBase.Protocol])(
       args: Any*): Connections =
    macro impl.Connections.factory

  def placed: Placement.Placed = erased
  def on: Placement.Select[Placement.Run] = erased
  def on[P]: Placement.On[P] with Placement.Run[P, from] = erased
  def remote: Placement.Narrow with Placement.Select[Placement.Call] with Placement.Call[Nothing, from] with Gateway[Nothing] = erased
  def remote[P]: Placement.Call[P, from] with Gateway[P] = erased
} 
Example 35
Source File: PlacedValueInfo.scala    From scala-loci   with Apache License 2.0 5 votes vote down vote up
package loci
package runtime

import transmitter.Marshallable

import scala.annotation.StaticAnnotation
import scala.annotation.meta.{getter, setter}

@getter @setter
final class MarshallableInfo[I](signature: Int) extends StaticAnnotation

final class PlacedValue[U, T](
  val signature: Value.Signature,
  val stable: Boolean,
  val arguments: Marshallable[U, _, _],
  val result: Marshallable[_, _, T])

@getter @setter
final class PlacedValueInfo(
  signature: String,
  arguments: Marshallable[_, _, _],
  result: Marshallable[_, _, _]) extends StaticAnnotation 
Example 36
Source File: package.scala    From scala-loci   with Apache License 2.0 5 votes vote down vote up
import loci.communicator._
import loci.language._
import loci.messaging._

import scala.annotation.{StaticAnnotation, compileTimeOnly, showAsInfix}
import scala.language.experimental.macros

package loci {
  @compileTimeOnly("enable macro paradise to use multitier code")
  final class multitier extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro impl.Multitier.annotation
  }

  object multitier {
    def start[P, Inst[P] <: Instance[P]](instance: Inst[P]): Runtime[P] =
      macro impl.Instance.start

    @compileTimeOnly("method can only be invoked in multitier code")
    def running: Boolean = erased

    @compileTimeOnly("method can only be invoked in multitier code")
    def terminate(): Unit = erased
  }

  final class peer extends StaticAnnotation

  sealed trait Single[P] extends Multiple[P]
  sealed trait Optional[P] extends Multiple[P]
  sealed trait Multiple[+P]

  trait Remote[+P] extends Equals
  object Remote extends transmitter.RemoteReference
}

package object loci {
  type Local[T] = T

  @showAsInfix type on[T, P] = Placed[T, P] with T
  @showAsInfix type per[T, P] = Placed.Subjective[T, P]

  def connect[P](setup: Connector[ConnectionsBase.Protocol]): Connections =
    macro impl.Connections.setup
  def connect[P](factory: ConnectionSetupFactory[ConnectionsBase.Protocol])(
       args: Any*): Connections =
    macro impl.Connections.factory

  def placed: Placement.Placed = erased
  def on: Placement.Select[Placement.Run] = erased
  def on[P]: Placement.On[P] with Placement.Run[P, from] = erased
  def remote: Placement.Narrow with Placement.Select[Placement.Call] with Placement.Call[Nothing, from] with Gateway[Nothing] = erased
  def remote[P]: Placement.Call[P, from] with Gateway[P] = erased
} 
Example 37
Source File: Decorator.scala    From Elysium   with MIT License 5 votes vote down vote up
package nz.daved.elysium.core

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import nz.daved.elysium.manipulate.DefManipulation._

import scala.meta.Defn.Def
import scala.meta._

@compileTimeOnly("@before not expanded")
class before(fun: () => Unit) extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    val q"new $_(${apply: Term.Apply})" = this
    defn.asInstanceOf[Def].prependStat(apply)
  }
}

@compileTimeOnly("@after not expanded")
class after(fun: () => Unit) extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    val q"new $_(${apply: Term.Apply})" = this
    defn.asInstanceOf[Def].appendStat(apply)
  }
} 
Example 38
Source File: ComponentApi.scala    From c4proto   with Apache License 2.0 5 votes vote down vote up
package ee.cone.c4di

import scala.annotation.StaticAnnotation
import scala.collection.immutable.Seq

object Types {
  type ComponentFactory[T] = Seq[TypeKey]=>Seq[T]
}

object CreateTypeKey { // to use mostly from generated code
  def apply(cl: Class[_], alias: String, args: List[TypeKey]): TypeKey =
    Value(cl.getName, alias, args)(cl)
  private case class Value(clName: String, alias: String, args: List[TypeKey])(val cl: Class[_]) extends TypeKey {
    def copy(alias: String, args: List[TypeKey]): TypeKey =
      Value(clName,alias,args)(cl)
  }
}
trait TypeKey extends Product {
  def cl: Class[_]
  def clName: String
  def args: List[TypeKey]
  def alias: String
  def copy(alias: String = alias, args: List[TypeKey] = args): TypeKey
}

class c4(apps: String*) extends StaticAnnotation
class provide extends StaticAnnotation
class c4multi(apps: String*) extends StaticAnnotation

trait AbstractComponents {
  def components: Seq[Component]
}
class Component(val out: TypeKey, val nonFinalOut: Option[TypeKey], val in: Seq[TypeKey], val create: Seq[Object]=>Seq[Object]) extends AbstractComponents {
  def components: Seq[Component] = Seq(this)
}


abstract class AutoMixer(val components: List[Component], val dependencies: List[AutoMixer])

trait GeneralC4Factory0
trait GeneralC4Factory1
trait GeneralC4Factory2
trait C4Factory0[+Out] { def create(): Out }
trait C4Factory1[In,+Out] { def create(in: In): Out }
trait C4Factory2[In1,In2,+Out] { def create(in1: In1, in2: In2): Out } 
Example 39
Source File: Protocol.scala    From c4proto   with Apache License 2.0 5 votes vote down vote up
package ee.cone.c4proto

import java.nio.charset.StandardCharsets.UTF_8

import ee.cone.c4di.TypeKey
import okio.ByteString

import collection.immutable.Seq
import scala.annotation.StaticAnnotation

case class Id(id: Long) extends StaticAnnotation

case class ShortName(name: String) extends StaticAnnotation

class GenLens extends StaticAnnotation

//  override def toString: String =
//    s"TypeKey(${if (clName.endsWith(alias)) clName else s"$clName/$alias"}${if (args.isEmpty) "" else args.map(_.toString).mkString("[",", ", "]")})"

case class MetaProp(id: Int, propName: String, propShortName: Option[String], resultType: String, typeProp: TypeKey)

trait ProtoOrigMeta {
  def id: Option[Long]
  def categories: List[DataCategory]
  def cl: Class[_]
  def shortName: Option[String]
  def metaProps: List[MetaProp]
}

trait HasId {
  def protoOrigMeta: ProtoOrigMeta
  def id: Long = protoOrigMeta.id.getOrElse(throw new Exception("This orig has no Id"))
  def hasId: Boolean = protoOrigMeta.id.nonEmpty
  lazy val className: String = protoOrigMeta.cl.getName

  @deprecated("Deprecated, use OrigMeta[Orig].categories", "07/04/20")
  def categories: List[DataCategory] = protoOrigMeta.categories
  @deprecated("Deprecated, use OrigMeta[Orig].cl", "07/04/20")
  def cl: Class[_] = protoOrigMeta.cl
  @deprecated("Deprecated, use OrigMeta[Orig].shortName", "07/04/20")
  def shortName: Option[String] = protoOrigMeta.shortName
  @deprecated("Deprecated, use OrigMeta[Orig].fieldsMeta", "07/04/20")
  def props: List[MetaProp] = protoOrigMeta.metaProps
}

object ToByteString {
  def apply(data: Array[Byte]): ByteString = ByteString.of(data,0,data.length)
  def apply(v: String): ByteString = apply(v.getBytes(UTF_8))
}

class replaceBy[T](factory: Object) extends StaticAnnotation

abstract class ArgAdapter[Value] {
  def encodedSizeWithTag (tag: Int, value: Value): Int
  def encodeWithTag(writer: ProtoWriter, tag: Int, value: Value): Unit
  def defaultValue: Value
  def decodeReduce(reader: ProtoReader, prev: Value): Value
  def decodeFix(prev: Value): Value
}

object FieldEncoding {
  val LENGTH_DELIMITED = com.squareup.wire.FieldEncoding.LENGTH_DELIMITED
} 
Example 40
Source File: DataCategory.scala    From c4proto   with Apache License 2.0 5 votes vote down vote up
package ee.cone.c4proto

import scala.annotation.StaticAnnotation

trait DataCategory extends Product

case class Cat(category: DataCategory*) extends StaticAnnotation

sealed trait DataTypeCategory extends DataCategory

case object B_Cat extends DataTypeCategory
case object C_Cat extends DataTypeCategory
case object D_Cat extends DataTypeCategory
case object E_Cat extends DataTypeCategory
case object N_Cat extends DataTypeCategory
case object S_Cat extends DataTypeCategory
case object U_Cat extends DataTypeCategory
case object V_Cat extends DataTypeCategory
case object T_Cat extends DataTypeCategory 
Example 41
Source File: LambdaHTTPApiAnnotation.scala    From quaich   with Apache License 2.0 5 votes vote down vote up
package codes.bytes.quaich.api.http.macros

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.postfixOps
import scala.reflect.macros.blackbox
import scala.language.experimental.macros

object LambdaHTTPApi {
  // todo - check for companion object and reject
  def annotation_impl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    import Flag._

    val p = c.enclosingPosition

    val inputs = annottees.map(_.tree).toList



    val result: Tree = inputs match {
      case (cls @ q"$mods class $name[..$tparams] extends ..$parents { ..$body }") :: Nil if mods.hasFlag(ABSTRACT) ⇒
        c.abort(p, "! The @LambdaHTTPApi annotation is not valid on abstract classes.")
        cls
      // todo - detect and handle companion object!
      case (cls @ q"$mods class $name[..$tparams] extends ..$parents { ..$body }") :: Nil ⇒
        //val baseName = name.decodedName.toString
        //val handlerName = TermName(s"$baseName$$RequestHandler")
        //val handlerName = name.toTermName
        val handlerName = name.asInstanceOf[TypeName].toTermName

        val cls = q"""
        $mods class $name[..$tparams](
            val request: codes.bytes.quaich.api.http.LambdaHTTPRequest,
            val context: codes.bytes.quaich.api.http.LambdaContext
          )
          extends ..$parents
          with codes.bytes.quaich.api.http.HTTPHandler {
            import org.json4s.jackson.JsonMethods._
            import org.json4s.jackson.Serialization
            import org.json4s.jackson.Serialization._
            import org.json4s.{NoTypeHints, _}

            protected implicit val formats = Serialization.formats(NoTypeHints)

            ..$body
          }
        """

        val obj = q"""
        object $handlerName extends codes.bytes.quaich.api.http.HTTPApp {
          def newHandler(
            request: codes.bytes.quaich.api.http.LambdaHTTPRequest,
            context: codes.bytes.quaich.api.http.LambdaContext
          ): codes.bytes.quaich.api.http.HTTPHandler =
            new $name(request, context)


        }
        """

        q"$cls; $obj"

      case Nil ⇒
        c.abort(p, s"Cannot annotate an empty Tree.")
      case _ ⇒
        c.abort(p, s"! The @LambdaHTTPApi Annotation is only valid on non-abstract Classes")
    }

    //c.info(p, "result: " + result, force = true)

    c.Expr[Any](result)

  }

}

@compileTimeOnly("Setup the macro paradise compiler plugin to enable expansion of macro annotations.")
class LambdaHTTPApi extends StaticAnnotation {

  def macroTransform(annottees: Any*): Any = macro LambdaHTTPApi.annotation_impl

}
// vim: set ts=2 sw=2 sts=2 et: 
Example 42
Source File: Macros.scala    From seed   with Apache License 2.0 5 votes vote down vote up
import scala.reflect.macros.blackbox
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation

object helloMacro {
  def impl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    import Flag._
    val result = {
      annottees.map(_.tree).toList match {
        case q"object $name extends ..$parents { ..$body }" :: Nil =>
          q"""
            object $name extends ..$parents {
              def hello: ${typeOf[String]} = "hello"
              ..$body
            }
          """
      }
    }
    c.Expr[Any](result)
  }
}

class hello extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro helloMacro.impl
} 
Example 43
Source File: api.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros


final class api extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro api.impl
}

private[forge] object api {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val utils = new MacroUtils[c.type](c)
    import utils._
    import c.universe._

    annottees.head match {
      case df: DefDef =>
        val withCtx   = ctx.impl(c)(annottees:_*)
        val withState = stateful.impl(c)(withCtx)
        withState
      case _ => invalidAnnotationUse("api", "defs")
    }
  }
} 
Example 44
Source File: Injectable.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description: Angular2 @Injectable annotation.

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.core

import angulate2.internal.ClassDecorator

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("@angular/core","Injectable")
object InjectableFacade extends js.Object {
  def apply() : js.Object = js.native
  def apply(options: js.Object) : js.Object = js.native
}

// NOTE: keep the constructor parameter list and Injectable.Macro.annotationParamNames in sync!
@compileTimeOnly("enable macro paradise to expand macro annotations")
class Injectable extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro Injectable.Macro.impl
}


object Injectable {

  private[angulate2] class Macro(val c: whitebox.Context) extends ClassDecorator {
    import c.universe._
    override val annotationName: String = "Injectable"

    override val annotationParamNames: Seq[String] = Seq()

    override def mainAnnotationObject = q"angulate2.core.InjectableFacade"
  }
} 
Example 45
Source File: typeclass.scala    From typeclassic   with Apache License 2.0 5 votes vote down vote up
package typeclassic

import scala.annotation.{ compileTimeOnly, StaticAnnotation }
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context

import macrocompat._

@compileTimeOnly("typeclass annotation should have been automatically removed but was not")
class typeclass(excludeParents: List[String] = Nil, generateAllOps: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro TypeClassMacros.generateTypeClass
}


@bundle
class TypeClassMacros(val c: Context) {
  import c.universe._

  def generateTypeClass(annottees: c.Expr[Any]*): c.Expr[Any] = {
    annottees.map(_.tree) match {
      case (typeClass: ClassDef) :: Nil => modify(typeClass, None)
      case (typeClass: ClassDef) :: (companion: ModuleDef) :: Nil => modify(typeClass, Some(companion))
      case other :: Nil =>
        c.abort(c.enclosingPosition, "@typeclass can only be applied to traits or abstract classes that take 1 type parameter which is either a proper type or a type constructor")
    }
  }

  private def modify(typeClass: ClassDef, companion: Option[ModuleDef]) = {
    val (tparam, proper) = typeClass.tparams match {
      case hd :: Nil =>
        hd.tparams.size match {
          case 0 => (hd, true)
          case 1 => (hd, false)
          case n => c.abort(c.enclosingPosition, "@typeclass may only be applied to types that take a single proper type or type constructor")
        }
      case other => c.abort(c.enclosingPosition, "@typeclass may only be applied to types that take a single type parameter")
    }

    val modifiedTypeClass = typeClass // TODO

    val modifiedCompanion = generateCompanion(typeClass, tparam, proper, companion match {
      case Some(c) => c
      case None => q"object ${typeClass.name.toTermName} {}"
    })

    val result = c.Expr(q"""
      $modifiedTypeClass
      $modifiedCompanion
    """)

    trace(s"Generated type class ${typeClass.name}:\n" + showCode(result.tree))

    result
  }

  private def generateCompanion(typeClass: ClassDef, tparam0: TypeDef, proper: Boolean, comp: Tree): Tree = {
    val tparam = eliminateVariance(tparam0)

    val q"$mods object $name extends ..$bases { ..$body }" = comp

    q"""
      $mods object $name extends ..$bases {
        import scala.language.experimental.macros
        ..$body
        ${generateInstanceSummoner(typeClass, tparam)}
      }
    """
  }

  private def generateInstanceSummoner(typeClass: ClassDef, tparam: TypeDef): Tree = {
    q"""
      @_root_.typeclassic.op("$$y {$$x}")
      def apply[$tparam](implicit x1: ${typeClass.name}[${tparam.name}]): ${typeClass.name}[${tparam.name}] =
        macro _root_.typeclassic.OpsMacros.op10
    """
  }

  // This method is from simulacrum, contributed by paulp, and is licensed under 3-Clause BSD
  private def eliminateVariance(tparam: TypeDef): TypeDef = {
    // If there's another way to do this I'm afraid I don't know it.
    val u        = c.universe.asInstanceOf[c.universe.type with scala.reflect.internal.SymbolTable]
    val tparam0  = tparam.asInstanceOf[u.TypeDef]
    val badFlags = (Flag.COVARIANT | Flag.CONTRAVARIANT).asInstanceOf[Long]
    val fixedMods = tparam0.mods & ~badFlags
    TypeDef(fixedMods.asInstanceOf[c.universe.Modifiers], tparam.name, tparam.tparams, tparam.rhs)
  }

  private def trace(s: => String) = {
    // Macro paradise seems to always output info statements, even without -verbose
    if (sys.props.get("typeclassic.trace").isDefined) c.info(c.enclosingPosition, s, false)
  }
} 
Example 46
Source File: valueclass.scala    From dilate   with Apache License 2.0 5 votes vote down vote up
package com.vitorsvieira.dilate

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.meta._
import scala.util.Try

@compileTimeOnly("@valueclass macro expands only in compile time.")
final class valueclass extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    defn match {
      case Term.Block(Seq([email protected](_, name, _, ctor, _), companion: Defn.Object)) =>
        val result = Dilate.valueclassApply(name, ctor.paramss)
        val newClass: Defn.Class = cls.copy(
          ctor = Ctor.Primary.apply(ctor.mods, ctor.name, result.domain.finalArgs)
        )

        val templateStats: Option[Seq[Stat]] = Try(
          result.template.valueclasses ++:
            result.template.implicitDefs ++:
            companion.templ.stats.getOrElse(Nil)
        ).toOption
        val newCompanion: Defn.Object = companion.copy(templ = companion.templ.copy(stats = templateStats))

        Term.Block(Seq(newClass, newCompanion))
      case [email protected](_, name, _, ctor, _)                                          =>
        val result: ExtractionResult = Dilate.valueclassApply(name, ctor.paramss)
        val newClass: Defn.Class = cls.copy(
          ctor = Ctor.Primary.apply(ctor.mods, ctor.name, result.domain.finalArgs)
        )

        val newCompanion: Defn.Object =
          q"""object ${Term.Name(name.value)} {
            ..${result.template.valueclasses}
            ..${result.template.implicitDefs}
          }"""

        Term.Block(Seq(newClass, newCompanion))
      case _ =>
        println(defn.structure)
        abort("@valueclass must annotate a class.")
    }
  }
} 
Example 47
Source File: newtype.scala    From dilate   with Apache License 2.0 5 votes vote down vote up
package com.vitorsvieira.dilate

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.meta._
import scala.util.Try

@compileTimeOnly("@newtype macro expands only in compile time.")
final class newtype extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    defn match {
      case Term.Block(Seq([email protected](_, name, _, ctor, _), companion: Defn.Object)) =>
        val result = Dilate.newtypeApply(name, ctor.paramss)
        val newClass: Defn.Class = cls.copy(
          ctor = Ctor.Primary.apply(ctor.mods, ctor.name, result.domain.finalArgs)
        )

        val templateStats: Option[Seq[Stat]] = Try(
          result.template.traits ++:
            result.template.types ++:
            result.template.implicitClasses ++:
            companion.templ.stats.getOrElse(Nil)
        ).toOption
        val newCompanion: Defn.Object = companion.copy(templ = companion.templ.copy(stats = templateStats))

        Term.Block(Seq(newClass, newCompanion))
      case [email protected](_, name, _, ctor, _) =>
        val result: ExtractionResult = Dilate.newtypeApply(name, ctor.paramss)
        val newClass: Defn.Class = cls.copy(
          ctor = Ctor.Primary.apply(ctor.mods, ctor.name, result.domain.finalArgs)
        )

        val newCompanion: Defn.Object =
          q"""object ${Term.Name(name.value)} {
            ..${result.template.traits}
            ..${result.template.types}
            ..${result.template.implicitClasses}
          }"""

        Term.Block(Seq(newClass, newCompanion))
      case _ =>
        println(defn.structure)
        abort("@newtype must annotate a class.")
    }
  }
} 
Example 48
Source File: DilateProtocol.scala    From dilate   with Apache License 2.0 5 votes vote down vote up
package com.vitorsvieira.dilate

import scala.annotation.StaticAnnotation
import scala.collection.immutable.Seq
import scala.meta._

sealed trait ClassParamAnnotation extends StaticAnnotation
final class hold extends ClassParamAnnotation

final private[dilate] case class ExtractionResult(
    template: CompanionObjectTemplate,
    domain:   OwnerClassArgs)

final private[dilate] case class CompanionObjectTemplate(
    valueclasses:    Seq[Defn.Class] = Seq.empty,
    traits:          Seq[Defn.Trait] = Seq.empty,
    types:           Seq[Defn.Type]  = Seq.empty,
    implicitClasses: Seq[Defn.Class] = Seq.empty,
    implicitDefs:    Seq[Defn.Def]   = Seq.empty
)

final private[dilate] case class OwnerClassArgs(finalArgs: Seq[Seq[Term.Param]] = Seq.empty)

final private[dilate] case class OwnerClassArgsSplitted(
    nonImplicitArgs: Seq[Term.Param],
    implicitArgs:    Seq[Term.Param])

final private[dilate] case class ExtractionPreResult(
    extraction: Seq[Extraction],
    newArgs:    OwnerClassArgs)

final private[dilate] case class Extraction(
    newArgs:     Term.Param,
    valueclass:  Option[Defn.Class]    = None,
    traitT:      Option[Defn.Trait]    = None,
    typeT:       Option[Defn.Type]     = None,
    implicitDef: Seq[Option[Defn.Def]] = Seq.empty
) 
Example 49
Source File: StreamStructs.scala    From spatial   with MIT License 5 votes vote down vote up
package spatial.tags

import argon.tags
import argon.tags.{Arith, Bits}
import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.blackbox


abstract class TypeclassMacro[Ctx <: blackbox.Context](val c: Ctx) {
  import c.universe._
  def implement(cls: ClassDef, obj: ModuleDef, fields: Seq[ValDef]): (ClassDef,ModuleDef)
}


object StagedStreamStructsMacro {

  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val typeclasses: Seq[tags.TypeclassMacro[c.type]] = Seq(
      new Bits[c.type](c),
      new Arith[c.type](c)
    )

    val utils = new MacroUtils[c.type](c)
    import c.universe._
    import utils._

    val (cls,obj) = annottees.toList match {
      case List(cd: ClassDef, md: ModuleDef) => (cd,md)
      case List(cd: ClassDef) => (cd, q"object ${cd.nameTerm}".asObject)
      case _ => invalidAnnotationUse("streamstruct", "classes")
    }

    val fields = cls.constructorArgs.head
    val methods = cls.nonConstructorMethods.filterNot{_.mods.hasFlag(Flag.CASEACCESSOR) }
    val parents: Seq[String] = cls.parents.collect{case Ident(TypeName(name)) => name }

    // TODO[5]: What to do if class has parents? Error?

    if (fields.isEmpty) abort("Classes need at least one field in order to be transformed into a @streamstruct.")
    if (methods.nonEmpty) {
      error(s"@streamstruct class had ${methods.length} disallowed methods:\n" + methods.map{method =>
        "  " + showCode(method.modifyBody(_ => EmptyTree))
      }.mkString("\n"))
      abort("@streamstruct classes with methods are not yet supported")
    }
    if (cls.tparams.nonEmpty) abort("@streamstruct classes with type parameters are not yet supported")
    if (cls.fields.exists(_.isVar)) abort("@streamstruct classes with var fields are not yet supported")

    val fieldTypes  = fields.map{field => q"${field.nameLiteral} -> argon.lang.Bits[${field.tpTree}]" }
    val fieldNames  = fields.map{field => q"${field.nameLiteral} -> ${field.name}"}
    val fieldOpts   = fields.map{field => field.withRHS(q"null") }
    val fieldOrElse = fields.map{field => q"Option(${field.name}).getOrElse{this.${field.name}(ctx,state)}" }

    var cls2 = q"class ${cls.name}[..${cls.tparams}]() extends spatial.lang.StreamStruct[${cls.fullName}]".asClass
    var obj2 = obj
    fields.foreach{field =>
      cls2 = cls2.injectMethod(
            q"""def ${field.name}(implicit ctx: forge.SrcCtx, state: argon.State): ${field.tpTree} = {
                  field[${field.tpTree}](${field.nameLiteral})(argon.lang.Bits[${field.tpTree}],ctx,state)
                }""".asDef)
    }
    cls2 = {
      cls2.injectField(q"lazy val fields = Seq(..$fieldTypes)".asVal)
          .mixIn(tq"argon.Ref[Any,${cls.fullName}]")
          .injectMethod(
            q"""def copy(..$fieldOpts)(implicit ctx: forge.SrcCtx, state: argon.State): ${cls.fullName} = {
                  ${obj2.name}.apply(..$fieldOrElse)(ctx, state)
                }""".asDef)
          .injectField(q"""override val box = implicitly[${cls.fullName} <:< (
                             spatial.lang.StreamStruct[${cls.fullName}]
                        with argon.lang.types.Bits[${cls.fullName}]
                        with argon.lang.types.Arith[${cls.fullName}]) ]""".asVal)
    }

    obj2 = {
      obj2.injectMethod(
        q"""def apply[..${cls.tparams}](..$fields)(implicit ctx: forge.SrcCtx, state: argon.State): ${cls.fullName} = {
              spatial.lang.StreamStruct[${cls.fullName}]( ..$fieldNames )(spatial.lang.StreamStruct.tp[${cls.fullName}], ctx, state)
            }
         """.asDef)
    }

    val (cls3,obj3) = typeclasses.foldRight((cls2,obj2)){case (tc, (c,o)) =>
      tc.implement(c, o, fields)
    }

    val (cls4, obj4) = forge.tags.ref.implement(c)(cls3, obj3)
    val out = q"$cls4; $obj4"

    //info(showRaw(out))
    //info(showCode(out))

    out
  }
} 
Example 50
Source File: dsl.scala    From spatial   with MIT License 5 votes vote down vote up
package spatial

import argon.tags.StagedStructsMacro
import spatial.tags.StagedStreamStructsMacro

trait SpatialDSL extends lang.api.StaticAPI_Frontend


  final class spatial extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro spatial.impl
  }
  private object spatial extends AppTag("spatial", "SpatialApp")

  final class struct extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro StagedStructsMacro.impl
  }
  final class streamstruct extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro StagedStreamStructsMacro.impl
  }
} 
Example 51
Source File: instrument.scala    From spatial   with MIT License 5 votes vote down vote up
package utils.tags

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros

final class instrument extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro instrument.impl
}

private[utils] object instrument {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import util._
    import c.universe._

    def instrument(df: DefDef): DefDef = {
      if (df.body != EmptyTree) df.modifyBody{body => q"instrument(${df.nameLiteral}){ $body }"}
      else df
    }

    val tree = annottees.head match {
      case cls: ClassDef  => cls.mapMethods(m => instrument(m)).mixIn(tq"utils.Instrumented")
      case obj: ModuleDef => obj.mapMethods(m => instrument(m)).mixIn(tq"utils.Instrumented")
      case _ => invalidAnnotationUse("@instrument", "objects", "defs")
    }
    //c.info(c.enclosingPosition, showCode(tree), force = true)
    tree
  }
} 
Example 52
Source File: op.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.blackbox

final class op extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro op.impl
}

object op {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import c.universe._
    import util._

    val (cls,obj) = annottees.toList match {
      case List(cd: ClassDef, md: ModuleDef) => (cd,md)
      case List(cd: ClassDef) => (cd, q"object ${cd.nameTerm}".asObject)
      case _ => invalidAnnotationUse("op", "classes")
    }

    val name = cls.name
    val names = cls.constructorArgs.head.map(_.name)
    val types = cls.constructorArgs.head.map(_.tp.get)
    val targs = cls.typeArgs
    val fnames = names.map{name => q"$$f($name)" }
    val updates = names.zip(fnames).map{case (name,fname) => q"$name = $fname" }

    val cls2 = cls.asCaseClass.withVarParams
      .injectMethod(q"override def mirror($$f:Tx) = new $name[..$targs](..$fnames)".asDef)
      .injectMethod(q"override def update($$f:Tx) = { ..$updates }".asDef)

    val obj2 = obj

    // TODO[5]: Not clear how this would be typed, or if its even an intuitive extractor
    

    //c.info(c.enclosingPosition, showCode(cls2), force = true)

    q"..${List(cls2,obj2)}"
  }
} 
Example 53
Source File: ref.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import language.experimental.macros
import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox


object ref {

  def implement(c: blackbox.Context)(cls: c.universe.ClassDef, obj: c.universe.ModuleDef): (c.universe.ClassDef, c.universe.ModuleDef) = {
    val util = new MacroUtils[c.type](c)
    import util._
    import c.universe._

    val (vargs,iargs) = cls.constructorArgs match {
      case List(v,i) if i.isImplicit => (v,i)
      case List(v) => (v, Nil)
      case _ => c.abort(c.enclosingPosition, "Ref classes can have at most one explicit and one implicit parameter list")
    }
    // TODO[5]: Should check that @ref class A mixes in Ref[?,A]

    val name = cls.name
    val tparams = cls.tparams
    val targs = cls.typeArgs
    val vnames = vargs.map(_.name)
    val inames = iargs.map(_.name)
    val cnames = vnames ++ inames
    val fullName = targsType(name, targs)

    val cls2 = cls.injectMethod(q"private def cargs: Seq[Any] = Seq(..$cnames)".asDef)
      .injectMethod(q"override protected def fresh = new $name[..$targs](..$vnames)".asDef)
      .injectField(q"override protected val __typePrefix = ${cls.nameLiteral}".asVal)
      .injectField(q"override protected val __typeArgs = cargs.collect{case t: argon.Type[_] => t}".asVal)
      .injectField(q"override protected val __typeParams = Seq(..$inames).filter{case t: argon.Type[_] => false; case _ => true}".asVal)

    val obj2 = (vargs, iargs) match {
      case (Nil,Nil) => obj.injectField(q"implicit val tp: $fullName = argon.proto(new $name[..$targs])".asVal)
      case (Nil, _)  => obj.injectMethod(q"implicit def tp[..$tparams](..$iargs): $fullName = argon.proto(new $name[..$targs]()(..$inames))".asDef)
      case (_, Nil)  => obj.injectMethod(q"def tp[..$tparams](..$vargs): $fullName = argon.proto(new $name[..$targs](..$vnames))".asDef)
      case _ =>         obj.injectMethod(q"def tp[..$tparams](..$vargs)(..$iargs): $fullName = argon.proto(new $name[..$targs](..$vnames)(..$inames))".asDef)
    }

    (cls2, obj2)
  }

  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import util._
    import c.universe._

    val (cls,obj) = annottees.toList match {
      case List(cd: ClassDef, md: ModuleDef) => (cd,md)
      case List(cd: ClassDef) => (cd, q"object ${cd.nameTerm}".asObject)
      case _ => invalidAnnotationUse("ref", "classes")
    }

    val (cls2, obj2) = implement(c)(cls, obj)

    //c.info(c.enclosingPosition, showCode(cls2), force = true)
    //c.info(c.enclosingPosition, showCode(obj2), force = true)

    q"..${List(cls2,obj2)}"
  }
} 
Example 54
Source File: NgModule.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2
// Description: Angular2 @NgModule macro annotation

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.core

import angulate2.internal.ClassDecorator

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("@angular/core","NgModule")
object NgModuleFacade extends js.Object {
  def apply() : js.Object = js.native
  def apply(options: js.Object) : js.Object = js.native
}

// NOTE: keep the constructor parameter list and Component.Macro.annotationParamNames in sync!
@compileTimeOnly("enable macro paradise to expand macro annotations")
class NgModule(providers: js.Array[js.Any] = null,
               declarations: js.Array[js.Any] = null,
               imports: js.Array[js.Any] = null,
               exports: js.Array[js.Any] = null,
               entryComponents: js.Array[js.Any] = null,
               bootstrap: js.Array[js.Any] = null,
               schemas: js.Array[js.Any] = null,
               id: String = null) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro NgModule.Macro.impl
}

object NgModule {
  private[angulate2] class Macro(val c: whitebox.Context) extends ClassDecorator {
    import c.universe._

    val annotationParamNames = Seq(
      "providers",
      "declarations",
      "imports",
      "exports",
      "entryComponents",
      "bootstrap",
      "schemas",
      "id"
    )

    override val annotationName: String = "NgModule"

    override def mainAnnotationObject = q"angulate2.core.NgModuleFacade"
  }

} 
Example 55
Source File: data.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros

final class data extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro data.impl
}

object data {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val utils = new MacroUtils(c)
    import utils._
    import c.universe._
    annottees.head match {
      case _:ModuleDef => stateful.impl(c)(annottees:_*)
      case _ => invalidAnnotationUse("data", "objects")
    }
  }
} 
Example 56
Source File: globalRewrite.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros

final class globalRewrite extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro globalRewrite.impl
}

object globalRewrite {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import c.universe._
    import util._

    annottees.head match {
      case _:DefDef =>
      case _ => c.error(c.enclosingPosition, "@globalRewrite can only be used on defs")
    }
    def incorrectSignature(): Unit = {
      c.error(c.enclosingPosition, "@globalRewrite def must have signature 'def name(rhs: T): Unit")
    }
    def noImplicitsAllowed(): Unit = {
      c.error(c.enclosingPosition, "@globalRewrite def cannot have implicit parameters")
    }
    def noTypeParametersAllowed(): Unit = {
      c.error(c.enclosingPosition, "@globalRewrite def cannot have type parameters")
    }

    val tree = api.impl(c)(annottees:_*) match {
      case d: DefDef =>
        val paramss = d.paramss
        if (paramss.length != 2) incorrectSignature()
        else if (paramss.head.length != 1) incorrectSignature()
        else if (paramss(1).length != 2) noImplicitsAllowed()
        else if (d.tparams.nonEmpty) noTypeParametersAllowed()

        val arg0 = paramss.head.head
        val name = Literal(Constant(d.name.toString))
        d.rhs match {
          case Match(_,_) =>
          case _ => c.error(c.enclosingPosition, "@globalRewrite rule must be a partial function")
        }

        val pf =
          q"""val ${d.name}: PartialFunction[(Op[_],SrcCtx,State),Option[Sym[_]]] = {case (__op,__ctx,__state) =>
            if (__op.isInstanceOf[${arg0.tp.get}]) {
              val ${arg0.name} = __op.asInstanceOf[${arg0.tp.get}];
              implicit val ctx = __ctx;
              implicit val state = __state;
              val func: PartialFunction[Op[_],Sym[_]] = ${d.rhs}
              if (func.isDefinedAt(${arg0.name})) Some(func.apply(${arg0.name})) else None
            }
            else None
          }
          """
        val add =
          q"""
             core.rewrites.addGlobal($name,${d.name})
           """
        q"$pf; $add"

      case t =>
        c.error(c.enclosingPosition, "@globalRewrite can only be used on defs")
        t
    }
    c.info(c.enclosingPosition, showCode(tree), force = true)
    tree
  }
} 
Example 57
Source File: flow.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros

final class flow extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro flow.impl
}

object flow {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import c.universe._
    import util._

    annottees.head match {
      case _:DefDef =>
      case _ => c.error(c.enclosingPosition, "@flow can only be used on defs")
    }
    def incorrectSignature(): Unit = {
      c.error(c.enclosingPosition, "@flow def must have signature 'def name(lhs: Sym[_], rhs: Op[_]): Unit")
    }

    val tree = api.impl(c)(annottees:_*) match {
      case d: DefDef =>
        val paramss = d.paramss
        if (paramss.length != 2) incorrectSignature()
        else if (paramss.head.length != 2) incorrectSignature()
        val arg0 = paramss.head.apply(0)
        val arg1 = paramss.head.apply(1)
        if (!arg0.tp.exists{t => isWildcardType(t, "Sym") } || !arg1.tp.exists{t => isWildcardType(t, "Op")}) {
          incorrectSignature()
        }

        val name = Literal(Constant(d.name.toString))

        val pf =
          q"""val ${d.name}: PartialFunction[(Sym[_],Op[_],forge.SrcCtx,argon.State),Unit] = {case (__sym,__op,__ctx,__state) =>
            val ${arg0.name} = __sym;
            val ${arg1.name} = __op;
            implicit val ctx = __ctx;
            implicit val state = __state;
            ${d.rhs}
          }
          """
        val add =
          q"""
             IR.flows.add($name,${d.name})
           """
        q"$pf; $add"

      case t =>
        __c.error(__c.enclosingPosition, "@flow can only be used on defs")
        t
    }
    //c.info(c.enclosingPosition, showCode(tree), force = true)
    tree
  }
} 
Example 58
Source File: mod.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros


final class mod extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro mod.impl
}
object mod {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import c.universe._
    import util._

    val tree = annottees.head match {
      case cls: ClassDef =>
        val names = cls.constructorArgs.head.map(_.name)

        //cls.asCaseClass.injectMethod(q"final override def names = Seq(..$names)")
        cls

      case t =>
        c.error(c.enclosingPosition, "@mod annotation can only be used on classes.")
        t
    }

    c.info(c.enclosingPosition, showCode(tree), force = true)
    tree
  }
} 
Example 59
Source File: curriedUpdate.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox


class curriedUpdate extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro curriedUpdate.impl
}

object curriedUpdate {
  private val updateRenamed = "update$r"

  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    import c.universe._

    annottees.head match {
      case DefDef(mods, TermName(name), tparams, vparamss, tpt, rhs) =>
        if (name.toString != "update")
          c.abort(c.enclosingPosition, "curriedUpdate can only be applied to the update method")
        if (vparamss.size != 3)
          c.abort(c.enclosingPosition, "curriedUpdate must have three argument list")
        if (vparamss.head.isEmpty)
          c.abort(c.enclosingPosition, "The first argument list must not be empty")
        if (vparamss(1).size != 1)
          c.abort(c.enclosingPosition, "The second argument list must have only one element")
        if (vparamss(2).size != 2)
          c.abort(c.enclosingPosition, "The third argument list must have two elements")

        val imprt   = q"import scala.language.experimental.macros"
        val updateR = DefDef(mods, TermName(updateRenamed), tparams, vparamss, tpt, rhs)
        val updateC = if (mods.hasFlag(Flag.OVERRIDE)) {
          q"override def update(values: Any*): Unit = macro forge.tags.curriedUpdate.updateMacroDispatcher"
        }
        else {
          q"def update(values: Any*): Unit = macro forge.tags.curriedUpdate.updateMacroDispatcher"
        }

        val result = q"$imprt ; $updateR ; $updateC"

        //c.info(c.enclosingPosition, showCode(result), true)
        result

      case _ =>
        c.abort(c.enclosingPosition, "curriedUpdate can only be applied on defs")
    }
  }

  def updateMacroDispatcher(c: blackbox.Context)(values: c.Tree*): c.Tree = {
    import c.universe._

    val inds = values.take(values.size - 3)
    val value = values(values.size - 3)
    val ctx = values(values.size - 2)
    val state = values(values.size - 1)
    val self = c.prefix.tree
    q"$self.${TermName(updateRenamed)}(..$inds)($value)($ctx, $state)"
  }
} 
Example 60
Source File: ctx.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros

final class ctx extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro ctx.impl
}

private[forge] object ctx {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import util._
    import c.universe._

    val tree = annottees.head match {
      case df: DefDef => df.injectImplicit("ctx", tq"forge.SrcCtx", tq"SrcCtx")
      case _ => invalidAnnotationUse("ctx", "defs")
    }
    tree
  }
} 
Example 61
Source File: stateful.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.blackbox


final class stateful extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro stateful.impl
}

private[forge] object stateful {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import util._
    import c.universe._

    def injectState(df: DefDef) = df.injectImplicit("state", tq"argon.State", tq"State")

    val tree = annottees.head match {
      case df: DefDef    => injectState(df)
      case mf: ModuleDef => mf.mapMethods(injectState)
      case _ => invalidAnnotationUse("stateful", "objects", "defs")
    }
    tree
  }
} 
Example 62
Source File: rewrite.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import utils.tags.MacroUtils

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros

final class rewrite extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro rewrite.impl
}

object rewrite {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val util = new MacroUtils[c.type](c)
    import c.universe._
    import util._

    annottees.head match {
      case _:DefDef =>
      case _ => c.error(c.enclosingPosition, "Rewrite can only be used on defs")
    }
    def incorrectSignature(): Unit = {
      c.error(c.enclosingPosition, "Rewrite def must have signature 'def name(rhs: T): Unit")
    }
    def noImplicitsAllowed(): Unit = {
      c.error(c.enclosingPosition, "Rewrite def cannot have implicit parameters")
    }
    def noTypeParametersAllowed(): Unit = {
      c.error(c.enclosingPosition, "Rewrite def cannot have type parameters")
    }

    val tree = api.impl(c)(annottees:_*) match {
      case d: DefDef =>
        val paramss = d.paramss
        if (paramss.length != 2) incorrectSignature()
        else if (paramss.head.length != 1) incorrectSignature()
        else if (paramss(1).length != 2) noImplicitsAllowed()
        else if (d.tparams.nonEmpty) noTypeParametersAllowed()

        val arg0 = paramss.head.head
        val name = Literal(Constant(d.name.toString))
        d.rhs match {
          case Match(_,_) =>
          case _ => c.error(c.enclosingPosition, "Rewrite rule must be a partial function")
        }

        val pf =
          q"""val ${d.name}: PartialFunction[(Op[_],SrcCtx,State),Option[Sym[_]]] = {case (__op,__ctx,__state) =>
            val ${arg0.name} = __op.asInstanceOf[${arg0.tp.get}];
            implicit val ctx = __ctx;
            implicit val state = __state;
            val func: PartialFunction[Op[_],Sym[_]] = ${d.rhs}
            if (func.isDefinedAt(${arg0.name})) Some(func.apply(${arg0.name})) else None
          }
          """
        val add = if (!showCode(arg0.tp.get).startsWith("Op[")) {
          q"""IR.rewrites.add[${arg0.tp.get}]($name,${d.name})"""
        }
        else {
          q"""IR.rewrites.addGlobal($name,${d.name})"""
        }
        q"$pf; $add"

      case t =>
        invalidAnnotationUse("rewrite", "defs")
        t
    }
    //c.info(c.enclosingPosition, showCode(tree), force = true)
    tree
  }
} 
Example 63
Source File: rig.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox
import scala.language.experimental.macros

final class rig extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro rig.impl
}

object rig {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    val withCtx   = ctx.impl(c)(annottees:_*)
    val withState = stateful.impl(c)(withCtx)
    withState
  }
} 
Example 64
Source File: Facades.scala    From scalapy   with MIT License 5 votes vote down vote up
package me.shadaj.scalapy.py

import scala.reflect.macros.whitebox
import scala.language.experimental.macros

import scala.annotation.StaticAnnotation
class native extends StaticAnnotation

object FacadeImpl {
  def creator[T <: Any](c: whitebox.Context)(implicit tag: c.WeakTypeTag[T]): c.Tree = {
    import c.universe._

    if (!tag.tpe.typeSymbol.annotations.exists(_.tpe =:= typeOf[native])) {
      c.error(c.enclosingPosition, "Cannot derive a creator for a trait that is not annotated as @py.native")
    }
    
    q"""new _root_.me.shadaj.scalapy.py.FacadeCreator[${tag.tpe}] {
      def create(value: _root_.me.shadaj.scalapy.py.PyValue) = new _root_.me.shadaj.scalapy.py.FacadeValueProvider(value) with ${tag.tpe} {}
    }"""
  }

  def native_impl[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[T] = {
    import c.universe._

    if (!c.enclosingClass.symbol.annotations.exists(_.tpe =:= typeOf[native])) {
      c.error(c.enclosingPosition, "py.native implemented functions can only be declared inside traits annotated as @py.native")
    }

    val method = c.internal.enclosingOwner.asMethod
    val methodName = method.name.toString
    val returnType = method.returnType
    val paramss = method.paramLists

    paramss.headOption match {
      case Some(params) =>
        val paramExprs = params.map(_.name)
        c.Expr[T](q"as[_root_.me.shadaj.scalapy.py.Dynamic].applyDynamic($methodName)(..$paramExprs).as[$returnType]")
      case scala.None =>
        c.Expr[T](q"as[_root_.me.shadaj.scalapy.py.Dynamic].selectDynamic($methodName).as[$returnType]")
    }
  }

  def native_named_impl[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[T] = {
    import c.universe._

    if (!c.enclosingClass.symbol.annotations.exists(_.tpe =:= typeOf[native])) {
      c.error(c.enclosingPosition, "py.native implemented functions can only be declared inside traits annotated as @py.native")
    }

    val method = c.internal.enclosingOwner.asMethod
    val methodName = method.name.toString
    val returnType = method.returnType
    val paramss = method.paramLists

    paramss.headOption match {
      case Some(params) =>
        val paramExprs = params.map { p =>
          val paramName = q"${p.asTerm}".toString
          s"""("${p.name}", $paramName)"""
        }

        c.Expr[T](c.parse(s"""as[_root_.me.shadaj.scalapy.py.Dynamic].applyDynamicNamed("$methodName")(${paramExprs.mkString(",")}).as[$returnType]"""))

      case scala.None =>
        c.Expr[T](q"as[_root_.me.shadaj.scalapy.py.Dynamic].selectDynamic($methodName).as[$returnType]")
    }
  }
} 
Example 65
Source File: autoSemigroupalK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoSemigroupalK")
class autoSemigroupalK extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoSemigroupalKMacros.semigroupalKInst
}

private[tagless] class autoSemigroupalKMacros(override val c: whitebox.Context) extends MacroUtils  {
  import c.universe._

  private def generateSemigroupalKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("semigroupalKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.SemigroupalK[$algebraType]",
      q"_root_.cats.tagless.Derive.semigroupalK[$algebraType]"
    )

  def semigroupalKInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList) { algebra =>
      algebra.forVaryingEffectType(generateSemigroupalKFor(algebra.name)) :: Nil
    }
} 
Example 66
Source File: autoContravariant.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoContravariant")
class autoContravariant extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoContravariantMacros.contravariantInst
}

private[tagless] class autoContravariantMacros(override val c: whitebox.Context) extends MacroUtils  {
  import c.universe._

  private def generateContravariantFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("contravariantFor" + algebraName),
      typeParams,
      tq"_root_.cats.Contravariant[$algebraType]",
      q"_root_.cats.tagless.Derive.contravariant[$algebraType]"
    )

  def contravariantInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateContravariantFor(algebra.name)) :: Nil
    }
} 
Example 67
Source File: autoFunctorK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoFunctorK")
class autoFunctorK(autoDerivation: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoFunctorKMacros.newDef
}

private [tagless] class autoFunctorKMacros(override val c: whitebox.Context) extends MacroUtils with CovariantKMethodsGenerator {
  import c.universe._

  private def generateFunctorKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("functorKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.FunctorK[$algebraType]",
      q"_root_.cats.tagless.Derive.functorK[$algebraType]"
    )

  def instanceDef(algebra: AlgDefn.UnaryAlg): Tree =
    algebra.forVaryingEffectType(generateFunctorKFor(algebra.name))

  def instanceDefFullyRefined(algDefn: AlgDefn.UnaryAlg): Tree = {
    algDefn.forVaryingEffectTypeFullyRefined {
      (algebraType, tparams) =>
        val impl = Seq(
          generateFunctorKFor("FullyRefined" + algDefn.name)(
            algebraType,
            tparams
          ),
          generateAutoDerive(algDefn.fullyRefinedTypeSig)(
            algebraType,
            tparams
          )
        )
        q"object fullyRefined { ..$impl }"
    }
  }

  def newDef(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList)(
      algebra => instanceDef(algebra) :: companionMapKDef(algebra) :: instanceDefFullyRefined(algebra) :: autoDerivationDef(algebra) :: Nil)
}

private [tagless] trait CovariantKMethodsGenerator { self: MacroUtils =>
  import c.universe._

  def companionMapKDef(algDefn: AlgDefn.UnaryAlg) = {
    val from = TermName("af")
    val F = createFreshTypeParam("F", 1)
    val G = createFreshTypeParam("G", 1)
    val algebraF = algDefn.newTypeSig(F)
    val fullyRefinedAlgebraG = algDefn.dependentRefinedTypeSig(G, from)

    algDefn.forVaryingEffectType((algebraType, tparams) => q"""
      def mapK[$F, $G, ..$tparams]($from: $algebraF)(fk: _root_.cats.~>[..${tArgs(F, G)}]): $fullyRefinedAlgebraG =
        _root_.cats.tagless.FunctorK[$algebraType].mapK($from)(fk).asInstanceOf[$fullyRefinedAlgebraG]
    """)
  }

  def generateAutoDerive(newTypeSig: TypeDef => TypTree)(algebraType: Tree, tparams: Seq[TypeDef]) = {
    val F = createFreshTypeParam("F", 1)
    val G = createFreshTypeParam("G", 1)
    val algebraF = newTypeSig(F)
    val algebraG = newTypeSig(G)

    q"""
      object autoDerive {
        @SuppressWarnings(Array("org.wartremover.warts.ImplicitParameter"))
        implicit def fromFunctorK[$F, $G, ..$tparams](
          implicit fk: _root_.cats.~>[..${tArgs(F, G)}],
          FK: _root_.cats.tagless.FunctorK[$algebraType],
          af: $algebraF)
          : $algebraG = FK.mapK(af)(fk)
      }"""
  }

  def autoDerivationDef(algDefn: AlgDefn.UnaryAlg) =
    if(autoDerive) algDefn.forVaryingEffectType(generateAutoDerive(algDefn.newTypeSig)) else EmptyTree

} 
Example 68
Source File: autoSemigroupal.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoSemigroupal")
class autoSemigroupal extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoSemigroupalMacros.semigroupalInst
}


private[tagless] class autoSemigroupalMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateSemigroupalFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("semigroupalFor" + algebraName),
      typeParams,
      tq"_root_.cats.Semigroupal[$algebraType]",
      q"_root_.cats.tagless.Derive.semigroupal[$algebraType]"
    )

  def semigroupalInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateSemigroupalFor(algebra.name)) :: Nil
    }
} 
Example 69
Source File: autoInvariantK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoInvariantK")
class autoInvariantK(autoDerivation: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoInvariantKMacros.newDef
}

private [tagless] class autoInvariantKMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateInvariantKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("invariantKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.InvariantK[$algebraType]",
      q"_root_.cats.tagless.Derive.invariantK[$algebraType]"
    )

  def instanceDef(algebra: AlgDefn.UnaryAlg): Tree =
    algebra.forVaryingEffectType(generateInvariantKFor(algebra.name))

  def instanceDefFullyRefined(algDefn: AlgDefn.UnaryAlg): Tree = {
    algDefn.forVaryingEffectTypeFullyRefined {
      (algebraType, tparams) =>
        val impl = Seq(
          generateInvariantKFor("FullyRefined" + algDefn.name)(
            algebraType,
            tparams
          ),
          generateAutoDerive(algDefn.fullyRefinedTypeSig)(
            algebraType,
            tparams
          )
        )
        q"object fullyRefined { ..$impl }"
    }
  }

  def companionIMapKDef(algDefn: AlgDefn.UnaryAlg) = {
    val from = TermName("af")
    val F = createFreshTypeParam("F", 1)
    val G = createFreshTypeParam("G", 1)
    val algebraF = algDefn.newTypeSig(F)
    val fullyRefinedAlgebraG = algDefn.dependentRefinedTypeSig(G, from)

    algDefn.forVaryingEffectType((algebraType, tparams) => q"""
      def imapK[$F, $G, ..$tparams]($from: $algebraF)(fk: _root_.cats.~>[..${tArgs(F, G)}])(gk: _root_.cats.~>[..${tArgs(G, F)}]): $fullyRefinedAlgebraG =
        _root_.cats.tagless.InvariantK[$algebraType].imapK($from)(fk)(gk).asInstanceOf[$fullyRefinedAlgebraG]
    """)
  }

  def generateAutoDerive(newTypeSig: TypeDef => TypTree)(algebraType: Tree, tparams: Seq[TypeDef]) = {
    val F = createFreshTypeParam("F", 1)
    val G = createFreshTypeParam("G", 1)
    val algebraF = newTypeSig(F)
    val algebraG = newTypeSig(G)

    q"""
      object autoDerive {
        @SuppressWarnings(Array("org.wartremover.warts.ImplicitParameter"))
        implicit def fromFunctorK[$F, $G, ..$tparams](
          implicit af: $algebraF,
          IK: _root_.cats.tagless.InvariantK[$algebraType],
          fk: _root_.cats.~>[..${tArgs(F, G)}],
          gk: _root_.cats.~>[..${tArgs(G, F)}])
          : $algebraG = IK.imapK(af)(fk)(gk)
      }"""
  }

  def autoDerivationDef(algDefn: AlgDefn.UnaryAlg) =
    if(autoDerive) algDefn.forVaryingEffectType(generateAutoDerive(algDefn.newTypeSig)) else EmptyTree

  def newDef(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList)(algebra => instanceDef(algebra) :: companionIMapKDef(algebra) :: instanceDefFullyRefined(algebra) :: autoDerivationDef(algebra) :: Nil)
} 
Example 70
Source File: autoProductNK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoProductK")
class autoProductNK extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoProductNKMacros.productKInst
}

private [tagless] class autoProductNKMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  def productMethod(typedef: TypeDefinition)(arity: Int): Tree = {
    def af(n: Int) = TermName("af" + n)

    val name = typedef.ident
    val range = 1 to arity

    // tparam"F1[_], F2[_], F3[_]"
    val effectTypeParams: List[TypeDef] =
      range.map(n => createTypeParam("F" + n, 1)).toList
    val effectTypeParamsNames = tArgs(effectTypeParams)

    //Tuple3K
    val productTypeName = tq"_root_.cats.tagless.${TypeName("Tuple" + arity + "K")}"

    val methods = typedef.impl.body.map {
      case q"def $method[..$typeParams](...$paramLists): ${_}[$resultType]" =>
        val returnItems = range.map(n => q"${af(n)}.$method(...${argumentLists(paramLists)})")
        q"""def $method[..$typeParams](...$paramLists): $productTypeName[..$effectTypeParamsNames]#λ[$resultType] =
           (..$returnItems)
        """

      case statement =>
        abort(s"autoProductK does not support algebra with such statement: $statement")
    }

    //af1: A[F1], af2: A[F2], af3: A[F3]
    val inboundInterpreters: Seq[ValDef] =
      (range zip effectTypeParamsNames).map {
        case (idx, fx) =>
          ValDef(
            Modifiers(Flag.PARAM),
            af(idx),
            typedef.applied(fx),
            EmptyTree
          )
      }

    q"""
        def ${TermName("product" + arity + "K")}[..$effectTypeParams](..$inboundInterpreters): $name[$productTypeName[..$effectTypeParamsNames]#λ] =
          new $name[$productTypeName[..$effectTypeParamsNames]#λ] {
            ..$methods
          }
      """

  }

  def productKInst(annottees: c.Tree*): c.Tree =
    enrich(annottees.toList) { td =>
      val productMethods = (3 to 9).map(productMethod(td))
      Seq(td.defn, addStats(td.companion, productMethods))
    }
} 
Example 71
Source File: autoApply.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoApply")
class autoApply extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoApplyMacros.applyInst
}


private[tagless] class autoApplyMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateApplyFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("applyFor" + algebraName),
      typeParams,
      tq"_root_.cats.Apply[$algebraType]",
      q"_root_.cats.tagless.Derive.apply[$algebraType]"
    )

  def applyInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateApplyFor(algebra.name)) :: Nil
    }
} 
Example 72
Source File: autoApplyK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoApplyK")
class autoApplyK(autoDerivation: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoApplyKMacros.newDef
}

private [tagless] class autoApplyKMacros(override val c: whitebox.Context) extends MacroUtils with CovariantKMethodsGenerator {
  import c.universe._

  private def generateApplyKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("applyKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.ApplyK[$algebraType]",
      q"_root_.cats.tagless.Derive.applyK[$algebraType]"
    )

  def instanceDef(algebra: AlgDefn.UnaryAlg): Tree =
    algebra.forVaryingEffectType(generateApplyKFor(algebra.name))

  def newDef(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList)(algebra => instanceDef(algebra) :: companionMapKDef(algebra) :: autoDerivationDef(algebra) :: Nil)
} 
Example 73
Source File: SealedTraitSpec.scala    From pushka   with Apache License 2.0 5 votes vote down vote up
import org.scalatest._
import pushka._
import pushka.annotation.pushka

import scala.annotation.StaticAnnotation

object SealedTraitSpec {

  abstract class Rgb(r: Int, g: Int, b: Int)

  @pushka sealed trait Color

  object Color {
    case object Red extends Rgb(255, 0, 0) with Color
    case object Green extends Rgb(0, 255, 0) with Color
    case object Blue extends Rgb(0, 0, 255) with Color
  }

  @pushka sealed trait WithBody {
    def x: Int
  }

  object WithBody {
    case object A extends WithBody { val x = 0 }
    case class B(y: Int) extends WithBody { val x = 1 }
  }

  @pushka sealed trait User

  object User {
    case object Empty extends User
    case class Name(first: String, last: String) extends User
    case object Anonymous extends User
  }

  @pushka case class Container(user: User, anotherField: Int)

  class theAnnotation(a: String, b: String) extends StaticAnnotation

  @pushka sealed trait Base

  object Base {
    @theAnnotation("Some message", "Today")
    case class Descendant(value: Int) extends Base

    object Descendant {
      def haha(): Unit = {}
    }
  }
}

class SealedTraitSpec extends FlatSpec with Matchers {

  import SealedTraitSpec._

  "ADT based on case class" should "writes by case class rules in property" in {
    val instance = Container(User.Name("John", "Doe"), 10)
    write(instance) should be(
      Ast.Obj(Map(
        "user" → Ast.Obj(Map(
          "name" → Ast.Obj(Map(
            "first" → Ast.Str("John"),
            "last" → Ast.Str("Doe"))
          ))),
        "anotherField" → Ast.Num("10")
      ))
    )
  }

  "ADT based on case object" should "writes as simple string" in {
    val instance = Container(User.Empty, 10)
    write(instance) should be(
      Ast.Obj(Map(
        "user" → Ast.Str("empty"),
        "anotherField" → Ast.Num("10"
        ))
      )
    )
  }

  "Sealed trait with body" should "be processed" in {
    write[WithBody](WithBody.A) shouldEqual Ast.Str("a")
    write[WithBody](WithBody.B(1)) shouldEqual Ast.Obj(Map("b" → Ast.Num(1)))
  }

  "Deprecated annotation in case classes" should "not breaks writing" in {
    write[Base](Base.Descendant(42))
  }

  "Color" should "be read correctly" in {
    read[Color](Ast.Str("red")) shouldBe Color.Red
  }

  it should "throw exception with correct message if Ast is invalid" in {
    val invalidAst = Ast("foo" → "bar")
    val exception = intercept[PushkaException] {
      read[Color](invalidAst)
    }
    exception.message should be(s"Error while reading AST $invalidAst to Color")
  }
} 
Example 74
Source File: virtualize.scala    From spatial   with MIT License 5 votes vote down vote up
package forge.tags

import language.experimental.macros
import scala.annotation.StaticAnnotation
import scala.reflect.macros.blackbox


    val inputs = annottees.toList
    val outputs = inputs match {
      case (a:ValDef) :: as if a.mods.hasFlag(Flag.PARAM) =>
        c.warning(c.enclosingPosition, "@virtualize cannot be used on parameters.")
        inputs
      case (_:TypeDef) :: as =>
        c.warning(c.enclosingPosition, "@virtualize cannot be used on type aliases.")
        inputs

      case a :: as => runVirtualizer(a) ::: as
      case Nil     => Nil
    }

    //info(showCode(outputs.head))

    q"..$outputs"
  }
} 
Example 75
Source File: ServiceMethod.scala    From typebus   with MIT License 5 votes vote down vote up
package io.surfkit.typebus.annotations

import java.nio.file.Files

import io.surfkit.typebus.ResourceDb
import play.api.libs.json.{Json, OFormat, Format}

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

@compileTimeOnly("enable macro to expand macro annotations")
class ServiceMethod extends StaticAnnotation {
  def macroTransform(annottees: Any*) = macro ServiceMethod.impl
}

object ServiceMethod extends ResourceDb{

  val databaseTableName = "_Service"

  sealed trait Store
  object Store{
    implicit val format: OFormat[Store] = Json.format[Store]
  }
  final case class ServiceMethod(in: String, out: String) extends Store
  object ServiceMethod{
    implicit val format: Format[ServiceMethod] = Json.format[ServiceMethod]
  }
  final case class ServiceStore(methods: Set[ServiceMethod]) extends Store
  object ServiceStore{
    implicit val format: Format[ServiceStore] = Json.format[ServiceStore]
  }

  var methods = Set.empty[ServiceMethod]

  def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    val result =
      annottees.map(_.tree).toList match {
        case q"$mods def $methodName[..$tpes]($arg, meta: EventMeta): Future[$returnType] = { ..$body }" :: Nil =>
        //case q"$mods def $methodName[..$tpes]($arg, meta: EventMeta): Future[$returnType]{..$body}" :: Nil =>
          // https://stackoverflow.com/questions/19379436/cant-access-parents-members-while-dealing-with-macro-annotations
          val retTpe = c.typecheck(q"(??? : $returnType)").tpe
          val argChild = arg.children.head
          val argTpe = c.typecheck(q"(??? : $argChild)").tpe
          //println(s"retTpe:${retTpe}  ${retTpe.typeSymbol.fullName}")
          //println(s"argTpe:${argTpe}  ${argTpe.typeSymbol.fullName}")
          // FIXME: packaging a jar will fail when trying to access the resource files.  For now we can skip this.
          try {
            methods += ServiceMethod(argTpe.typeSymbol.fullName, retTpe.typeSymbol.fullName)
            val servicePath = databaseTablePath(databaseTableName)
            Files.write(servicePath, serialiseServiceStore(ServiceStore(methods)).getBytes)
          }catch{
            case _: Throwable =>
          }
          q"""$mods def $methodName[..$tpes]($arg, meta: EventMeta): Future[$returnType] = { ..$body }"""

        case _ => c.abort(c.enclosingPosition, s"Annotation @ServiceMethod can be used only with methods of the form (T, EventMeta) => Future[U] instead of: ${annottees.map(_.tree).toList}")
      }
    c.Expr[Any](result)
  }

  def serialiseServiceStore(value: ServiceStore): String = Json.toJson(value).toString()
    //Pickle.intoBytes(value).array

  def deSerialiseServiceStore(json: String): ServiceStore = Json.parse(json).as[ServiceStore]
    //Unpickle[ServiceStore].fromBytes(java.nio.ByteBuffer.wrap(bytes))
} 
Example 76
Source File: annotations.scala    From freestyle   with Apache License 2.0 5 votes vote down vote up
package freestyle
package free

import scala.annotation.{compileTimeOnly, StaticAnnotation}
import freestyle.free.internal.{freeImpl, moduleImpl}

@compileTimeOnly("enable macro paradise to expand @free macro annotations")
class free extends StaticAnnotation {
  import scala.meta._

  inline def apply(defn: Any): Any = meta { freeImpl.free(defn) }
}

@compileTimeOnly("enable macro paradise to expand @module macro annotations")
class module extends StaticAnnotation {
  import scala.meta._

  inline def apply(defn: Any): Any = meta { moduleImpl.module(defn) }
}

class debug extends StaticAnnotation 
Example 77
Source File: annotations.scala    From freestyle   with Apache License 2.0 5 votes vote down vote up
package freestyle
package tagless

import freestyle.tagless.internal._

import scala.meta._
import scala.annotation.{StaticAnnotation, compileTimeOnly}

@compileTimeOnly("enable macro paradise to expand @tagless macro annotations")
class tagless(val stacksafe: Boolean) extends StaticAnnotation {
  import scala.meta._

  inline def apply(defn: Any): Any = meta {
    val stacksafe: Boolean = this match {
      case q"new $_(${Lit.Boolean(ss)})" => ss
      case q"new $_(stacksafe = ${Lit.Boolean(ss)})" => ss
      case _ => false
    }
    taglessImpl.tagless(defn, stacksafe)
  }
}

@compileTimeOnly("enable macro paradise to expand @module macro annotations")
class module extends StaticAnnotation {
  import scala.meta._

  inline def apply(defn: Any): Any = meta { moduleImpl.module(defn) }
} 
Example 78
Source File: ReaderOfMacro.scala    From grafter   with MIT License 5 votes vote down vote up
package org.zalando.grafter.macros

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import ReaderMacros._


object ReaderOfMacro {

  val annotationName = "readerOf"

  def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    def name(t: Name) = t.decodedName.toString.trim

    val (classTree, companionTree): (Tree, Option[Tree]) =
      annotationInputs(c)(annotationName)(annottees)

    classTree match {

      case ClassDef(_, className, _, Template(_, _, fields)) =>
        val typeParam  = typeParameter(annotationName)(c)
        def params     = fieldsNamesAndTypes(c)(fields)
        val paramNames = params.map(_._1).distinct
        val implicits  = params.map { case (p, _type) => q"""private val ${TermName("_"+name(p))}: cats.data.Reader[$typeParam, ${_type}] = implicitly[cats.data.Reader[$typeParam, ${_type}]];""" }
        val readValues = paramNames.map { p => q"""val ${TermName("_"+name(p)+"Value")} = ${TermName("_"+name(p))}.apply(r);""" }
        val values     = paramNames.map { p => q"""${TermName("_"+name(p)+"Value")}""" }
        val klassName  = name(className)

        val reader =
          c.Expr[Any](
            q"""
             implicit val reader: cats.data.Reader[$typeParam, ${TypeName(klassName)}] = {
               cats.data.Reader { r =>
                 ..$readValues
                 new ${TypeName(klassName)}(...${List(values)})
               }
             }
             """)

        outputs(c)(classTree, className, companionTree) {
          q"""
         ..$implicits

         ..$reader
      """
        }

      case other =>
        c.abort(c.macroApplication.pos, s"the @$annotationName annotation must annotate a class, found $other")
    }

  }

}

class readerOf[A] extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro ReaderOfMacro.impl
} 
Example 79
Source File: DefaultReaderMacro.scala    From grafter   with MIT License 5 votes vote down vote up
package org.zalando.grafter.macros

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import ReaderMacros._

object DefaultReaderMacro {

  val annotationName = "defaultReader"

  def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    val (classTree, companionTree): (Tree, Option[Tree]) =
      annotationInputs(c)(annotationName)(annottees)

    classTree match {
      case ClassDef(_, className, typeParams, _) =>
        val genericTypeName = internal.reificationSupport.freshTypeName("A")
        val typeParam = typeParameter(annotationName)(c)

        typeParams match {
          case _ :: Nil =>
            outputs(c)(classTree, className, companionTree) {
              q"""
         implicit def reader[$genericTypeName, F[_]](implicit defaultReader: cats.data.Reader[$genericTypeName, $typeParam[F]]): cats.data.Reader[$genericTypeName, $className[F]] =
           org.zalando.grafter.GenericReader.widenReader(defaultReader)
      """
            }

          case Nil =>
            outputs(c)(classTree, className, companionTree) {
              q"""
         implicit def reader[$genericTypeName](implicit defaultReader: cats.data.Reader[$genericTypeName, $typeParam]): cats.data.Reader[$genericTypeName, $className] =
           org.zalando.grafter.GenericReader.widenReader(defaultReader)
      """
            }

          case other =>
            c.abort(c.macroApplication.pos, s"the @$annotationName annotation must specify a type containing at most one type parameter, found $other")

        }

      case other =>
        c.abort(c.macroApplication.pos, s"the @$annotationName annotation must annotate a trait, found $other")
    }
  }

}

class defaultReader[A] extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro DefaultReaderMacro.impl
} 
Example 80
Source File: Routes.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description: Angulate2 extension for simplified creation of routing modules

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.ext

import angulate2.internal.ClassDecorator
import angulate2.router.Route

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js

@compileTimeOnly("enable macro paradise to expand macro annotations")
class Routes(root: Boolean, routes: Route*) extends StaticAnnotation {
  def this(providers: js.Array[js.Any])(root: Boolean, routes: Route*) = this(root,routes:_*)
  def macroTransform(annottees: Any*): Any = macro Routes.Macro.impl
}

object Routes {
  private[angulate2] class Macro(val c: whitebox.Context) extends ClassDecorator {
    import c.universe._

    val annotationParamNames = Seq(
      "root",
      "routes*"
    )

    override val firstArglistParamNames = Seq(
      "providers"
    )

    override val annotationName: String = "Routes"

    override def mainAnnotationObject = q"angulate2.core.NgModuleFacade"

    private val routerModule = q"angulate2.ops.@@[angulate2.router.RouterModule]"

    override def analyze: Analysis = super.analyze andThen {
      case (cls: ClassParts, data) =>
        val cdd = ClassDecoratorData(data)
        val routes = q"scalajs.js.Array(..${cdd.annotParams("routes")})"
        val remainingParams = cdd.annotParams - "root" - "routes"

        val imports = cdd.annotParams("root") match {
          case Literal(Constant(true)) => q"scalajs.js.Array(angulate2.router.RouterModule.forRoot($routes))"
          case Literal(Constant(false)) => q"scalajs.js.Array(angulate2.router.RouterModule.forChild($routes))"
        }
        (cls, ClassDecoratorData.update(data,cdd.copy(annotParams = remainingParams ++ Map("imports" -> imports, "exports" -> routerModule))))
      case default => default
    }

  }
} 
Example 81
Source File: debug.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description: Annotation to enable debugging of its annottee

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.ext

import scala.annotation.StaticAnnotation


@deprecated("Use angulate2.std.debug or de.surfice.smacrotools.debug instead","0.0.5")
class debug(showExpansion: Boolean = true,
            logInstances: Boolean = true) extends StaticAnnotation

object debug {
  private[angulate2] case class DebugConfig(showExpansion: Boolean,
                                            logInstances: Boolean)
  private[angulate2] lazy val defaultDebugConfig = DebugConfig(false,false)
} 
Example 82
Source File: Directive.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description: Angular2 @Directive macro annotation

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.core

import angulate2.internal.{ClassDecorator, FieldDecorator}

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("@angular/core","Directive")
object DirectiveFacade extends js.Object {
  def apply(options: js.Object) : js.Object = js.native
}

// NOTE: keep the constructor parameter list and Directive.Macro.annotationParamNames in sync!
@compileTimeOnly("enable macro paradise to expand macro annotations")
class Directive(selector: String = null,
                inputs: js.Array[String] = null,
                outputs: js.Array[String] = null,
                host: js.Dictionary[String] = null,
                template: String = null,
                providers: js.Array[js.Any] = null,
                exportAs: String = null,
                queries: js.Any = null) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro Directive.Macro.impl
}


object Directive {

  private[angulate2] abstract class BaseMacro extends ClassDecorator with FieldDecorator

  private[angulate2] class Macro(val c: whitebox.Context) extends BaseMacro {
    import c.universe._

    override def annotationName = "Directive"

    override def mainAnnotationObject: c.universe.Tree = q"angulate2.core.DirectiveFacade"

    override def annotationParamNames: Seq[String] = Seq(
      "selector",
      "inputs",
      "outputs",
      "host",
      "template",
      "providers",
      "exportAs",
      "queries"
    )
  }
} 
Example 83
Source File: Pipe.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description:

// Copyright (c) 2017 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.core

import angulate2.internal.ClassDecorator
import de.surfice.smacrotools.createJS

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("@angular/core","Pipe")
object PipeFacade extends js.Object {
  def apply(options: js.Object) : js.Object = js.native
}

// NOTE: keep the constructor parameter list and Directive.Macro.annotationParamNames in sync!
@compileTimeOnly("enable macro paradise to expand macro annotations")
class Pipe(name: String, pure: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro Pipe.Macro.impl
}

object Pipe {

  private[angulate2] class Macro(val c: whitebox.Context) extends ClassDecorator {
    import c.universe._
    val annotationParamNames = Seq(
      "name",
      "pure"
    )

    override val annotationName: String = "Pipe"

    override def mainAnnotationObject = q"angulate2.core.PipeFacade"
  }
}

@createJS
trait PipeTransform0[T,R] {
  def transform(value: T): R
}

@createJS
trait PipeTransform1[T,A1,R] {
  def transform(value: T, arg1: A1): R
}

@createJS
trait PipeTransform2[T,A1,A2,R] {
  def transform(value: T, arg1: A1, arg2: A2): R
}

@createJS
trait PipeTransform3[T,A1,A2,A3,R] {
  def transform(value: T, arg1: A1, arg2: A2, arg3: A3): R
}