Templating

Sensei uses mustache templating to extend the recipe writing capabilities. Properties that support this can be identified by a table that will show below their input box. This table (also called the mustache code browser) is populated with available variables and their previews. There are also some functions available to manipulate the variables.

Variables

search:
  methodcall:
    name: "getLogger"
    args:
      1:
        not:
          value: "{{{containingClass.name}}}.class"

Variables can be used by surrounding them with three curly braces.

When used in the search, the available variables are relative to the searched element. In the example above, the containingClass.name is based off the searched method call. This results in the name of the class where the marked method call belongs to.

When used in the quickfix, the available variables are relative to the quickfix target. For example, when the target is containingClass, all variables are relative to the parent class. When variables relative to the marked element are needed, the markedElement variable can be used.

Note

Be aware that the table will not appear when rule previews are not available.

Note

Arrays in mustache are zero based, {{{arguments.0}}} will result in the first argument.

markedElement

The variable context in quickfix actions are based off the target the action is performed upon. For example, when the addAnnotation action is used with target parentField, the variables of the field will be available. To use the variables of the element that was marked, the special variable markedElement can be used.

Following example replaces a deprecated annotation with its successor. The {{{name}}} variables is coming from the field which is the target of the quickfix action. To copy the original value of the old annotation, the {{{markedElement.elementValuePairs}}} variable is used, utilizing the markedElement variable.

@DisplayName("Counter value")
int counter;
search:
  annotation:
    type: "DisplayName"
availableFixes:
- name: "Replace with the new @Name annotation"
  actions:
  - remove: {}
  - addAnnotation:
      annotation: "@Name(serialize = \"field_{{{name}}}\", display = {{{markedElement.elementValuePairs}}})"
      target: "parentField"
@Name(serialize = "field_counter", display = "Counter value")
int counter;

IDE properties

Some IDE and environment properties are also available as variables. Some IDEs may have extra properties available, but the table below shows all the properties that all the IDEs support.

Property

Sample output

IDE.USER

username

IDE.PROJECT_NAME

sensei-demo-project

IDE.DATE

12/09/2012

IDE.YEAR

2012

IDE.TIME

12:46

Basic Functions

Functions can be used using the following syntax:

{{#lowerCase}}{{{ containingClass.name }}}{{/lowerCase}}

Function

Input

Result

lowerCaseFirst

ArrayList

arrayList

upperCaseFirst

linkedList

LinkedList

lowerCase

NORTH

north

upperCase

Arrays

ARRAYS

camelToUnderscoreCase

ConcurrentHashMap

concurrent_hash_map

The sed Function

The sed function allows more advanced operations. It function consists of two arguments, separated with a comma. The first being the sed-pattern and the second is the input which the operation is performed upon.

{{#sed}}s/example/world/,hello example{{/sed}}

If either the sed-pattern or the input contains commas, the argument has to be wrapped with the encodeString function.

{{#sed}}s/example/world/,{{#encodeString}}{{{ args.1.value }}}{{/encodeString}}{{/sed}}
{{#sed}}{{#encodeString}}s/ example/, world/{{/encodeString}},{{#encodeString}}Hello example{{/encodeString}}{{/sed}}

Applying the above example to the string literal Hello example will result into Hello, world.

Capture groups

The sed function also supports the use of capture groups. In the example below a capture group is used to change the the name without changing anything else.

private String s;
{{#sed}}s/private ([^ ]+) (.*)/private $1 prefixed_$2/,{{{.}}}{{/sed}}
private String prefixed_s;

Note

Capture group $0 will insert the input that was given.