我有一个宏插件,它检查一个实体是否是一个案例类,然后以点表示法返回所有字段。
例如。
case class Language(name: String)
@Lenses
case class Page(a: Language)
所以主方法会返回
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 抛出错误。看起来这个宏扩展会导致一些开销或无限循环,因为我看到 java 编译器的内存在增加,即使我已经将内存增加到 12GB