Я называю компилятор Scala 3 библиотекой, которая дает вам CompilationUnit
за исходный код после компиляции. Здесь есть tpdTree
, который, судя по его звучанию, должен содержать информацию о типе.
Я пытаюсь пройти по дереву, чтобы получить любой символ типа:
atPhase(Phases.typerPhase.next) {
// traverse unit.tpdTree...
}
Где выглядит ходьба по дереву:
class ValExtractor(tpes: Set[String]) extends tpd.TreeTraverser:
def isAcceptableType(tpe: Types.Type)(using ctx: Context): Boolean =
tpe.baseClasses.exists { sym =>
tpes.contains(sym.fullName.toString)
}
override def traverse(tree: tpd.Tree)(using ctx: Context): Unit =
tree match
case tpd.ValDef(name, tpt, _) if isAcceptableType(tpt.tpe) =>
println("do something")
case t: tpd.Template => this((), t.body)
case t: tpd.PackageDef => this((), t.stats)
case t: tpd.TypeDef => this((), t.rhs)
case _ => ()
end ValExtractor
я получил
[info] assertion failed: denotation class Int invalid in run 1. ValidFor: Period(1..55, run = 2)
[info] scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
[info] dotty.tools.dotc.core.Denotations$SingleDenotation.updateValidity(Denotations.scala:719)
[info] dotty.tools.dotc.core.Denotations$SingleDenotation.bringForward(Denotations.scala:744)
[info] dotty.tools.dotc.core.Denotations$SingleDenotation.toNewRun$1(Denotations.scala:803)
[info] dotty.tools.dotc.core.Denotations$SingleDenotation.current(Denotations.scala:877)
[info] dotty.tools.dotc.core.Symbols$Symbol.recomputeDenot(Symbols.scala:122)
[info] dotty.tools.dotc.core.Symbols$Symbol.computeDenot(Symbols.scala:116)
[info] dotty.tools.dotc.core.Symbols$Symbol.denot(Symbols.scala:109)
[info] dotty.tools.dotc.core.Symbols$.toDenot(Symbols.scala:502)
[info] dotty.tools.dotc.core.Denotations$SingleDenotation.updateValidity(Denotations.scala:718)
[info] dotty.tools.dotc.core.Denotations$SingleDenotation.bringForward(Denotations.scala:744)
[info] dotty.tools.dotc.core.Denotations$SingleDenotation.toNewRun$1(Denotations.scala:803)
[info] dotty.tools.dotc.core.Denotations$SingleDenotation.current(Denotations.scala:877)
[info] dotty.tools.dotc.core.Types$NamedType.computeDenot(Types.scala:2253)
[info] dotty.tools.dotc.core.Types$NamedType.denot(Types.scala:2213)
[info] dotty.tools.dotc.core.Types$NamedType.info(Types.scala:2201)
[info] dotty.tools.dotc.core.Types$TypeRef.underlying(Types.scala:2693)
[info] dotty.tools.dotc.core.Types$Type.baseClasses(Types.scala:600)
Что я делаю не так?
В моем случае в моем методе было (using ctx: Context)
, но, видимо, это не соответствовало контексту запуска. Передача его явно следующим образом исправила его:
atPhase(Phases.typerPhase.next) {
(new ValExtractor(valTypes.toSet)).getVals(unit.tpdTree)
}(using run.runContext)
Вам нужно запустить запрос в контексте, где значение run
такое же, как и при создании определений (или это более поздний запуск, но более ранний запуск недействителен).
Сообщение об ошибке, которое вы видите, заключается в том, что вы спрашиваете об обозначении символа в прогоне 1, который концептуально был создан до того, как он был создан в прогоне 2.
См. https://thewikihow.com/video_WxyyJyB_Ssc для видео, в котором объясняется концепция запуска/фазы.
Спасибо за ответ. Передача в контексте явно зафиксировала это: