QualifierOrScopeOnInjectMethod
Qualifiers/Scope annotations on @Inject methods don't have any effect. Move the qualifier annotation to the binding location.

Severity
WARNING
Tags
LikelyError

The problem

The @Inject annotation is applied to injection points - methods, constructors, or fields that a dependency injection tool like Guice or Dagger will invoke or populate to construct an object.

Scope annotations (annotations that are themselves annotated with @ScopeAnnotation) are used to denote the ‘effective scope’ of an object. Examples of scope annotations include @Singleton, @RequestScope, @SessionScope. These annotations can be used either on the declaration of a type (so that every instantiation of that object will be handled with the appropriate scope), or on a provider method (to declare that the particular binding declared by that provider method is subject to that annotation’s scoping rules):

@Singleton
class ExpensiveGlobalObject {
    @Inject ExpensiveGlobalObject(SomeDependencies stuff) {...}
}

class SomeModule extends AbstractModule {
    ...
    @Provides
    @Singleton
    OtherExpensiveObject provideOtherExpensiveObject() { return new Gold(); }
}

Qualifier annotations (annotations that are themselves annotated with @Qualifier or @BindingAnnotation) are used to distinguish different instances of the same type of object (the @Red Robot instead of the @Blue Robot). These annotations can be used inside injection points, or on those provider methods:

class RobotArena {
    @Inject RobotArena(@Red Robot redBot, @Blue Robot blueBot) {...}
}

class SomeModule extends AbstractModule {
    ...
    @Provides
    @Red
    Robot provideRedRobot() { return new Robot("red"); }
}

Notably: there is no method declaration where @Inject and either a scope or a qualifier annotation can reasonably coexist. Either the method is an injection point, and the dependency injection system will ignore the scope or qualifier annotation, or the method is a provider method, and the @Inject method won’t have any effect, as modules are constructed without a dependency injection container.

class Example {
  // Here, @Singleton is ignored. Perhaps the scope should go onto Example, to make dependency
  // injection systems treat the Example type as a singleton.
  @Inject @Singleton
  Example(Robot something) {}
}
class MyModule extends AbstractModule {
  ...
  // The `@Inject` doesn't do anything: Guice will use this method to define a Singleton binding
  // for Database. When a Database is constructed by Guice, a DatabaseCredentials will be
  // constructed and this method will be invoked, but it isn't invoked until then.
  @Provides @Singleton @Inject
  Database providesSingletonDatabase(DatabaseCredentials db) { ... }
}

Suppression

Suppress false positives by adding the suppression annotation @SuppressWarnings("QualifierOrScopeOnInjectMethod") to the enclosing element.