我試圖通過使用隱式宏來收集範圍中存在的所有標識符,但我無法找到找到它們的優雅方法。收集範圍內的所有標識符
val endPos = c.enclosingPosition.endOrPoint
val mNames = c.enclosingMethod
.collect {case v: ValDef => v}
.filter(_.pos.start > endPos)
.map {case ValDef(_, name, _, _) => Ident(name)}
val cNames = c.enclosingClass
.collect {case ValDef(_, name, _, _) => Ident(name)}
val names = mNames ++ cNames
先前捕獲的所有變量,即使它們在不同的方法定義,但我需要一種方法來過濾從cNames
發生在方法ValDefs。調用children
看起來可能有效,但我仍然從其他塊中獲取ValDefs。
我的最終目標是能夠做到Logger.trace()
,並記錄範圍內的所有變量。所以
def test() = {
val v = 2
val z = "fdsaf"
Logger.trace()
}
將登錄v: 2, z: "fdsaf"
編輯2:
import c.universe._
val callingPos = c.enclosingPosition
val encMet = Option(c.enclosingMethod)
val classElements = c.enclosingClass
.asInstanceOf[ImplDefApi]
.impl.children
.collect {
case v: Block => v.asInstanceOf[Tree]
case v: DefDef => v.asInstanceOf[Tree]
case v: ValDef => v.asInstanceOf[Tree]
case v: ModuleDef => v.asInstanceOf[Tree]
}
val classFields = classElements.collect {case [email protected](_, name, _, _) if !v.isEmpty => Ident(name)}
val blockFields = classElements.collectFirst{
case Block(body, ret) if positionIsInList(c)(body) => body.collect {
case [email protected](_, name, _, _) if v.pos precedes callingPos => Ident(name)
}
}.getOrElse(List())
val methodFields = encMet
.map(_.collect {case [email protected](_, name, _, _) if v.pos precedes callingPos => Ident(name)})
.getOrElse(List())
val names = classFields ++ blockFields ++ methodFields
作品在大多數情況下,但未能上塊。
我編輯了我的問題來解決我的最終目標,就在'編輯2'之前。我已經看到了你的拉動請求enclosingOwner,看起來它幾乎可以解決這個問題,但我無法弄清楚如何從'Symbol'中獲得'Tree'。 – user60561
從符號中獲取樹是不可能的,因爲符號只是編譯器可用的定義表中的條目,沒有附加任何AST信息。這可能會在未來發生變化,但到目前爲止它不受支持。 –
我不認爲現在可以編寫這種宏。查找範圍內最接近的內容是使用c.inferImplicitValue,但爲此,您需要將事物隱式化,並事先知道某種類型。 –