methodcall

public void userMethod() {
    otherMethod();
}

Invokes a method.

Configuration options

type

Checks the type which the method is called on. In case of a static method call

search:
  methodcall:
    type: MyClass
public void example() {
   MyClass m = new MyClass();
   m.someMethod();
}
public void example() {
   MyClass.someStaticMethod();
}

See also

The examples above use shorthands, see type target for more advanced configurations

name

Matches the name of the method.

search:
  methodcall:
    name: someMethod
public void example() {
   MyClass m = new MyClass();
   m.someMethod();
}
public void example() {
   MyStaticClass.someMethod();
}

See also

The examples above use shorthands, see string target for more advanced configurations

declaration

The place where the method is defined will be resolved and matched against a method target.

search:
  methodcall:
    declaration:
      annotation:
        type: "SomeAnnotation"
@SomeAnnotation
public void action() {
}

public void doSomething() {
   this.action();
}

returnType

Checks the return type of a method.

search:
  methodcall:
    returnType: String
public String action() {
}

public void doSomething() {
   String test = this.action();
}
public String action() {
}

public void doSomething() {
   Object test = this.action();
}

Note that we don't check the type of the variable that the result value is assigned to. Instead we check the actual return type of the method call.

See also

The examples above use shorthands, see type target for more advanced configurations

args

Checks the arguments of the method call. This option is configured as a list of argument targets. There is a possibility to specific match a certain argument (based on the position) or to choose the any match.

search:
  methodcall:
    args:
      1:
        value: "1"
      2:
        value: "2"
public void action(int a, int b) {
}

public void doSomething() {
   this.action(1, 2);
}

argCount

Checks the number of arguments

search:
  methodcall:
    argCount: 2
public void action(int a, int b) {
}

public void doSomething() {
   this.action(1, 2);
}

See also

The examples above use shorthands, see integer target for more advanced configurations

on

Looks at the declaration of the instance that this object has been called on. This option can be used to search for instances where method chaining or builder patterns are used.

search:
  methodcall:
    name: equals
      on:
        methodcall
          name: toLower
public bool matches(String input) {
   return input.toLower().equals("sensei");
}

As seen in the example, the on allows the user to specify another target. See Targets for all available options.

The examples also indicate a common case for this type of configuration, where we want to search for consecutive method calls that can be replaced by a single, more robust one. In this example, we could replace this into a single method call equalsIgnoreCase.

followedBy

Checks if the returned instance has been used as:

  • the instance of which a method gets called on

  • as argument of another method call

  • or as an implicit call (e.g. close gets implicitly called when using a try-with-resources)

search:
  methodcall:
    name: createSecureXmlFactory
    followedBy:
      methodcall:
        name: setSecure
public bool matches(String input) {
   XmlFactory xml = createSecureXmlFactory();
   xml.setSecure();
}

The example above illustrates how to search for unnecessary explicit configurations.

In practice, this configuration will mostly be used together with the negation block not.

search:
  methodcall:
    name: createCookie()
    not:
      followedBy:
        methodcall:
          name: setSecure
public bool matches(String input) {
   Cookie cookie = createCookie();
}

before

This option only becomes significant in combination with followedBy. It adds a constraint to the analyzer to stop scanning the code when target is matched.

search:
  methodcall:
    not:
      followedBy:
        methodcall:
          name: "setSecure"
      before:
        methodcall:
          type: "Response"
          name: "addCookie"
public bool matches(String input) {
   Cookie cookie = createCookie();
   Response.addCookie(cookie);

   // the cookie creation will still be marked since the setSecure
   // has been called to late.
   cookie.setSecure(true);
}

Generic Configuration options

The following options are generic and available for every target.

anyOf

Similar to the logical operator OR: one or more descendant options should match.

search:
  <target>:
    anyOf:
    - name: "illegal"
    - name: "alsoIllegal"

allOf

Similar to the logical operator AND: all descendant options must match.

search:
  <target>:
    allOf:
    - annotation: "HttpPost"
    - annotation: "AllowUnAuthorized"

with

The only purpose to use this field is to make the recipe easier to read. It provides no additional functionality.

search:
  <target>:
    with:
      annotation: "HttpPost"

not, without

Works as the logical operator NOT. It will negate the result of the descendant options. Sensei presents the user with both options. They display the same behavior, but certain scenarios tend to read better using without.

search:
  <target>:
    not:
      annotation: "HttpPost"
search:
  <target>:
    without:
      annotation: "HttpPost"

in

Performs a structural search, this option is mainly used to narrow down recipes. Examples of this would be to only analyze and mark code inside a certain class or method that has a specific annotation. However, we haven't limited this option to only support these two scenarios. More advanced configuration can be achieved.

search:
  <target>:
    in:
      class:
        name:
          contains: "Controller"
search:
  <target>:
    in:
      method:
        annotation:
          type: "HttpPost"

label

Labels do not modify the behavior of searching elements, but they allow addressing a specific element in a quick fix.

search:
  element:
    tagName: inner
    attribute:
      name: data
    in:
      element:
        label: outerelement

availableFixes:
- name: add the 'type' attribute on the outer element
  actions:
  - add:
      attribute:
        name: type
        value: '"unsafe"'
      target: label:outerelement
- <outer>
+ <outer type="unsafe">
      <inner data="test"/>
  </outer>