我正在尝试更改其他人编写的编译器插件,该插件直接在打字器之后运行,我想生成引发异常的代码。
异常类如下所示:
case class MyException(message: String) extends Exception(message)
不过,在实际代码中,这是一个内部类。
我看了他如何得到一个固定类的符号并做了类似的事情,我不知道是否有更好的方法,但这是他是如何做到的:
val exceptionClass = MyException.getClass.getName
val exceptionName = if (exceptionClass.last == '$') exceptionClass.dropRight(1) else exceptionClass
val symbol = rootMirror.getModuleByName(newTermName(exceptionName))
为了抛出异常,我这样做了:
import CODE._
THROW(symbol, Literal(Constant("My message")))
我认为,以下内容也是等效的(和产生等效的行为)
Throw(symbol.tpe, Literal(Constant("My Message")))
Throw(NEW(symbol, Literal(Constant("My message"))))
Throw(New(symbol.tpe, Literal(Constant("My message"))))
但我有一个例外:
== Enclosing template or block ==
Apply( // val <error>: <error> in class <error>
new MyException.type."<init>" // val <error>: <error> in class <error>, tree.tpe=<error>
Nil
)
== Expanded type of tree ==
TypeRef(TypeSymbol(class MyException extends ))
uncaught exception during compilation: scala.reflect.internal.Types$TypeError
error: scala.reflect.internal.Types$TypeError: MyException.type does not have a constructor
...
我想我必须以某种方式以不同的方式使用"新",有谁知道这是如何正确完成的?
Scala邮件列表的某个人告诉我解决方案:
我应该以不同的方式获取符号,我需要类的符号,而不是模块的符号,如果是对象来调用方法等,则使用后者,但是我们需要这里的类,所以而不是
val symbol = rootMirror.getModuleByName(newTermName(exceptionName))
我写
val symbol = rootMirror.getClassByName(newTermName(exceptionName))