Skip to content

Instantly share code, notes, and snippets.

@DmytroMitin
Last active September 13, 2019 10:22
Show Gist options
  • Save DmytroMitin/e2930223069f5bbb303bb9460b97ae89 to your computer and use it in GitHub Desktop.
Save DmytroMitin/e2930223069f5bbb303bb9460b97ae89 to your computer and use it in GitHub Desktop.
import Macros._
object App {
class A
class A1
class A2
class A3
@checkImplicits
def foo(implicit a: A = new A, a1: A1 = new A1, a2: A2 = new A2, a3: A3 = new A3): Unit = ()
implicit val aa: A = new A
implicit val aa1: A1 = new A1
foo
//no implicit parameter a2 of type A2 in method foo
//no implicit parameter a3 of type A3 in method foo
def main(args: Array[String]): Unit = ()
}
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
object Macros {
@compileTimeOnly("enable macro paradise")
class checkImplicits extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro CheckImplicitsMacro.impl
}
object CheckImplicitsMacro {
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
annottees match {
case q"$mmods def $mtname[..$tparams](...$paramss): $mtpt = $mexpr" :: Nil =>
if (paramss.isEmpty || paramss.last.isEmpty || (paramss.last.head match { case q"${mods: Modifiers} val $_: $_ = $_" => !mods.hasFlag(Flag.IMPLICIT) }))
c.abort(c.enclosingPosition, s"no implicit parameters in method $mtname, paramss=$paramss")
val params1 = paramss.last.map {
case q"$mods val $tname: $tpt = $expr" =>
val tname1 = TermName(c.freshName(tname.toString))
val message = s"no implicit parameter $tname of type $tpt in method $mtname"
(
q"$mods val $tname1: $tpt = null",
q"val $tname: $tpt = if ($tname1 == null) { _root_.scala.Predef.println($message); $tname1 } else $expr"
)
}
val (implicitParams, localVals) = (params1.map(_._1), params1.map(_._2))
q"""$mmods def $mtname[..$tparams](...${paramss.init :+ implicitParams}): $mtpt = {
..$localVals
$mexpr
}"""
case _ => c.abort(c.enclosingPosition, s"not method, annottees=$annottees")
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment