我有一个宏插件,该插件检查实体是否为case类,然后以点表示法返回所有字段。
例如。
case class Language(name: String)
@Lenses
case class Page(a: Language)
因此main方法将返回
Seq("language.name")
这在scala 2.11.6和2.11.8上运行良好,但是,我刚刚将项目更新为2.11.12,并且开始出现GC开销错误。
我以前的方法曾经实现为:
def isCClass(tpe: Type): Boolean = {
tpe.widen.dealias.typeSymbol.asInstanceOf[ClassSymbol].isCaseClass
}
正如我提到的那样,它可以在2.11.6和2.11.8上运行,但在2.11.12中出现转换错误而失败
exception during macro expansion:
[error] java.lang.ClassCastException: scala.reflect.internal.Symbols$AbstractTypeSymbol cannot be cast to scala.reflect.api.Symbols$ClassSymbolApi
然后我更新了代码以匹配typeSymbol,如下所示:
def isCClass(tpe: Type): Boolean = {
tpe.widen.dealias.typeSymbol match {
case typeSymbol: ClassSymbol => typeSymbol.asInstanceOf[ClassSymbol].isCaseClass
case _ => false
}
}
但这会导致以下错误:
exception during macro expansion: [error] java.lang.OutOfMemoryError: GC overhead limit exceeded
我的内存增加到了3 / 4gb,但出现了同样的错误。 在我的zsh配置上使用:
alias sbt="sbt -mem 3092"
我添加了一个规范,几乎复制了我感兴趣的实体的所有依赖项类型,这些实体我希望在我的插件项目中提取所有字段名称,包括@Lenses依赖项和测试通过。但到目前为止没有运气。
任何提示都说明匹配是否昂贵
但是,在真实项目中,它是大型代码库中的多个模块,因此它是GC。
更新: 我已更改匹配的实现方式:
def isCClass(tpe: Type): Boolean = {
val tpeSymbol = tpe.widen.dealias.typeSymbol
if (tpeSymbol.isClass) tpeSymbol.asInstanceOf[ClassSymbol].isCaseClass else false
}
这解决了2.11.12的问题,但是,我尝试使用带有深度嵌套类型的参数的实体回到2.11.8,并且GC引发错误。 看起来这种宏扩展正在引起一些开销或无限循环,因为即使将内存增加到12GB,我仍然看到Java编译器的内存在增加