Fixes

Recipes contain a list of availableFixes. A fix defines a name, the actions that will be executed, and configuration regarding the import processing functionality of Sensei.

availableFixes:
- name: My first fix
  actions:
  - rewrite:
      to: Logger.log({{{arguments}}})

name

The name that will be shown while selecting the fix from the intentions menu.

actions

This is a collection of Actions that define what this fix will do.

availableIf

Provides a way to only make this fix available if a certain condition passes. Conditions can be checked on the marked element, "followed by" element or any labeled element. Single actions in a fix may also have conditions using applyIf.

markedElement

With markedElement, the condition will be checked against the element that matched the search part of the recipe.

 search:
   methodcall:
     anyOf:
     - name: warning
     - name: info
     type: java.util.logging.Logger
 availableFixes:
 - name: Change to org.slf4J.Logger#warn
   availableIf:
     markedElement:
       is:
         methodcall:
           name: warning
   actions:
   - rewrite:
       to: slf4jlogger.warn({{{arguments}}})
 - name: Change to org.slf4J.Logger#info
   availableIf:
     markedElement:
       is:
         methodcall:
           name: info
   actions:
   - rewrite:
       to: slf4jlogger.info({{{arguments}}})
-     logger.info("hi");
+     slf4jlogger.info("hi");

-     logger.warning("hi");
+     slf4jlogger.warn("hi");

followedByElement

Similar to markedElement, but here the condition is checked against the "followed by" element.

label

Similar to markedElement, but here the condition is checked against the element with the associated label.

 search:
   methodcall:
     args:
       1:
         label: level
         type: java.util.logging.Level
       2:
         type: java.lang.String
     name: log
     type: java.util.logging.Logger
 availableFixes:
 - name: Change to org.slf4j.logging.Logger#info
   actions:
   - rewrite:
       to: slf4jlogger.info({{{arguments.1}}})
   availableIf:
     label:
       labelName: level
       is:
         reference:
           name: java.util.logging.Level.INFO
 - name: Change to org.slf4j.logging.Logger#warn
   actions:
   - rewrite:
       to: slf4jlogger.warn({{{arguments.1}}})
   availableIf:
     label:
       labelName: level
       is:
         reference:
           name: java.util.logging.Level.WARNING
-     logger.log(Level.INFO, "hi");
+     slf4jlogger.info("hi");

-     logger.log(Level.WARNING, "hi");
+     slf4jlogger.warn("hi");

processImports

By default Sensei imports the qualified names this behaviour can be changed using processImports. When processImports is true the fully qualified references will be dequalified and imported, when processImports is false the fully qualified references will stay fully qualified.

availableFixes:
- actions:
  - addField:
      field: private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger({{{containingClass.name}}}.class);
  processImports: false
   class MyClass {
+      private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
   }
availableFixes:
- actions:
  - addField:
      field: private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger({{{containingClass.name}}}.class);
  processImports: true
+  import org.slf4j.Logger;

   class MyClass {
+      private static Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
   }

doStaticImports

The doStaticImports option can be used to let Sensei statically import the fully qualified references.

availableFixes:
- actions:
  - rewrite:
      to: org.junit.assert.Assert.assertEquals({{{arguments.2}}}, {{{arguments.1}}})
  doStaticImports: true
+  import static org.junit.assert.Assert.assertEquals;

-  Assert.assertEquals(actual, expected);
+  assertEquals(expected, actual);

Warning

doStaticImports will not have any impact when processImports is false as that setting completely negates any import processing.