-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Test and refactor TreeInfo#defPath #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I'm about to refactor that method in terms of a TreeAccumulator. Note that I've packaged the test case in `dotty.tools.dotc.ast` I believe this is the best approach for organizing unit tests: the import tax is minimized, and use of relative imports is made less fragile by avoiding creating new packages to test code. I'll reorganize the other unit tests like this if others agree.
Uses a TreeAccumulator, rather than ad-hoc descent through `productIterator`.
I tried to change I was going for something like: def contains(that: Positioned): Boolean = {
object accum extends untpd.TreeAccumulator[Boolean] {
override def apply(x: Boolean, tree: untpd.Tree): Boolean = {
def modsContains = tree match {
case md: untpd.MemberDef => md.mods.envelope contains that.pos
case _ => false
}
x || (tree.envelope contains that.pos) || modsContains || foldOver(x, tree)
}
}
(this eq that) || (that mach {
case tree: Tree => accum(false, this)
case mods: Modifiers => ...
}
} class TreesTest extends DottyTest {
@Test
def testContains = checkCompile("frontend", "class A { def bar = { 22 }} ") {
(tree, context) =>
implicit val ctx = context
val aTree = tree.find(tree => tree.symbol.name == typeName("A")).get.asInstanceOf[TypeDef]
val barTree = tree.find(tree => tree.symbol.name == termName("bar")).get.asInstanceOf[ValDef]
assertTrue(bar contains bar.mods)
assertTrue(aTree contains aTree.mods)
assertTrue(aTree contains bar)
assertTrue(aTree contains bar.mods)
assertFalse(barTree contains aTree)
assertFalse(barTree.mods contains barTree)
}
} |
@@ -330,6 +330,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { | |||
def deepFold[T](z: T)(op: (T, tpd.Tree) => T) = | |||
new DeepFolder(op).apply(z, tree) | |||
|
|||
def find[T](pred: (tpd.Tree) => Boolean): Option[tpd.Tree] = | |||
shallowFold[Option[tpd.Tree]](None)((accum, tree) => if (pred(tree)) Some(tree) else accum) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make these available for untyped trees, too?
Regarding a traversal over trees and modifiers: we've added something similar to So maybe it is worth introducing |
The change looks good to me. Regarding contains, we seal Positioned and add a PositionedAccumulator; I see no problem with that. The current solution works, but it's not as extensible as it could be. |
Test and refactor TreeInfo#defPath
Backport "fix: Allow `as` as an infix type in non context bound types" to 3.3 LTS
Review by @odersky