1

I am working on a scalac plugin in which I am traversing the AST. Right now I am using a for each loop over the unit.body, which I get from the passed Global value. The issue I am facing is that due to the recursive nature of said for each traversal, I visit each Tree and its children, though I do not want to traverse the latter since I am using pattern matching to match for function calls.

So for example if I would traverse the statement:

x.do(arg1)(arg2)(arg3)

I will get the following things in my traversal:

1. x.do(arg1)(arg2)(arg3)
2.    x.do(arg1)(arg2)
3.        x.do(arg1)
4.            x.do
5.                x
6.                do
7.            arg1
8.        arg2
9.    arg3

Here I indented the Tree objects in order of traversal. Now if I would use the Apply case class to match with each of these, I would get a match out of 1,2, and 3, while I really only want 1. I thought about using a context sensitive solution (like check against the previous traversed Tree) but it is not consistent enough for my purposes. I am also not looking for specific methods, which would make matching easier, but for methods in general, but I cannot allow for these children to be counted.

Is there a better pattern I can match function calls with when writing a scalac plugin, or a better way to do the traversal, so that I do not run into this recursion issue?

MrDeal
  • 373
  • 2
  • 11

1 Answers1

0

I found the answer myself: Instead of using the intuitive

for(tree <- treeObject), where treeObject : Tree

You can just use the children object in each Tree object and do the following

def func(treeObject : Tree) : Something = {
    for(tree <- treeObject.children) {
        if(/*your condition for further traversal*/)
            func(treeObject : Tree) //RECURSE
        else
            someValue //do whatever and RETURN
    }
}

With this approach you can set a stopping condition for traversal. So let's say you only want to look at each method invocation. A method invocation can be matched for using the Apply case class. Now you can just check whether or not your current tree matches with that pattern. If it does you do your work on it and return. If it is not traverse the Tree further by using recursion, to get possible method invocations further "down".

MrDeal
  • 373
  • 2
  • 11