Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom annotation to suppress a specific FindBugs warning

I want to create custom annotations to suppress individual FindBugs warnings to make it easier to use them via code-completion. For example, this one ignores constructors that don't set all @Nonnull fields.

@TypeQualifierDefault(ElementType.CONSTRUCTOR)
@SuppressFBWarnings("NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR")
@Retention(RetentionPolicy.CLASS)
public @interface SuppressNonnullFieldNotInitializedWarning
{ }

However, I still see the warning when using the annotation.

public class User {
    @Nonnull
    private String name;

    @SuppressNonnullFieldNotInitializedWarning
    public User() {
        // "Nonnull field name is not initialized by new User()"
    }
}

I've tried different retention policies and element types, putting the annotation on the constructor and the class, and even @TypeQualifierNickname.

This same pattern works to apply @Nonnull to all fields in a class.

@Nonnull
@TypeQualifierDefault(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldsAreNonnullByDefault
{ }

FindBugs correctly displays a warning for code that assigns null to name.

@FieldsAreNonnullByDefault
public class User {
    private String name;

    public UserModel() {
        name = null;
        // "Store of null value into field User.name annotated Nonnull"
    }
}

I believe the problem is that @SuppressFBWarnings is not marked with @TypeQualifier while @Nonnull is, and thus @TypeQualifierDefault and @TypeQualifierNickname don't apply to it. But there must be some other mechanism to apply one annotation using another.

like image 422
David Harkness Avatar asked Jan 11 '13 19:01

David Harkness


People also ask

What is suppress warning annotation?

Annotation Type SuppressWarnings Note that the set of warnings suppressed in a given element is a superset of the warnings suppressed in all containing elements. For example, if you annotate a class to suppress one warning and annotate a method to suppress another, both warnings will be suppressed in the method.


1 Answers

(Not specifically answering the question), but if you just want to make code-completion work better with @SuppressFBWarnings, you could define a static final String for each of the warning codes and then use those in the annotation. e.g.

public final class FBWarningCodes {
    private FBWarningCodes() { }

    public static final String NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR = "NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR";
}

Then:

import static com.tmobile.tmo.cms.service.content.FBWarningCodes.*;

@SuppressFBWarnings(NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR)

(though admittedly Eclipse doesn't want to do code-completion unless you specify value= in the annotation)

like image 133
paulcm Avatar answered Oct 11 '22 03:10

paulcm