Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在scala 2.13中。如何在宏中可靠地记录信息/警告/错误?_Scala_Implicit_Scala Macros_Scala Macro Paradise_Scala 2.13 - Fatal编程技术网

在scala 2.13中。如何在宏中可靠地记录信息/警告/错误?

在scala 2.13中。如何在宏中可靠地记录信息/警告/错误?,scala,implicit,scala-macros,scala-macro-paradise,scala-2.13,Scala,Implicit,Scala Macros,Scala Macro Paradise,Scala 2.13,我正在编写一个宏,使用scala 2.13的模式匹配和常量类型功能,可以在编译过程中记录短消息: class EmitMsg[T, SS <: EmitMsg.EmitLevel] {} object EmitMsg { trait EmitLevel trait Info extends EmitLevel trait Warning extends EmitLevel trait Error extends EmitLevel trait Abort exte

我正在编写一个宏,使用scala 2.13的模式匹配和常量类型功能,可以在编译过程中记录短消息:

class EmitMsg[T, SS <: EmitMsg.EmitLevel] {}

object EmitMsg {

  trait EmitLevel

  trait Info extends EmitLevel
  trait Warning extends EmitLevel
  trait Error extends EmitLevel
  trait Abort extends EmitLevel

  def create[A, SS <: EmitMsg.EmitLevel]: EmitMsg[A, SS] = new EmitMsg[A, SS]

  implicit def emit[A, SS <: EmitMsg.EmitLevel]: EmitMsg[A, SS] = macro Macros.emit[A, SS]

  final class Macros(val c: whitebox.Context) {
    val u = c.universe
    import u._

    def outer: EmitMsg.type = EmitMsg.this

    def emit[A: c.WeakTypeTag, LL: c.WeakTypeTag]: c.Tree = {

      val aa: Type = weakTypeOf[A]
      val v = aa match {
        case v: u.ConstantType => v.value.value
        case _ =>
          throw new UnsupportedOperationException(
            s"type $aa is not a constant"
          )
      }
      val ss = "" + v
      val ll: Type = weakTypeOf[LL]

      // if inherited from multiple traits, take the most serious one
      if (ll <:< weakTypeOf[Abort]) {
        c.abort(c.enclosingPosition, ss)
      } else if (ll <:< typeOf[Error]) {
        c.error(c.enclosingPosition, ss)
      } else if (ll <:< typeOf[Warning]) {
        c.warning(c.enclosingPosition, ss)
      } else if (ll <:< typeOf[Info]) {
        c.info(c.enclosingPosition, ss, force = true)
      } else {
        throw new UnsupportedOperationException(
          s"type $ll is not an EmitLevel"
        )
      }

      q"$liftOuter.create[$aa, $ll]"
    }
  }
}
(这将生成正确的编译消息):

。。。但如果是隐式宏模式()的一部分,则很少起作用:

因此,我的问题是:

  • 调用c.info/warning/error是编译时登录的正确方法吗

  • 如果是这样,为什么它们从来没有作为隐式宏模式的一部分工作

非常感谢你的建议

更新1刚刚找到了一个解决方案(错误)

val tree0=
c、 打字检查(
q”“”
新的u root_u.scala.annotation.implicitNotFound(“伪”)
""",
沉默=错误
)
类消息扩展了Transformer{
val global=c.universe.asInstanceOf[scala.tools.nsc.global]
覆盖def转换(树:树):树={
超级变换{
树匹配{
大小写文字(常量(“伪”)=>文字(常量(msg))
案例t=>t
}
}
}
}
val tree=new subsmessage().transform(tree0)
注释sym.setAnnotations(注释(树))
()

这是一个复杂的破解,它通过在隐式函数的定义上添加@implicitNotFound注释来工作。到目前为止,我还不知道有任何类似的警告和信息案例解决方案。不过,如果您不想在隐式解析过程中延迟编译错误,则最好使用更简单的解决方案

只要将
c
a
blackbox.Context
而不是
whitebox.Context

EmitMsg.emit["ABC", EmitMsg.Error]
EmitMsg.emit["ABC", EmitMsg.Warning]
...

[Error] /home/peng/git/shapesafe/macro/src/test/scala/org/shapesafe/m/EmitMsgSpec.scala:19: ABC
[Warn] /home/peng/git/shapesafe/macro/src/test/scala/org/shapesafe/m/EmitMsgSpec.scala:20: ABC
one warning found
  it("can emit error") 

    type TT = EmitMsg["ABC", EmitMsg.Error]
    implicitly[TT] //(EmitMsg.emit)
  }
/*
 Generates the following Message:

[Error] /home/peng/git/shapesafe/macro/src/test/scala/org/shapesafe/m/EmitMsgSpec.scala:15: could not find implicit value for parameter e: TT
*/

  it("can emit warning") {

    type TT = EmitMsg["ABC", EmitMsg.Warning]
    implicitly[TT] //(EmitMsg.emit)
  }
/*
Doesn't do a thing
*/

  it("can emit info") {

    type TT = EmitMsg["ABC", EmitMsg.Info]
    implicitly[TT] //(EmitMsg.emit)
  }
/*
Doesn't do a thing
*/