3

我正在注释一个特征,例如:

@ScreenModel
trait TestTrait {
  .......
}

然后我得到了@ScreenModel 的实现,例如:

def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._

val output : List[Tree] = annottees.map(_.tree) match {
  case(cd @ q"$mods trait $name[..$tparams] extends ..$parents { ..$body }") :: Nil =>

    val compObjVar = s"""{
        import models.presentation.blocks.BlockModel;
        class AAAA {
          class BBBB {

          }
        }
    }""";

    val rawTree=c.parse(compObjVar)

    val merged = q"{..$rawTree}";
    merged :: Nil
  case _ => c.abort(c.enclosingPosition, "Invalid test target")
}
c.Expr[Any](q"..$output")
}

所以,我得到:

“没有同伴的顶级类只能扩展为同名类或块”

但是,如果我在 AAA 类中的 AAA 类之前移动导入,那么它可以工作:

    val compObjVar = s"""{
        class AAAA {
          import models.presentation.blocks.BlockModel;
          class BBBB {

          }
        }
    }""";

为什么?

4

1 回答 1

7

它打破了文档中的这条规则:

顶级扩展必须保留注释者的数量、他们的风格和他们的名字,唯一的例外是一个类可能会扩展成一个同名的类和一个同名的模块,在这种情况下,它们会按照之前的规则自动成为同伴.

这意味着如果您使用宏注释转换类或特征,它必须扩展为同名的类,或具有同名伴侣的类。也就是说,我们保留了正在扩展的树的根。

如果我们尝试扩展class A为:

import package.name
class A

我们正在扩展的树的根不再是 的class A,而是包含类和新导入的树的根,但它是什么?不可能什么都没有。减少可能的扩展数量会降低插件的复杂性,从而减少可能出错的事情的数量。

如果您必须添加导入,您可以在类中这样做。如果导入需要同时出现在类和伴随对象中,则可以将它们分解为自己的Tree进行拼接。

于 2016-05-30T23:31:19.903 回答