scala宏与import语句不起作用

时间:2016-05-30 22:26:28

标签: scala scala-macros scala-macro-paradise

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

@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 {

          }
        }
    }""";

为什么?

1 个答案:

答案 0 :(得分:7)

它违反了documentation

的规则
  

顶级扩展必须保留注释的数量,它们的风格和名称,唯一的例外是类可以扩展为同名类加上同名模块,在这种情况下它们会自动成为同伴按照以前的规则。

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

如果我们尝试将 $('#objects img').resizable({ handles : 'se', stop : resizestop }).parent('.ui-wrapper').draggable({ revert : 'invalid' }); 扩展为:

class A

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

如果必须添加导入,则可以在类中添加。如果导入需要同时出现在类和伴随对象中,则可以将它们考虑在自己的class A中进行拼接。