Я пытаюсь собрать все идентификаторы, существующие в области видимости, с помощью неявного макроса, но я не могу найти элегантный способ их найти.Собирать все идентификаторы в области
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
предыдущие захватывает все переменные, даже если они определены в различных методах, но мне нужен способ фильтрации ValDefs, которые происходят в методах от cNames
. Вызов children
выглядел так, как будто он сработал, но я все равно получаю ValDefs из других блоков.
Моя конечная цель состоит в том, чтобы сделать Logger.trace()
и иметь все переменные в области регистрации. Так
def test() = {
val v = 2
val z = "fdsaf"
Logger.trace()
}
бы войти v: 2, z: "fdsaf"
Edit 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:». Я видел ваш запрос на pulling для приложения thewner, который выглядит так, как будто это почти решит это, но я не могу понять, как получить «Tree» из «Symbol». – user60561
Получение дерева из символа невозможно, потому что символы - это просто записи в таблице определений, доступных компилятору, без какой-либо информации об АСТ, прикрепленной к ним. Это может измениться в будущем, но пока это не поддерживается. –
Я не думаю, что на данный момент можно написать такой макрос. Самое близкое, что вы можете найти в сфере действия, - это c.inferImplicitValue, но для этого вам нужно, чтобы ваша вещь была неявной и определенного типа была известна заранее. –