Có cách nào thuận tiện để biến một số MethodSymbol
sang bên trái của cây định nghĩa phương thức (ví dụ: DefDef
) trong Scala 2.10 không?Tạo cây định nghĩa phương thức từ biểu tượng phương thức và một nội dung
Ví dụ: giả sử tôi muốn tạo macro sẽ lấy một cá thể của một đặc điểm và bao bọc tất cả các phương pháp của đặc điểm đó bằng một số chức năng gỡ lỗi. Tôi có thể viết như sau:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object WrapperExample {
def wrap[A](a: A): A = macro wrap_impl[A]
def wrap_impl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]) = {
import c.universe._
val wrapped = weakTypeOf[A]
val f = Select(reify(Predef).tree, "println")
val methods = wrapped.declarations.collect {
case m: MethodSymbol if !m.isConstructor => DefDef(
Modifiers(Flag.OVERRIDE),
m.name,
Nil, Nil,
TypeTree(),
Block(
Apply(f, c.literal("Calling: " + m.name.decoded).tree :: Nil),
Select(a.tree, m.name)
)
)
}.toList
//...
}
Tôi đã elided kinh doanh nhàm chán của những phương pháp này gắn bó trong một lớp ẩn danh mới mà thực hiện các đặc điểm và sau đó instantiating rằng đẳng cấp bạn có thể tìm thấy trọn vẹn một ví dụ làm việc here nếu bạn' lại quan tâm.
Bây giờ tôi có thể viết những dòng này, ví dụ:
scala> trait X { def foo = 1; def bar = 'a }
defined trait X
scala> val x = new X {}
x: X = [email protected]
scala> val w: X = WrapperExample.wrap[X](x)
w: X = [email protected]
scala> w.foo
Calling: foo
res0: Int = 1
scala> w.bar
Calling: bar
res1: Symbol = 'a
Vì vậy, nó hoạt động, nhưng chỉ trong trường hợp rất đơn giản-nó sẽ không nếu đặc điểm có phương pháp với danh sách tham số, với bổ truy cập, chú thích, v.v.
Điều tôi thực sự muốn là hàm sẽ lấy biểu tượng phương thức và cây cho phần nội dung mới và trả lại DefDef
. Tôi đã bắt đầu viết một bằng tay, nhưng nó liên quan đến rất nhiều thứ khó sử dụng như thế này:
List(if (method.isImplicit) Some(Flag.IMPLICIT) else None, ...)
Đó là gây phiền nhiễu, tiết và dễ bị lỗi. Tôi có thiếu một số cách hay hơn để thực hiện điều này trong API phản chiếu mới không?
Cảm ơn (và +1), nhưng nếu đặc điểm tôi đang tìm kiếm là gì? Trong trường hợp đó tôi bị mắc kẹt với cách tiếp cận ở trên, phải không? –
Ah, tôi hiểu ý của bạn là gì. Bạn có thể sử dụng API này: https://github.com/scalamacros/kepler/blob/0acb8a30c379f268e8a3e1340504530493a1a1dc/src/reflect/scala/reflect/api/Trees.scala#L2480. Chúng tôi đã không dùng nó trong phiên bản 2.10.1, nhưng bạn có thể xem cách triển khai: https://github.com/scalamacros/kepler/blob/0acb8a30c379f268e8a3e1340504530493a1a1dc/src/reflect/scala/reflect/internal/Trees.scala#L975 . –