Trees
Trees is an abstract class (com.sun.source.util.Trees) which has two implementations, namely JavacTrees and DocTrees. Both live in com.sun.tools.javac.api. Trees, in its various implementations, is a helper class that, according to the short javadoc comment on top, bridges JSR 199, JSR 269, and the Tree API.
- JSR 199 describes javax.tools
- JSR 269 describes javax.lang.model
- The Tree API describes com.sun.source.tree
The javax.tools package contains interfaces like JavaCompiler, JavaFileManager and Tool, plus classes like SimpleJavaFileObject and ToolProvider. The javax.lang.model package contains the subpackages element (interfaces for Symbol (sub)classes), type (interfaces for (sub)types of Type, and util (abstract Visitor classes for different Java versions, plus Elements interface that is implemented by com.sun.tools.javac.model.JavacElements, the latter being a utility class to operate on ‘program elements’). The com.sun.source.tree contains all Tree interfaces.
What can be bridged
In this section I sum up all the ‘bridges’ that Trees can make, ie the conversions form one sort of object to another. These are not casts, it is more like
From TreePath to Symbol
If we look at the first code block in the previous blog post, where we try to pick the ClassSymbol from a file, we use this line:
currentClass = (ClassSymbol) trees.getElement(getCurrentPath());
It is the getElement(TreePath treePath) that makes the bridge. It returns the interface type (Element) by default, but with a cast you can get the underlying runtime type.
If the element is not available (it is a field in JCTree but it is only set somewhere during the analyze phase), the method will return null.
If the TreePath does not identify a Tree that has a Symbol in it, the method returns an IllegalArgumentException.
From Symbol to TreePath
This method returns a TreePath if you provide a Symbol:
public abstract TreePath getPath(Element e);
If the node cannot be found, it will return null.
From Symbol to Tree
This method is less powerful than the previous one. Returns null if the node cannot be found:
public abstract Tree getTree(Element element);
From Tree to TreePath
Often you need the TreePath, because via TreePath you can find Symbol:
public abstract TreePath getPath(CompilationUnitTree unit, Tree node);
Note that when you work in an extension of TreePathScanner, you can use this method:
public TreePath getCurrentPath() {
return path;
}
TreePathScanner always knows its TreePath. This getCurrentPath() method is actually the only new method that is provided by TreePathScanner above everything that is inherited from its parent TreeScanner.
From TreePath to Scope
While I don’t know where I could put this method to use, I know there is a relationship between TreePath and Scope and that both are required to understand semantics, and semantics requires context. The implementation of this method in JavacScope is not an easy one, it involves classes JavacScope, AttrContext and Env.
public abstract Scope getScope(TreePath path);