I'm using the RunningStrategies class in my Scala code to define a set of running strategies. To create an instance of RunningStrategies, I'm using the apply method along with a variable number of arguments representing the different strategies. To achieve this, I have also defined a macro called RunningStrategiesMacros.
However, when I try to use RunningStrategies with some strategies, I get the following error message: "macro implementation not found: apply". The error seems to be related to the fact that I'm trying to use the macro implementation in the same compilation run that defines it.
RunningStrategy:
package com.dv.phoenix.brandsafety.models
object RunningStrategy extends Enumeration {
type RunningStrategy = Value
val
MonitoringOnly,
BlockingOnly,
MonitoringAndBlockingInherent,
MonitoringAndBlockingRecalculate
= Value
}
RunningStrategies:
package com.dv.phoenix.brandsafety.models
import com.dv.phoenix.brandsafety.models.RunningStrategy.RunningStrategy
import com.dv.phoenix.brandsafety.utils.RunningStrategiesMacros
import scala.language.experimental.macros
case class RunningStrategies private (runningStrategies: Set[RunningStrategy])
object RunningStrategies {
def apply(strategies: RunningStrategy*): RunningStrategies = macro RunningStrategiesMacros.applyImp
}
RunningStrategiesMacro:
package com.dv.phoenix.brandsafety.utils
import com.dv.phoenix.brandsafety.models.RunningStrategies
import com.dv.phoenix.brandsafety.models.RunningStrategy.RunningStrategy
import scala.reflect.macros.blackbox
object RunningStrategiesMacros {
def applyImp(c: blackbox.Context)(runningStrategies: c.Expr[RunningStrategy]*): c.Expr[RunningStrategies] = {
import c.universe._
val hasMonitoringAndBlockingInherent = runningStrategies.map(_.tree.toString).contains(s"${RunningStrategy.getClass.getName.stripSuffix("$")}.${RunningStrategy.MonitoringAndBlockingInherent}")
val hasMonitoringAndBlockingRecalculate = runningStrategies.map(_.tree.toString).contains(s"${RunningStrategy.getClass.getName.stripSuffix("$")}.${RunningStrategy.MonitoringAndBlockingRecalculate}")
if (hasMonitoringAndBlockingInherent && hasMonitoringAndBlockingRecalculate) {
c.abort(c.enclosingPosition, "runningStrategies cannot include both RunningStrategy.MonitoringAndBlockingInherent and RunningStrategy.MonitoringAndBlockingRecalculate")
} else {
c.Expr(q"RunningStrategies(Set(..$runningStrategies))")
}
}
}
Usuage:
override protected val runningStrategies: RunningStrategies = RunningStrategies(MonitoringOnly, MonitoringAndBlockingInherent, MonitoringAndBlockingRecalculate)
I got the following error:
macro implementation not found: apply
(the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)
override protected val runningStrategies: RunningStrategies = RunningStrategies(MonitoringOnly, MonitoringAndBlockingInherent, MonitoringAndBlockingRecalculate)
I have noticed that the scala-logging library has managed to solve this problem with their LoggerImpl and LoggerMacro classes. Can someone explain how they were able to do this and how I can apply the same technique to my RunningStrategiesMacro?