Tree
Tree
interface.Tree
. This interface is the foundational contract for all types defined within any abstract syntax tree. A Tree type has the following characteristics:accept()
method that acts as a callback into a language-specific Visitor.print()
methods.TreeVisitor
TreeVisitor<T extends Tree, P>
from which all of OpenRewrite's visitors extend. It is this class that provides the generic, parameterized T visit(T, P)
method that drives a visitor's polymorphic navigation, cursoring, and life-cycle. The parameterized type T
represents the type of tree elements upon which the visitor will navigate and transform. The second parameterized type P
is an additional, shared context that is passed to all visit methods as a visitor navigates a given AST.visitClassDeclaration()
method being called multiple times. The cursor can be used to determine which class declaration represents the top-level class:TreeVisitor
. As an example, the OpenRewrite language binding for Java is JavaVisitor
. It is on these language-specific source visitors that the visit methods for each AST element are defined along with the language-specific traversal logic.TreeBuilder.visit(T, P)
method is called and how that is mapped into its language-specific counterpart. Let's visualize how a Java CompilationUnit is passed from a client to the visitor:visit()
will result in having the compilation unit's accept()
method executed. The accept()
method will then cast the visitor to the language-specific variant and then call the appropriate, language-specific visitCompilationUnit()
method.TreeBuilder.visit()
method also means the developer is circumventing proper cursor management and critical visitor life-cycle management.visitMethodInvocation
is overridden to increment the counter. The JavaVisitor will traverse the AST and call this method each time a method invocation is encountered in the tree.org.openrewrite.java.tree.J
and all of its language-specific visit methods also return J
.visitMethodInvocation
will typically return J.MethodInvocation
, visitCompilationUnit
will typically return a J.CompilationUnit
, and so on. There are a narrow set of circumstances when this is not true. For example, an UnwrapParentheses visitor might override the J.Parentheses<?>
and can return whatever type of expression is inside the parentheses it is unwrapping.refactor
that helps you call super and cast the result in one call:with
call to a variable locally that you return at the end of the visit method.andThen(anotherVisitor)
. This is useful for building up pipelines of refactoring operations built up of lower-level components. For example, when ChangeFieldType finds a matching field that it is going to transform, it chains together an AddImport visitor to add the new import if necessary, and a RemoveImport to remove the old import if there are no longer any references to it.