How to identify a while(true) loop in a synthax tree with quasiquotes

Hi, I am trying to identify a while(true){block_of_code} in a sythax tree using a quasiquote.

Using the quasiquote q"while ($expr) $expr" from the quasiquote patterns page recognises other while loops but not while(true) loops.

How can I do this with a quasiquote?

The same quasiquote q"while (true) $expr" should work

def test(t: Tree) = t match {
  case q"while (true) $expr" => println(s"expr=$expr")
  case _ => println("default")

test(q"while (true) i=1") //expr=i = 1
test(q"while (false) i=1") //default
test(q"while (x == x) i=1") //default
1 Like

Hmm, that doesn’t seem to work from within a compiler plugin while analysing source code line by line. Admittedly I am parsing each line as a Trees#Tree rather than just a Tree but the matching of other while statements works fine.
The quasiquote q"while ($expr) $expr" picks up only while loops without true/false as the condition by the way, rather than picking up all of them.

A while loop is represented as a LabelDef and an If block. I think there’s a compiler phase that transforms if (true) x else y expressions to x. If your plugin runs after that phase I guess it doesn’t recognize that LabelDef as a while loop anymore cause the If block is gone.

If that’s the case you could match on LabelDef(_, _, rhs) and check that rhs is not an If tree. I haven’t tested any of this though.


Here’s what I do in my scala-fortify plugin. It’s a late-phase compiler plugin, so as Jasper indicates, it must handle already-transformed trees. As a result, I don’t use quasiquote-based matching at all.

My plugin is closed-source, but here’s the relevant snippet of code:

      // while(true) / do while(true)
      case LabelDef(
          block @ Block(statements, Apply(Ident(TermName(name2)), List())))
          if (name.startsWith("while$") || name.startsWith("doWhile$")) && name2 == name =>

You might look at Scala.js, which is also a late-phase plugin but is open-source. I bet it has a similar match in it. (It’s even possible I cribbed my version from Scala.js…)


Thanks that worked!