Scala 如何匹配返回未来且具有多个参数或多个参数列表(curried)的方法?

Scala 如何匹配返回未来且具有多个参数或多个参数列表(curried)的方法?,scala,aop,scalameta,Scala,Aop,Scalameta,我正在使用scalameta,我希望有一个通用的度量注释,它发送关于方法执行所用时间的度量 我使用了清伟的缓存注释演示。 它适用于非异步方法,但由于ExecutionContext参数列表的原因,my属性与返回Future的方法不匹配 我的注释如下所示: package measurements import scala.concurrent.Future import scala.meta._ class measure(name: String) extends scala.anno

我正在使用scalameta,我希望有一个通用的度量注释,它发送关于方法执行所用时间的度量

我使用了清伟的缓存注释演示。

它适用于非异步方法,但由于ExecutionContext参数列表的原因,my属性与返回Future的方法不匹配

我的注释如下所示:

package measurements 

import scala.concurrent.Future
import scala.meta._

class measure(name: String) extends scala.annotation.StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    defn match {
      case defn: Defn.Def => {
        this match {
          case q"new $_($backendParam)" =>
            val body: Term = MeasureMacroImpl.expand(backendParam, defn)
            defn.copy(body = body)
          case x =>
            abort(s"Unrecognized pattern $x")
        }
      }
      case _ =>
        abort("This annotation only works on `def`")
    }
  }
}

object MeasureMacroImpl {

  def expand(nameExpr: Term.Arg, annotatedDef: Defn.Def): Term = {
    val name: Term.Name = Term.Name(nameExpr.syntax)
    annotatedDef match {
      case q"..$_ def $methodName[..$tps](..$nonCurriedParams): $rtType = $expr" => {
        rtType match {
          case f: Future[Any] => q"""
            val name = $name
            println("before " + name)
            val future: ${rtType} = ${expr}
            future.map(result => {
              println("after " + name)
              result
            })
           """
          case _ => q"""
            val name = $name
            println("before " + name)
            val result: ${rtType} = ${expr}
            println("after " + name)
            result
           """
        }
      }
      case _ => abort("This annotation only works on `def`")
    }
  }
}
@measure("A")
def test(x: String): String = x

@measure("B")
def testMultipleArg(x: Int, y: Int): Int = x + y
@measure("C")
def testAsync(x: String)(implicit ec: ExecutionContext) : Future[String] = {
 Future(test(x))
}
我使用如下注释:

package measurements 

import scala.concurrent.Future
import scala.meta._

class measure(name: String) extends scala.annotation.StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    defn match {
      case defn: Defn.Def => {
        this match {
          case q"new $_($backendParam)" =>
            val body: Term = MeasureMacroImpl.expand(backendParam, defn)
            defn.copy(body = body)
          case x =>
            abort(s"Unrecognized pattern $x")
        }
      }
      case _ =>
        abort("This annotation only works on `def`")
    }
  }
}

object MeasureMacroImpl {

  def expand(nameExpr: Term.Arg, annotatedDef: Defn.Def): Term = {
    val name: Term.Name = Term.Name(nameExpr.syntax)
    annotatedDef match {
      case q"..$_ def $methodName[..$tps](..$nonCurriedParams): $rtType = $expr" => {
        rtType match {
          case f: Future[Any] => q"""
            val name = $name
            println("before " + name)
            val future: ${rtType} = ${expr}
            future.map(result => {
              println("after " + name)
              result
            })
           """
          case _ => q"""
            val name = $name
            println("before " + name)
            val result: ${rtType} = ${expr}
            println("after " + name)
            result
           """
        }
      }
      case _ => abort("This annotation only works on `def`")
    }
  }
}
@measure("A")
def test(x: String): String = x

@measure("B")
def testMultipleArg(x: Int, y: Int): Int = x + y
@measure("C")
def testAsync(x: String)(implicit ec: ExecutionContext) : Future[String] = {
 Future(test(x))
}
我希望将其与以下异步方法一起使用:

package measurements 

import scala.concurrent.Future
import scala.meta._

class measure(name: String) extends scala.annotation.StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    defn match {
      case defn: Defn.Def => {
        this match {
          case q"new $_($backendParam)" =>
            val body: Term = MeasureMacroImpl.expand(backendParam, defn)
            defn.copy(body = body)
          case x =>
            abort(s"Unrecognized pattern $x")
        }
      }
      case _ =>
        abort("This annotation only works on `def`")
    }
  }
}

object MeasureMacroImpl {

  def expand(nameExpr: Term.Arg, annotatedDef: Defn.Def): Term = {
    val name: Term.Name = Term.Name(nameExpr.syntax)
    annotatedDef match {
      case q"..$_ def $methodName[..$tps](..$nonCurriedParams): $rtType = $expr" => {
        rtType match {
          case f: Future[Any] => q"""
            val name = $name
            println("before " + name)
            val future: ${rtType} = ${expr}
            future.map(result => {
              println("after " + name)
              result
            })
           """
          case _ => q"""
            val name = $name
            println("before " + name)
            val result: ${rtType} = ${expr}
            println("after " + name)
            result
           """
        }
      }
      case _ => abort("This annotation only works on `def`")
    }
  }
}
@measure("A")
def test(x: String): String = x

@measure("B")
def testMultipleArg(x: Int, y: Int): Int = x + y
@measure("C")
def testAsync(x: String)(implicit ec: ExecutionContext) : Future[String] = {
 Future(test(x))
}
但我得到了以下错误:

exception during macro expansion: 
scala.meta.internal.inline.AbortException: This annotation only works on `def`

我假设问题是MeasureMacroImpl匹配,但我不确定如何匹配多个参数组。你们能帮帮我吗?任何想法或示例代码都将不胜感激。我是scala和scala meta的新手,所以如果我问了一个微不足道的问题,我深表歉意

出现错误,因为
MeasureMacroImpl
与当前参数不匹配

匹配咖喱参数非常简单,只需使用

scala
案例q“.$def$methodName[…$tps](…$nonCurriedParams):$rtType=$expr”


请注意,
..$nonCurriedParams
而不是
。$nonCurriedParams

起作用了!非常感谢。请继续制作教程。:)