Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
648 views
in Technique[技术] by (71.8m points)

scala - Can't access Parent's Members while dealing with Macro Annotations

I am kind of blocked with the following (macro annotation) situation. Suppose I have an annotation called @factory which aims to generate an apply method for the annotated trait in the corresponding companion object. For instance, given the trait A:

@factory
trait A {
  val a1: Int
}

the expected code to be generated is the following one:

object A extends Factory[A] {
  def apply(_a1: Int) = new A {
    val a1 = _a1
  }
}

Now suppose we have a trait B which inherits from A:

@factory
trait B extends A {
  val b1: String
}

which is supposed to generate:

object B extends Factory[B] {
  def apply(_a1: Int, _b1: String) = new B {
    val a1 = _a1
    val b1 = _b1
  }
}

In the latter case, I need to know which are the attributes existing at A, but I don't know how to get any information about them. While dealing with macro annotations I have only access to the B trait AST (as a ClassDef). Although its template contains references to the parents (as TypeTrees), both fields tpe and symbol are empty.

It would be great for me to get access to the A AST. However, I think that's not feasible. Therefore, any symbol or type (pointing either the parent or the current type) would be good enough.

If you want to see more implementation details, I have uploaded the project to https://github.com/jesuslopez-gonzalez/cool-factory. It can generate the apply for the local values.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Trees that go into macro annotation arguments are purposefully untyped. However running c.typeCheck(q"(??? : <tree that represents the parent>)").tpe will provide the missing information. Don't forget to duplicate that tree before typechecking, because c.typeCheck mutates the tree in place, which might be undesireable.

In case when both parent and child are declared in the same non-toplevel scope, there will be a problem of typeCheck not seeing the parent, as c.typeCheck's in macro annotations are performed in parent lexical scope, so that annotations don't get to see half-constructed scopes. Something similar has been reported here: https://github.com/aztek/scala-workflow/issues/2#issuecomment-23947943.

The decision to exclude current scope from typechecking is not a final one. This week I'll be thinking a bit more about how macro annotations should interact with enclosing scopes, and will probably change it to do what you would like it to do. I'd do the change right now, but I need to make sure there won't be any insane behaviour arising from that change.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...