2014-05-13 127 views
1

我试图定义一个扩展到类与伴侣对象的案例类的宏注释,但我运行在一些问题。斯卡拉类扩展与伴侣的宏扩展:类型未找到

我可以创建一个与该类名称相同的对象,并在其上定义方法。 但是当我尝试使用类的类型名称作为方法的返回类型或参数类型,我得到一个“未找到:键入”

class term extends StaticAnnotation { 
def macroTransform(annottees: Any*) = macro termMacro.impl 
} 

object termMacro { 

def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { 
    import c.universe._ 
    val inputs = annottees.map(_.tree).toList 

    val (cls, comp) = annottees.map(_.tree) match { 

     case [email protected]"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$_ } with ..$_ { $self => ..$stats }" :: tail => 

      val paramnames = paramss.head.map { 
       case q"$mods val $name: $tpt = $default" => name 
      } 

      val ctorparams = List(paramss.head ++ Seq(
       q"val position: SourcePosition = (0,0)" 
      )) 

      val ctorname = TermName(tpname.decodedName.toString) 
      //val clstype = 
      (
       q""" 
         import ast.Term 
         case class $tpname(...$ctorparams) extends Term { $self => 
          def children() = { 
           List(..$paramnames) 
          } 

          ..$stats 
         } 
       """, 
       q""" 
         object $ctorname { 
          def unapply(t: $tpname): Option[(Int, Int)] = { 
           Some(Tuple2(3, 4)) 
          } 
        } 
       """ 
      ) 

     case head :: tail => 
      c.abort(c.enclosingPosition, s"The @Term annotation is for case classes, found $head") 
    } 

    c.error(c.enclosingPosition, showRaw(cls) + "\n" + showRaw(comp)) 
    c.Expr[Any](Block(List(cls, comp), Literal(Constant(())))) 
} 
} 

例如用法是:@term case class A(x: Term) extends Term,并会给我的编译器错误“未找到:A型”在这个定义的位置@term

我已经收窄的位置下降到对象定义的不应用方法

。 。

任何帮助表示赞赏 我非常新斯卡拉宏,所以任何进一步的建议也可以理解

方的问题:在的IntelliJ/gradle这个项目调试宏任何意见

+0

对我来说它说“方法不适用被定义两次”。你能否将整个项目发布到某个地方在github? –

+0

感谢你看看这个,尤金。如果可能的话,我想暂时保留这个项目的私有权限,但由于我希望你的进一步帮助,我已经给你访问github上的repo。分支术语宏包含如此处所示的宏定义。 –

+0

我以前见过类似的错误btw。看起来,case class的自己的伴侣对象仍然由编译器创建。 –

回答

1

q"import foo; class Bar"创建?一个块,所以宏注释会失效tly用{ import foo; class Bar }代替class Bar,这使得Bar成为一个本地类,它在块外部是不可见的。

+0

(Re)移动导入确实修复了它。感谢您花时间检查项目并帮助我解决这个问题。最亲切。自从我在代尔夫特大学(在代理Spoofax工作的人)听到你的讲话以来,我一直期待着自己检查Scala宏。我对你正在做的工作印象最深刻。看到你的项目产生了多少有趣的后续工作,这是不可思议的。我将密切关注钯金项目。 –