scala.reflect.macros.blackbox.Context Scala Examples

The following examples show how to use scala.reflect.macros.blackbox.Context. 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: AssertMacros.scala    From incubator-daffodil   with Apache License 2.0 5 votes vote down vote up
package org.apache.daffodil.exceptions

import scala.reflect.macros.blackbox.Context

object AssertMacros {

  def usageMacro2(c: Context)(testAbortsIfFalse: c.Tree, message: c.Tree): c.Tree = {
    import c.universe._

    val testAsString = testAbortsIfFalse.toString

    q"""
    if (!($testAbortsIfFalse)) {
         Assert.abort2("Usage error: " + $message, $testAsString)
    }
    """
  }

  def usageMacro1(c: Context)(testAbortsIfFalse: c.Tree): c.Tree = {
    import c.universe._

    val testAsString = testAbortsIfFalse.toString

    q"""
    if (!($testAbortsIfFalse)) {
         Assert.abort("Usage error: " + $testAsString)
    }
    """
  }

  def invariantMacro1(c: Context)(testAbortsIfFalse: c.Tree): c.Tree = {
    import c.universe._

    val testAsString = testAbortsIfFalse.toString

    q"""
    if (!($testAbortsIfFalse)) {
         Assert.abort("Invariant broken: " + $testAsString)
    }
    """
  }

  def notYetImplementedMacro0(c: Context)(): c.Tree = {
    import c.universe._

    q"""
         Assert.nyi()
    """
  }

  def notYetImplementedMacro1(c: Context)(testThatWillThrowIfTrue: c.Tree): c.Tree = {
    import c.universe._

    val testAsString = testThatWillThrowIfTrue.toString

    q"""
    if ($testThatWillThrowIfTrue){
         Assert.nyi($testAsString)
    }
    """
  }

  def notYetImplementedMacro2(c: Context)(testThatWillThrowIfTrue: c.Tree, msg: c.Tree): c.Tree = {
    import c.universe._

    val testAsString = testThatWillThrowIfTrue.toString

    q"""
    if ($testThatWillThrowIfTrue){
         Assert.nyi($msg + " (" + $testAsString + ")")
    }
    """
  }

} 
Example 2
Source File: Tools.scala    From jsonapi-scala   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.qvantel.jsonapi.macrosupport

import scala.annotation.compileTimeOnly
import scala.reflect.macros.blackbox.Context
import shapeless.{CNil, Coproduct}

@compileTimeOnly("Macros can only be used at compile-time")
trait Tools {
  val c: Context
  import c.universe._

  private[this] val coproductType = typeOf[Coproduct]
  private[this] val coproductNil  = typeOf[CNil]

  private[this] def inl(name: TermName): c.Tree = {
    val bind = pq"$name"
    q"_root_.shapeless.Inl($bind)"
  }

  private[this] def inr(tree: c.Tree): c.Tree = q"_root_.shapeless.Inr($tree)"

  def coproductTypes(t: c.Type): List[c.Type] = {
    def go(ta: List[c.Type], acc: List[c.Type]): List[c.Type] =
      ta match {
        case Nil                                 => acc
        case l :: r :: Nil if r =:= coproductNil => acc :+ l
        case l :: r :: Nil                       => go(r.dealias.typeArgs, acc :+ l)
      }

    if (t <:< coproductType) {
      go(t.dealias.typeArgs, Nil)
    } else {
      c.abort(c.enclosingPosition, s"The type $t must be a shapeless.Coproduct")
    }
  }

  def coproductPattern(n: Int, name: TermName): c.Tree =
    (1 until n).foldLeft(inl(name))((tree, _) => inr(tree))

  def coproductPatterns(nTypes: Int, name: TermName): Seq[c.Tree] =
    (1 to nTypes).map(coproductPattern(_, name))
} 
Example 3
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 4
Source File: GetOrElseFail.scala    From troy   with Apache License 2.0 5 votes vote down vote up
package troy.driver.query.select

import shapeless._
import troy.driver.CassandraDataType
import troy.driver.schema.FunctionTypeResolver
import troy.driver.schema.column.ColumnType
import troy.tast.Select.{ Selection, ColumnName, Function, SelectClause, SelectionClauseItem }
import troy.tutils._
import scala.reflect.macros.blackbox.Context

trait GetOrElseFail[M] {
  type Out
}

object GetOrElseFail {

  type Aux[M, O] = GetOrElseFail[M] { type Out = O }

  def apply[M](implicit instance: GetOrElseFail[M]): Aux[M, instance.Out] = instance

  def instance[M, O]: Aux[M, O] = new GetOrElseFail[M] { override type Out = O }

  implicit def getEitherIfRight[T] = instance[TRight[T], T]
  implicit def failEitherIfLeft[E <: THList[String]]: Aux[TLeft[E], Nothing] = macro GetOrElseFailMacro.fail[E]
}

object GetOrElseFailMacro {
  def fail[E <: THList[String]](c: Context)(implicit eType: c.WeakTypeTag[E]) = {
    c.abort(c.enclosingPosition, show(c)(eType.tpe))
  }

  def show(c: Context)(typ: c.universe.Type): String = typ match {
    case t if t <:< c.typeOf[TNone]              => ""
    case t if t <:< c.typeOf[HNil]               => ""
    case t if t <:< c.typeOf[TSome[_]]           => show(c)(typ.typeArgs.head)
    case t if t <:< c.typeOf[shapeless.::[_, _]] => typ.typeArgs.map(show(c)).mkString
    case t                                       => trim(t.toString)
  }

  def trim(typRepr: String): String = typRepr match {
    case StringPattern(str) => str
    case other              => other
  }

  val StringPattern = """String\("(.*)"\)""".r

} 
Example 5
Source File: SelectionTypeResolver.scala    From troy   with Apache License 2.0 5 votes vote down vote up
package troy
package driver.query.select

import shapeless._
import troy.driver.CassandraDataType
import troy.driver.schema.FunctionTypeResolver
import troy.driver.schema.column.ColumnType
import troy.tast._
import troy.tast.Select.{ Selection, ColumnName, Function, SelectClause, SelectionClauseItem }
import troy.tutils.{ TLeft, TRight, TEither, TOption }
import scala.reflect.macros.blackbox.Context

trait SelectionTypeResolver[Version, T <: TableName[_, _], S <: Selection] {
  type Out <: TEither[THList[String], THList[CassandraDataType]]
}

object SelectionTypeResolver extends LowPriority {

  type Aux[V, T <: TableName[_, _], S <: Selection, O <: TEither[THList[String], THList[CassandraDataType]]] = SelectionTypeResolver[V, T, S] { type Out = O }

  def apply[V, T <: TableName[_, _], S <: Selection](implicit s: SelectionTypeResolver[V, T, S]): Aux[V, T, S, s.Out] = s

  def instance[V, T <: TableName[_, _], S <: Selection, O <: TEither[THList[String], THList[CassandraDataType]]]: Aux[V, T, S, O] = new SelectionTypeResolver[V, T, S] { type Out = O }

  implicit def hNilInstance[V, T <: TableName[_, _]] = instance[V, T, SelectClause[HNil], TRight[HNil]]

  implicit def hColumnInstance[V, T <: TableName[_, _], CN <: Identifier, CNAlias <: TOption[Identifier], ST <: THList[SelectionClauseItem[_, _]], TailType <: THList[CassandraDataType]](
    implicit
    headType: ColumnType[V, T, CN],
    tailType: SelectionTypeResolver.Aux[V, T, SelectClause[ST], TRight[TailType]]
  ) = instance[V, T, SelectClause[SelectionClauseItem[ColumnName[CN], CNAlias] :: ST], TRight[headType.Out :: TailType]]

  //  implicit def hFunctionInstance[V, K <: MaybeKeyspaceName, T <: Identifier, F <: FunctionName[_, _], FParams <: HList, FParamTypes <: HList, Alias <: TOption[Identifier], ST <: THList[SelectionClauseItem[_, _]]](
  //    implicit
  //    fParamTypes: SelectionTypeResolver.Aux[V, TableName[K, T], FParams, FParamTypes], // FIXME: Is it correct to assume function params can be treated as normal selected fields?
  //    headType: FunctionTypeResolver[V, F, FParamTypes, K],
  //    tailType: SelectionTypeResolver[V, TableName[K, T], SelectClause[ST]]
  //  ) = instance[V, TableName[K, T], SelectClause[SelectionClauseItem[Function[F, FParams], Alias] :: ST], headType.Out :: tailType.Out]
}

trait LowPriority {
  import Select._
  import SelectionTypeResolver.instance

  implicit def hColumnNotFoundInstance[V, K <: MaybeKeyspaceName, T <: Identifier, CN <: Identifier, CNAlias <: TOption[Identifier], ST <: THList[SelectionClauseItem[_, _]]] =
    instance[V, TableName[K, T], SelectClause[SelectionClauseItem[ColumnName[CN], CNAlias] :: ST], TLeft["Column " :: CN :: " does not exist in table " :: T :: HNil]]
}

object ImplicitNotFoundMacro {
  // FIXME: Implicits need to match for failures also to be able to report the exact error
  // The code below falsely report the first column, even if another column doesn't exist
  def columnNotFound[V, T, ColumnName](c: Context)(implicit columnName: c.WeakTypeTag[ColumnName]) = {
    c.abort(c.enclosingPosition, "One of the selected columns doesn't exist") //s"Undefined name ${columnName.tpe} in selection clause.")
  }
} 
Example 6
Source File: RegexLiteral.scala    From kantan.regex   with Apache License 2.0 5 votes vote down vote up
package kantan.regex
package literals

import java.util.regex.Pattern
import scala.reflect.macros.blackbox.Context
import scala.util.{Failure, Success, Try => UTry}

final class RegexLiteral(val sc: StringContext) extends AnyVal {
  def rx(args: Any*): Pattern = macro RegexLiteral.rxImpl
}

// Relatively distatefull trick to get rid of spurious warnings.
trait RegexLiteralMacro {
  def rxImpl(c: Context)(args: c.Expr[Any]*): c.Expr[Pattern]
}

object RegexLiteral extends RegexLiteralMacro {

  override def rxImpl(c: Context)(args: c.Expr[Any]*): c.Expr[Pattern] = {
    import c.universe._

    c.prefix.tree match {
      case Apply(_, List(Apply(_, List(lit @ Literal(Constant(str: String)))))) =>
        UTry(Pattern.compile(str)) match {
          case Failure(_) => c.abort(c.enclosingPosition, s"Illegal regex: '$str'")
          case Success(_) =>
            reify {
              Pattern.compile(c.Expr[String](lit).splice)
            }
        }
      case _ =>
        c.abort(c.enclosingPosition, "rx can only be used on string literals")
    }
  }
}

trait ToRegexLiteral {
  implicit def toRegexLiteral(sc: StringContext): RegexLiteral = new RegexLiteral(sc)
} 
Example 7
Source File: Helpers.scala    From pine   with Apache License 2.0 5 votes vote down vote up
package pine.macros

import java.io.File

import scala.reflect.macros.blackbox.Context

object Helpers {
  def literalValueTree[T](c: Context)(tree: c.Tree): T = {
    import c.universe._
    tree match {
      case Literal(Constant(value)) => value.asInstanceOf[T]
      case _ =>
        c.error(c.enclosingPosition, "Literal expected")
        throw new RuntimeException()
    }
  }

  def literalValueExpr[T](c: Context)(expr: c.Expr[T]): T =
    literalValueTree[T](c)(expr.tree)

  def readFile(file: File): String = {
    val source = io.Source.fromFile(file)
    try source.mkString finally source.close()
  }
} 
Example 8
Source File: ExternalHtml.scala    From pine   with Apache License 2.0 5 votes vote down vote up
package pine.macros

import java.io.File

import scala.reflect.macros.blackbox.Context

import pine._
import pine.internal.HtmlParser

object ExternalHtml {
  trait Method {
    
    def xml (fileName: String): Tag[Singleton] = macro XmlImpl
    def html(fileName: String): Tag[Singleton] = macro HtmlImpl
  }

  def convert(c: Context)(node: Node, root: Boolean): c.Expr[Node] = {
    import c.universe._

    node match {
      case Text(text) => c.Expr(q"pine.Text($text)")
      case tag @ Tag(_, _, _) =>
        val tagAttrs    = tag.attributes
        val tagChildren = tag.children.map(convert(c)(_, root = false))

        c.Expr(q"pine.Tag(${tag.tagName}, $tagAttrs, List(..$tagChildren))")
    }
  }

  def parse(c: Context, xml: Boolean)
           (fileName: c.Expr[String]): c.Expr[Tag[Singleton]] = {
    val path = new File(c.enclosingPosition.source.path).getParentFile
    val fileNameValue = Helpers.literalValueExpr(c)(fileName)
    val html = Helpers.readFile(new File(path, fileNameValue))
    val node = HtmlParser.fromString(html, xml)
    convert(c)(node, root = true)
      .asInstanceOf[c.Expr[Tag[Singleton]]]
  }

  def XmlImpl(c: Context)(fileName: c.Expr[String]): c.Expr[Tag[Singleton]] =
    parse(c, xml = true)(fileName)

  def HtmlImpl(c: Context)(fileName: c.Expr[String]): c.Expr[Tag[Singleton]] =
    parse(c, xml = false)(fileName)
} 
Example 9
Source File: Utils.scala    From aerospike-scala   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.aerospikemacro.converters

import ru.tinkoff.aerospikescala.domain.ByteSegment

import scala.reflect.macros.blackbox.Context


object Utils {
  def pickValue[T: c.WeakTypeTag](c: Context): c.universe.Tree = {
    import c.universe._
    val tpe = weakTypeOf[T]
    val tpeName = q"${tpe.typeSymbol.fullName}"

    val err =
      q"""throw new IllegalArgumentException(
         "You need to write your own toValue function in KeyWrapper implicit for type " + $tpeName) """

    tpe match {
      case t if t =:= weakTypeOf[ByteSegment] => q"""v match {
        case ByteSegment(bytes, offset, length) => new ByteSegmentValue(bytes, offset, length)
        case _ => $err
        }"""
      case t if t =:= weakTypeOf[Int] => q"""new IntegerValue(v)"""
      case t if t =:= weakTypeOf[Long] => q"""new LongValue(v)"""
      case t if t =:= weakTypeOf[String] => q"""new StringValue(v)"""
      case t if t =:= weakTypeOf[Boolean] => q"""new BooleanValue(v)"""
      case t if t =:= weakTypeOf[Float] => q"""new FloatValue(v)"""
      case t if t =:= weakTypeOf[Double] => q"""new DoubleValue(v)"""
      case t if t =:= weakTypeOf[Array[Byte]] => q"""new BytesValue(v)"""
      case t if t =:= weakTypeOf[scala.collection.immutable.Seq[_]] => q"""new ListValue(v)"""
      case t if t =:= weakTypeOf[Map[_, _]] => q"""new MapValue(v)"""
      case _ => q"""Try(Value.get(v)) match {
      case Failure(th) => $err
      case Success(s) => s
    }"""
    }
  }
} 
Example 10
Source File: KeyWrapper.scala    From aerospike-scala   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.aerospikemacro.converters

import com.aerospike.client.Value._
import com.aerospike.client.{Key, Value}
import ru.tinkoff.aerospikemacro.domain.{DBCredentials, WrapperException}

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


trait KeyWrapper[KT] {

  val dbName: String    = ""
  val tableName: String = ""

  def apply(k: KT): Key = new Key(dbName, tableName, toValue(k))

  def toValue(v: KT): Value = Value.get(v) match {
    case _: NullValue =>
      throw new WrapperException {
        val msg = "You need to write your own toValue function in KeyWrapper"
      }
    case other => other
  }
}

object KeyWrapper {
  import Utils._

  implicit def materializeK[T](implicit dbc: DBCredentials): KeyWrapper[T] = macro implK[T]

  def implK[T: c.WeakTypeTag](c: Context)(dbc: c.Expr[DBCredentials]): c.Expr[KeyWrapper[T]] = {
    import c.universe._
    val tpe = weakTypeOf[T]

    val db        = reify(dbc.splice.namespace)
    val tableName = reify(dbc.splice.setname)

    val toDBValue = pickValue(c)

    c.Expr[KeyWrapper[T]] {
      q"""
      import com.aerospike.client.{Key, Value}
      import com.aerospike.client.Value._
      import scala.collection.immutable.Seq
      import ru.tinkoff.aerospikescala.domain.ByteSegment
      import scala.util.{Failure, Success, Try}

      new KeyWrapper[$tpe] {
        override val dbName = $db
        override val tableName = $tableName
        override def toValue(v: $tpe): Value = $toDBValue
      }
     """
    }
  }

  def create[T](dbc: DBCredentials): KeyWrapper[T] = macro implK[T]

} 
Example 11
Source File: IOMacros.scala    From incubator-daffodil   with Apache License 2.0 5 votes vote down vote up
package org.apache.daffodil.io

import scala.reflect.macros.blackbox.Context

object IOMacros {

  
  def withBitLengthLimitMacroForInput(c: Context)(lengthLimitInBits: c.Tree)(body: c.Tree) = {

    import c.universe._

    val dStream = TermName(c.freshName)
    val newLengthLimit = TermName(c.freshName)
    val savedLengthLimit = TermName(c.freshName)
    // c.prefix is the expression this macro was expanded on. Not quite same thing as 'this' because we have to be
    // careful not to use it more than once or it will evaluate more than once.
    val selfExp = c.prefix

    q"""{
    import org.apache.daffodil.util.MaybeULong

    val $dStream = $selfExp
    val $newLengthLimit = $lengthLimitInBits
    val $savedLengthLimit = $dStream.bitLimit0b

    if (!$dStream.setBitLimit0b(MaybeULong($dStream.bitPos0b + $newLengthLimit))) false
    else {
      try {
        $body
      } finally {
        $dStream.resetBitLimit0b($savedLengthLimit)
      }
      true
    }
  }"""
  }
} 
Example 12
Source File: TimerMacros.scala    From incubator-daffodil   with Apache License 2.0 5 votes vote down vote up
package org.apache.daffodil.util

import scala.reflect.macros.blackbox.Context

object TimeTrackerMacros {

  def trackMacro(c: Context)(name: c.Tree)(body: c.Tree) = {
    import c.universe._

    val startTime = TermName(c.freshName)
    val endTime = TermName(c.freshName)
    val childrenTime = TermName(c.freshName)
    val timeTaken = TermName(c.freshName)
    val selfTime = TermName(c.freshName)
    val sectionTime = TermName(c.freshName)
    val result = TermName(c.freshName)
    val key = TermName(c.freshName)

    q"""
    {
      val $startTime = System.nanoTime
      TimeTracker.childrenTimeStack.push(0)
      
      val $result = try {
        $body
      } finally {
        val $endTime = System.nanoTime
        val $timeTaken = $endTime - $startTime
        val $childrenTime = TimeTracker.childrenTimeStack.pop()
        val $selfTime = $timeTaken - $childrenTime

        val $key = $name
        val $sectionTime = TimeTracker.sectionTimes.get($key)
        if ($sectionTime == null) {
          TimeTracker.sectionTimes.put($key, new TimeTracker.SectionTime($selfTime, 1))
        } else {
          $sectionTime.time += $selfTime
          $sectionTime.count += 1
        }

        if (!TimeTracker.childrenTimeStack.isEmpty) {
          TimeTracker.childrenTimeStack.push(TimeTracker.childrenTimeStack.pop + $timeTaken) 
        }
      }

      $result
    }
    """
  }
} 
Example 13
Source File: SDEMacros.scala    From incubator-daffodil   with Apache License 2.0 5 votes vote down vote up
package org.apache.daffodil.exceptions

import scala.reflect.macros.blackbox.Context

object SDEMacros {

  def schemaDefinitionUnlessMacro(c: Context)(testThatWillThrowIfFalse: c.Expr[Boolean], str: c.Expr[String], args: c.Expr[Any]*): c.Expr[Unit] = {
    import c.universe._

    val selfExp = c.prefix

    c.Expr(q"""
    {
      if (!($testThatWillThrowIfFalse)) {
        $selfExp.SDE($str, ..$args)
      }
    }
    """)
  }

  def schemaDefinitionWhenMacro(c: Context)(testThatWillThrowIfTrue: c.Expr[Boolean], str: c.Expr[String], args: c.Expr[Any]*): c.Expr[Unit] = {
    import c.universe._

    val selfExp = c.prefix

    c.Expr(q"""
    {
      if ($testThatWillThrowIfTrue) {
        $selfExp.SDE($str, ..$args)
      }
    }
    """)
  }

  def schemaDefinitionWarningUnlessMacro(c: Context)(testThatWillWarnIfFalse: c.Expr[Boolean], str: c.Expr[String], args: c.Expr[Any]*): c.Expr[Unit] = {
    import c.universe._

    val selfExp = c.prefix

    c.Expr(q"""
    {
      if (!($testThatWillWarnIfFalse)) {
        $selfExp.SDW($str, ..$args)
      }
    }
    """)
  }

  def schemaDefinitionWarningUnlessSuppressMacro(c: Context)(warnID: c.Tree, testThatWillWarnIfFalse: c.Expr[Boolean], str: c.Expr[String], args: c.Expr[Any]*): c.Expr[Unit] = {
    import c.universe._

    val selfExp = c.prefix

    c.Expr(q"""
    {
      if (!($testThatWillWarnIfFalse)) {
        $selfExp.SDW($warnID, $str, ..$args)
      }
    }
    """)
  }

  def schemaDefinitionWarningWhenMacro(c: Context)(testThatWillWarnIfTrue: c.Expr[Boolean], str: c.Expr[String], args: c.Expr[Any]*): c.Expr[Unit] = {
    import c.universe._

    val selfExp = c.prefix

    c.Expr(q"""
    {
      if ($testThatWillWarnIfTrue) {
        $selfExp.SDW($str, ..$args)
      }
    }
    """)
  }

  def schemaDefinitionWarningWhenSuppressMacro(c: Context)(warnID: c.Tree, testThatWillWarnIfTrue: c.Expr[Boolean], str: c.Expr[String], args: c.Expr[Any]*): c.Expr[Unit] = {
    import c.universe._

    val selfExp = c.prefix

    c.Expr(q"""
    {
      if ($testThatWillWarnIfTrue) {
        $selfExp.SDW($warnID, $str, ..$args)
      }
    }
    """)
  }
} 
Example 14
Source File: ReaderBuilder.scala    From xtract   with Apache License 2.0 5 votes vote down vote up
package com.lucidchart.open.xtract.meta

import com.lucidchart.open.xtract.{XPath, XmlReader}
import scala.reflect.macros.blackbox.Context


private[xtract] class ReaderBuilder(val c: Context) {
  import c.universe._

  private case class MetaReaderLine(
    name: String,
    path: Option[Expr[XPath]],
    tpe: Type
  )

  private def makeReader[A: c.WeakTypeTag](params: Seq[MetaReaderLine]): c.Expr[XmlReader[A]] = {
    val tp = weakTypeOf[A]
    if (tp == typeOf[Nothing]) {
      c.abort(c.enclosingPosition, "You must specify a type parameter [?]")
    }

    val lines = params.map { line =>
      val term = TermName(line.name)

      val nodeExpr = line.path.map { path =>
        q"($path)(xml)"
      }.getOrElse {
        q"xml \ ${line.name}"
      }

      fq"$term <- com.lucidchart.open.xtract.XmlReader.of[${line.tpe}].read($nodeExpr)"
    }

    val names = params.map { line =>
      TermName(line.name)
    }

    val comp = weakTypeOf[A].typeSymbol
    val readImpl = q"""
      for(..$lines) yield new ${tp}(..$names)
    """

    val res = c.Expr[XmlReader[A]](q"""
      new com.lucidchart.open.xtract.XmlReader[$tp] {
        def read(xml: scala.xml.NodeSeq) = {
          $readImpl
        }
      }
    """)
    println(s"Result: $res")
    res
  }

  private def extractParams(fields: Seq[c.Expr[ReadLine[_]]]): Seq[MetaReaderLine] = {
    fields.map { lineExpr =>
      lineExpr.tree match {
        case current @ q"$expr[$tpe](...$argss)" => {
          val t: Type = tpe.asInstanceOf[TypeTree].tpe
          if (t == typeOf[Nothing]) {
            c.abort(current.pos, "You must specify a type parameter: ReadLine[?]")
          }
          argss.head match {
            case List(nameLit) => MetaReaderLine(extractLiteralString(nameLit), None, t)
            case List(nameLit, pathExpr) => MetaReaderLine(extractLiteralString(nameLit), Some(c.Expr(pathExpr)), t)
          }
        }
      }
    }
  }

  private def inferParams[A: c.WeakTypeTag]: Seq[MetaReaderLine] = {
    val tp = weakTypeOf[A]
    val params = tp.decl(termNames.CONSTRUCTOR).alternatives.collectFirst {
      case m: MethodSymbol if m.isPrimaryConstructor => m.paramLists.flatten
    }.getOrElse(c.abort(c.enclosingPosition, s"No constructor found for ${tp}"))
    for (param <- params ) yield {
      MetaReaderLine(param.name.toString, None, param.info)
    }
  }

  private def extractLiteralString(t: Tree): String = {
    t match {
      case Literal(Constant(str: String)) => str
      case _ => c.abort(t.pos, "A literal String is required for the field name")
    }
  }

  def buildReader[A: c.WeakTypeTag](lines: c.Expr[ReadLine[_]]*): c.Expr[XmlReader[A]] = {
    val params: Seq[MetaReaderLine] = extractParams(lines)
    makeReader[A](params)
  }

  def inferReader[A: c.WeakTypeTag]: c.Expr[XmlReader[A]] = {
    val params = inferParams[A]
    makeReader[A](params)
  }

} 
Example 15
Source File: ShouldNotTypecheck.scala    From scala-parallel-collections   with Apache License 2.0 5 votes vote down vote up
package testutil

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
import scala.reflect.macros.TypecheckException
import java.util.regex.Pattern


object ShouldNotTypecheck {
  def apply(code: String): Unit = macro applyImplNoExp
  def apply(code: String, expected: String): Unit = macro applyImpl

  def applyImplNoExp(ctx: Context)(code: ctx.Expr[String]) = applyImpl(ctx)(code, null)

  def applyImpl(ctx: Context)(code: ctx.Expr[String], expected: ctx.Expr[String]): ctx.Expr[Unit] = {
    import ctx.universe._

    val Expr(Literal(Constant(codeStr: String))) = code
    val (expPat, expMsg) = expected match {
      case null => (null, "Expected some error.")
      case Expr(Literal(Constant(s: String))) =>
        (Pattern.compile(s, Pattern.CASE_INSENSITIVE | Pattern.DOTALL), "Expected error matching: "+s)
    }

    try ctx.typecheck(ctx.parse("{ "+codeStr+" }")) catch { case e: TypecheckException =>
      val msg = e.getMessage
      if((expected ne null) && !(expPat.matcher(msg)).matches)
        ctx.abort(ctx.enclosingPosition, "Type-checking failed in an unexpected way.\n"+
          expMsg+"\nActual error: "+msg)
      else return reify(())
    }

    ctx.abort(ctx.enclosingPosition, "Type-checking succeeded unexpectedly.\n"+expMsg)
  }
} 
Example 16
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 17
Source File: ConfigLoader.scala    From shocon   with Apache License 2.0 5 votes vote down vote up
package org.akkajs.shocon

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

object ConfigLoader {

  import org.akkajs.shocon.verboseLog

  /// Loads the content of all config files passed with -Xmacro-settings:
  private def loadExplicitConfigFiles(c: Context): Option[String] =
    // check if config files to be loaded are defined via macro setting -Xmacro-settings:shocon.files=file1.conf;file2.conf
    c.settings.find(_.startsWith("shocon.files="))
      // load these files
      .map( _.split("=") match {
      case Array(_,paths) =>
        val (found,notfound) = paths.split(";").toList
          .map( new java.io.File(_) )
          .partition( _.canRead )

        if(notfound.nonEmpty)
          c.warning(c.enclosingPosition, s"shocon - could not read configuration files: $notfound")

        c.info(c.enclosingPosition, s"shocon - statically reading configuration from $found", force=false)
        found
      case _ => Nil
    })
      // concat these files into a single string
      .map( _.map(scala.io.Source.fromFile(_).getLines.mkString("\n")).mkString("\n\n") )

  def loadDefault(c: Context) = {
    import c.universe._

    val configStr: String =
      // load explicitly defined config files vi -Xmacro-settings:file1.conf;file2.conf;...
      loadExplicitConfigFiles(c)
        // or else load application.conf
        .getOrElse{
          try {
            val confPath = new Object {}.getClass
              .getResource("/")
              .toString + "application.conf"

            c.info(c.enclosingPosition,
              s"shocon - statically reading configuration from $confPath", force=false)

            val stream =
              new Object {}.getClass.getResourceAsStream("/application.conf")

            scala.io.Source.fromInputStream(stream).getLines.mkString("\n")
          } catch {
            case e: Throwable =>
              // we use print instead of c.warning, since multiple warnings at the same c.enclosingPosition seem not to work (?)
              println(c.enclosingPosition, s"WARNING: could not load config file: $e")
              "{}"
          }
        }

    c.Expr[com.typesafe.config.Config](q"""{
        com.typesafe.config.Config(
          org.akkajs.shocon.Config.gen($configStr)
        )
      }""")
  }


  def loadDefaultImpl(c: Context)() = loadDefault(c)
  def loadDefaultImplCL(c: Context)(cl: c.Expr[ClassLoader]) = loadDefault(c)

  def loadFromString(c: Context)(s: c.Expr[String]) = {
    import c.universe._

    s.tree match {
      case q"""$strLit""" =>
        strLit match {
          case Literal(Constant(str)) =>
            if (verboseLog)
              c.info(c.enclosingPosition, "[shocon-facade] optimized at compile time", false)
            
            c.Expr[com.typesafe.config.Config](q"""{
              com.typesafe.config.Config(
                org.akkajs.shocon.Config.gen(${str.toString})
              )
            }""")
          case _ =>
            if (verboseLog)
              c.warning(c.enclosingPosition, "[shocon-facade] fallback to runtime parser")

            c.Expr[com.typesafe.config.Config](q"""{
              com.typesafe.config.Config(
                org.akkajs.shocon.Config($strLit)
              )
            }""")
        }
    }
  }
} 
Example 18
Source File: Macros.scala    From zio   with Apache License 2.0 5 votes vote down vote up
package zio.test

import scala.reflect.macros.TypecheckException
import scala.reflect.macros.blackbox.Context

import zio.UIO

private[test] object Macros {

  def typeCheck_impl(c: Context)(code: c.Expr[String]): c.Expr[UIO[Either[String, Unit]]] = {
    import c.universe._
    try {
      c.typecheck(c.parse(c.eval(c.Expr[String](c.untypecheck(code.tree)))))
      c.Expr(q"zio.UIO.succeed(Right(()))")
    } catch {
      case e: TypecheckException => c.Expr(q"zio.UIO.succeed(Left(${e.getMessage}))")
      case t: Throwable          => c.Expr(q"""zio.UIO.die(new RuntimeException("Compilation failed: " + ${t.getMessage}))""")
    }
  }
} 
Example 19
Source File: CopMacros.scala    From iota   with Apache License 2.0 5 votes vote down vote up
package iota  //#=cats
package iotaz //#=scalaz
package internal

import scala.reflect.macros.blackbox.Context

private[iota]  //#=cats
private[iotaz] //#=scalaz
final class CopMacros(val c: Context) {
  import c.universe._

  //#+scalaz
  def copGen[A, R <: iotaz.TList](
    implicit
    evA: c.WeakTypeTag[A],
    evR: c.WeakTypeTag[R]
  ): Tree = {
    val A = evA.tpe
    val R = evR.tpe

    val aSym = A.typeSymbol.asClass

    val Cop = weakTypeOf[iotaz.Cop[_]].typeSymbol

    if (!aSym.isSealed)
      c.abort(c.enclosingPosition, "only supports sealed traits / classes")
    else {
      // ordering is ill-defined, we use source ordering
      val subs =
        aSym.asClass.knownDirectSubclasses.toList
          .map(_.asClass)
          .sortBy(_.pos.start)

      // we need to reconstruct the TList so the compiler can confirm that the
      // order of subs matches the order in R. Ignores type parameters.

      def deconstructTCons(t: Type): List[Type] = {
        val args = t.typeArgs
        if (args.isEmpty) Nil
        else {
          val List(head, tail) = args
          head.typeConstructor :: deconstructTCons(tail)
        }
      }
      val provided   = deconstructTCons(R.dealias)
      val calculated = subs.map(_.toTypeConstructor)
      provided.zip(calculated).map {
        case (r, s) =>
          if (!(r =:= s))
            c.abort(
              c.enclosingPosition,
              s"sealed trait parameters are out of order: provided $provided does not match calculated $calculated at $r =:= $s"
            )
      }

      // should probably generate an Inject instead of like this
      val fromParts = subs.zipWithIndex.map {
        case (sub, i) =>
          val t = sub.toType
          cq"c: $t => ${Cop.companion}.unsafeApply[$R, $t]($i, c)"
      }

      q"""
        _root_.scalaz.Isomorphism.IsoSet[$A, $Cop[$R]](
          (a: $A) => a match { case ..$fromParts },
          (c: $Cop[$R]) => c.value.asInstanceOf[$A]
        )
      """
    }
  }
  //#-scalaz

} 
Example 20
Source File: VisualTraceMacros.scala    From watr-works   with Apache License 2.0 5 votes vote down vote up
package edu.umass.cs.iesl.watr
package tracemacros

import scala.reflect.macros.blackbox.Context

sealed trait VisualTraceLevel

object VisualTraceLevel {
  case object EnterExit extends VisualTraceLevel
  case object Checkpoint extends VisualTraceLevel
  case object PrintLogs extends VisualTraceLevel
  case object JsonLogs extends VisualTraceLevel
  // case object Callback extends VisualTraceLevel
  // val all = List(Off, EnterExit, Checkpoint, Debug, Callback)
  // def cmp(a: VisualTraceLevel, b:VisualTraceLevel) = all.indexOf(b) - all.indexOf(a)
}

trait EnableTrace {
  def isEnabled(v: VisualTraceLevel): Boolean
  def tracingEnabled(): Boolean
  def traceLevels(): Seq[VisualTraceLevel]
}

object VisualTraceMacros {
  type VTraceContext = Context { type PrefixType = EnableTrace }


  def runOnTraceLevel[T](c: VTraceContext)(vtl: c.Expr[VisualTraceLevel])(body: c.Tree): c.Tree = {
    import c.universe._
    q"""
    if (${c.prefix}.tracingEnabled()) {

       val doTrace: Boolean = ${c.prefix}.traceLevels().contains(..$vtl)

       if (doTrace) {
          val _ = $body
       }
    }
    """
  }

} 
Example 21
Source File: StringInterpolatorHelper.scala    From seals   with Apache License 2.0 5 votes vote down vote up
package dev.tauri.seals
package macros

import scala.reflect.macros.blackbox.Context

trait StringInterpolatorHelper {

  def extractLiteral(c: Context): String = {
    import c.universe._
    val s: String = c.prefix.tree match {
      case Apply(_, List(Apply(_, List(Literal(Constant(s: String)))))) =>
        s
      case _ =>
        c.abort(c.enclosingPosition, "not a string literal")
    }
    s
  }
} 
Example 22
Source File: UUIDMacro.scala    From seals   with Apache License 2.0 5 votes vote down vote up
package dev.tauri.seals
package macros

import java.util.UUID

import scala.reflect.macros.blackbox.Context

import cats.implicits._

object UUIDMacro extends StringInterpolatorHelper {

  def impl(c: Context)(): c.Expr[UUID] = {
    import c.universe._
    val s: String = extractLiteral(c)
    val u: UUID = try {
      UUID.fromString(s)
    } catch {
      case ex: IllegalArgumentException =>
        c.abort(c.enclosingPosition, show"not a valid UUID (${ex.getMessage})")
    }
    if (u.variant =!= 2) {
      c.abort(c.enclosingPosition, "not an RFC-4122 UUID (variant is not 2)")
    }
    val msb: Long = u.getMostSignificantBits
    val lsb: Long = u.getLeastSignificantBits
    c.Expr[UUID](q"new _root_.java.util.UUID(${msb}, ${lsb})")
  }
} 
Example 23
Source File: TestSupport.scala    From monadless   with Apache License 2.0 5 votes vote down vote up
package io.monadless.impl

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
import org.scalamacros.resetallattrs._
import language.higherKinds
import scala.reflect.macros.TypecheckException

private[monadless] trait TestSupport[M[_]] {
  def get[T](m: M[T]): T
  def showTree[T](t: T): Unit = macro TestSupportMacro.showTree
  def showRawTree[T](t: T): Unit = macro TestSupportMacro.showRawTree
  def forceLift[T](t: T): T = macro TestSupportMacro.forceLift
  def runLiftTest[T](expected: T)(body: T): Unit = macro TestSupportMacro.runLiftTest[M, T]
}

private[monadless] class TestSupportMacro(val c: Context) {
  import c.universe._

  def showTree(t: Tree): Tree = {
    c.warning(c.enclosingPosition, t.toString)
    q"()"
  }
  def showRawTree(t: Tree): Tree = {
    c.warning(c.enclosingPosition, showRaw(t))
    q"()"
  }

  def forceLift(t: Tree): Tree =
    c.resetAllAttrs {
      Trees.Transform(c)(t) {
        case q"$pack.unlift[$t]($v)" =>
          q"${c.prefix}.get($v)"
      }
    }

  def runLiftTest[M[_], T](expected: Tree)(body: Tree): Tree =
    c.resetAllAttrs {

      val lifted =
        q"${c.prefix}.get(${c.prefix}.lift($body))"

      val forceLifted = forceLift(body)

      q"""
        val expected = scala.util.Try($expected)
        assert(expected == ${typecheckToTry(lifted, "lifted")})
        assert(expected == ${typecheckToTry(forceLifted, "force lifted")})
        ()
      """
    }

  def typecheckToTry(tree: Tree, name: String): Tree = {
    try {
      val typeCheckedTree = c.typecheck(c.resetAllAttrs(tree))
      c.info(c.enclosingPosition, s"$name: $typeCheckedTree", force = false)
      q"scala.util.Try($typeCheckedTree)"
    } catch {
      case e: TypecheckException =>
        val msg = s"""
          |$name fails typechecking: $e
          |tree: $tree
          |""".stripMargin
        c.info(e.pos.asInstanceOf[Position], msg, force = true)
        q"""scala.util.Failure(new Exception($msg))"""
    }
  }
} 
Example 24
Source File: Macro.scala    From monadless   with Apache License 2.0 5 votes vote down vote up
package io.monadless.impl

import language.higherKinds
import scala.reflect.macros.blackbox.Context
import scala.reflect.macros.TypecheckException

private[monadless] class Macro(val c: Context) {
  import c.universe._

  def lift[M[_], T](body: Expr[T])(implicit m: WeakTypeTag[M[_]]): Tree = {
    val tree = Transformer[M](c)(body.tree)
    Trees.traverse(c)(tree) {
      case tree @ q"$pack.unlift[$t]($v)" =>
        c.error(tree.pos, "Unsupported unlift position")
    }
    try c.typecheck(tree)
    catch {
      case e: TypecheckException =>
        val msg =
          s"""Can't typecheck the monadless transformation. Please file a bug report with this error and your `Monadless` instance. 
             |Failure: ${e.msg}
             |Tree: $tree""".stripMargin
        c.abort(c.enclosingPosition, msg)
    }
  }
} 
Example 25
Source File: Trees.scala    From monadless   with Apache License 2.0 5 votes vote down vote up
package io.monadless.impl

import scala.reflect.macros.blackbox.Context

private[monadless] object Trees {

  object Transform {
    def apply(c: Context)(tree: c.Tree)(pf: PartialFunction[c.Tree, c.Tree]): c.Tree = {
      import c.universe._
      new Transformer {
        override def transform(tree: Tree) =
          pf.lift(tree).getOrElse(super.transform(tree))
      }.transform(tree)
    }
    def unapply(c: Context)(tree: c.Tree)(pf: PartialFunction[c.Tree, c.Tree]): Option[c.Tree] =
      apply(c)(tree)(pf) match {
        case `tree` => None
        case tree   => Some(tree)
      }
  }

  def traverse(c: Context)(tree: c.Tree)(pf: PartialFunction[c.Tree, Unit]) = {
    import c.universe._
    new Traverser {
      override def traverse(tree: Tree) =
        pf.lift(tree).getOrElse(super.traverse(tree))
    }.traverse(tree)
  }
  def exists(c: Context)(tree: c.Tree)(pf: PartialFunction[c.Tree, Boolean]) = {
    var r = false
    traverse(c)(tree) {
      case t if pf.isDefinedAt(t) && !r => r = pf(t)
    }
    r
  }
}