Scanning java tree to visit each node and do some processing using TreeScanner

Any Java class is internally converted into a tree structure where each node of the tree can be a function node, variable node, forloop node etc. Every language semantic present in Java would have a node representation.

Consider this class which has method, variable definitions, try/catch block and a for loop

public class Sample {
	public static void main(String[] args) {
		int x = 10;
 
		try{
			int y  =10/0;
		}catch(Exception e){
 
		}
 
		for(int z=0;z<10;z++){
 
		}
	}
}

We will use TreeScanner class to scan this code. We will extend TreeScanner class and implement our own CustomScanner. In our implementation, we are not doing anything but just printing the value of the node.

package jdk9;
 
import java.io.IOException;
 
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
 
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.CatchTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ForLoopTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.TryTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreeScanner;
 
public class TreeScannerExample {
	public static void main(String[] args) throws IOException {
		TreeScanner<Object, Object> ts = new CustomScanner();
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		StandardJavaFileManager fMgr = compiler.getStandardFileManager(null,
				null, null);
		Iterable<? extends JavaFileObject> units = fMgr
				.getJavaFileObjects("C:\\Downloads\\workspace\\SampleProject\\src\\jdk9\\Sample.java");
		JavacTask task = (JavacTask) compiler.getTask(null, fMgr, null, null,
				null, units);
		for (CompilationUnitTree t : task.parse()) {
			t.accept(ts, null);
		}
	}
 
}
 
class CustomScanner extends TreeScanner<Object, Object> {
 
	public Object visitVariable(VariableTree t, Object o) {
		System.out.println("visitVariable : " + t);
		return super.visitVariable(t,o);
	}
 
 
	public Object visitAssignment(AssignmentTree t,Object o) {
		System.out.println("visitAssignment : " + t);
		return super.visitAssignment(t,o);
	}
 
	public Object visitMethod(MethodTree t,Object o) {
		System.out.println("visitMethod : " + t);
		return super.visitMethod(t, o);
	}
 
	public Object visitForLoop(ForLoopTree t,Object o) {
		System.out.println("visitForLoop : " + t);
		return super.visitForLoop(t, o);
	}
 
	public Object visitTry(TryTree t,Object o) {
		System.out.println("visitTry : " + t);
		return super.visitTry(t, o);
	}
 
	public Object visitCatch(CatchTree t,Object o) {
		System.out.println("visitCatch : " + t);
		return super.visitCatch(t, o);
	}
 
}

Output of above code would be :

visitMethod :
public static void main(String[] args) {
int x = 10;
try {
int y = 10 / 0;
} catch (Exception e) {
}
for (int z = 0; z < 10; z++) {
}
}
visitVariable : String[] args
visitVariable : int x = 10
visitTry : try {
int y = 10 / 0;
} catch (Exception e) {
}
visitVariable : int y = 10 / 0
visitCatch : catch (Exception e) {
}
visitVariable : Exception e
visitForLoop : for (int z = 0; z < 10; z++) {
}
visitVariable : int z = 0

In our custom scanner we had overridden only 5 methods. We can override methods for every possible node

So now you can write your own scanners which can scan the java code and do any kind of processing with those nodes

Mar Java Mit Java 🙂

Uday Ogra

Connect with me at http://facebook.com/tendulkarogra and lets have some healthy discussion :)

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *