2016-05-30 71 views
2

我註釋的性狀,如:斯卡拉宏觀與import語句不工作

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

      } 
     } 
    }"""; 

爲什麼?

回答

6

它打破從documentation這條規則:

頂級擴張必須保留annottees,他們的口味,他們的名字的數量,唯一的例外是一類可能擴展到一個同名類加上一個相同名稱的模塊,在這種情況下,它們將按照以前的規則自動成爲夥伴。

這意味着如果您正在使用宏註釋來轉換類或特徵,則它必須擴展爲具有相同名稱的同類名稱的類或類。也就是說,我們保留了正在擴展的樹的根。

如果我們試圖擴大class A到:

import package.name 
class A 

我們正在擴大該樹的根沒有class A不再是那個,而是一個包含類和新的進口,但它是什麼?它不能一無是處。減少可能的擴展數量可以降低插件的複雜度,從而減少出錯的可能性。

如果您必須添加導入,您可以在課程中這樣做。如果進口需要同時出現在班級和伴侶對象中,則可以將它們分解到自己的Tree中進行拼接。