JavaTemplate
, which parses textual code snippets into AST elements ready fo ruse in a visitor.JavaTemplate
produces ASTs that are correctly formatted, fully type-attributed, and able to reference symbols from the lexical scope of insertion.JavaTemplate
are constructed within a JavaVisitor
by calling JavaTemplate.builder()
:String
code snippet. The snippet must be syntactically correct code for the context it is being inserted into. Snippets may reference variables, functions, and other symbols visible within the lexical scope of the insertion point.withTemplate()
. See Usage.#{any(<type>)}
where <type> is the expected type of the parameter. If any type is permissible then the shortest form #{any()}
should be used. When substituting an array type use #{anyArray()}
. Examples of snippets with typed substitution indicators:Object o = #{any()};
boolean b = #{any(boolean)};
foo.acceptsACollection(#{any(java.util.Collection)});
String[] = #{anyArray(java.lang.String)};
String
to a template. Typed substitution indicators are required when supplying an AST element as a template substitution parameter.#{}
when providing a non-AST element like a String
as template substitution argument . When providing an AST element, like a J.Identifier
, into a context where the concept of type is nonsensical first convert them to an appropriate String
. Examples of untyped insertion points include the text of a comment, the name of a class in a class declaration, and keywords like if
or while
. Examples of snippets with untyped substitution indicators://TODO: Fix bug #{}
public class #{} { }
JavaTemplate
has to be informed using the method JavaTemplate.Builder.imports()
. For static imports, use JavaTemplate.Builder.staticImports()
. For example:JavaTemplate
producing AST elements missing type attribution, or failing outright with an exception. While correct source can sometimes be produced from ASTs with missing or inaccurate types it severely compromises interoperability with other recipes. JavaTemplate
does not automatically add a corresponding import to the SourceFile
being refactored. JavaVisitor.maybeAddImport()
is the recommended way to add imports to Java SourceFile
.JavaTemplate
uses a JavaParser
to convert text into AST elements. The default JavaParser
is aware only of types provided by the Java Runtime, so if your snippet references any types from other sources you must supply an appropriately configured JavaParser
.JavaParser.Bulider.classpath(
) can be used to look up libraries by artifactId from the runtime classpath. In this example, the template
snippet references a symbol of type BasicPolymorphicTypeValidator
, which is provided by the jackson-databind library:JavaParser.Builder.dependsOn()
. Stubs must be valid Java source files, but only methods that are used in the template must exist in the stub, and those methods can be implemented with the bare minimum to be syntactically valid method declarations.J.withTemplate()
. This example visitor uses a template to replace all method invocations of countLetters(String)
with withString(String).length()
:J.withTemplate()
requires the specification of coordinates and the values to be filled in for any substitution indicators.JavaVisitor.maybeAddImport()
to add imports for any new types your template might be introducing!J.MethodDeclaration.getCoordinates().replace()
is the appropriate coordinate. But maybe you just want to add an annotation, in which case J.MethodDeclaration.getCoordinates().addAnnotation()
is appropriate. Each AST element exposes different coordinates. All coordinates include a "replace" coordinate to replace the entire AST element with the template result. Look for a getCoordinates()
method to see what other coordinates are available.