Alissa
Alissa

Reputation: 714

checkstyle disallow SuppressWarnings annotation unless there is a comment nearby

In our project, we sometimes have to have some warnings suppressed (e.g. "WeakerAccess" might be suppressed as project is also used as a lib in another project, or "expression is always false" for instanceof a checked exception that is thrown from a lib that masks the fact of throwing that exception).

On the other hand, it's not good to just add a suppression, as it might be unclear why is it there. So, I'd like to add a checkstyler rule that would only allow SuppressWarnings annotation if there is a comment nearby. That should be enough for people to start adding explanations.

But I can't find a way to do that. There is this block:

<module name="SuppressWarnings">
  <property name="format"
      value="^unchecked$|^unused$"/>
  <property name="tokens"
    value="
    CLASS_DEF,INTERFACE_DEF,ENUM_DEF,
    ANNOTATION_DEF,ANNOTATION_FIELD_DEF,
    ENUM_CONSTANT_DEF,METHOD_DEF,CTOR_DEF
    "/>
</module>

and some stuff about special comments to turn off checkstyler for a line, but it is just another suppress warnings thing that would need an explanation as well... But is there a way to say that suppression is OK if there is any comment nearby (on a line before or on the same line)?

Upvotes: 0

Views: 2045

Answers (1)

rveach
rveach

Reputation: 2201

I recommend using 2 checks in unison. Use SuppressWarningsCheck to flag the methods you want documented and display an error message that says it is a violation because it is not documented. Then use SuppressWithNearbyCommentFilter to suppress violations of the other check when documentation is added. For the filter to work, the documentation must start with a specific text so it doesn't falsely suppress SuppressWarnings that don't really have a documentation.

Example:

$ cat TestClass.java
public class TestClass {
    //SuppressWarnings: this is my reason for the suppression
    @SuppressWarnings("unchecked")
    void method() {
    }

    //this is just a comment and not a reason
    @SuppressWarnings("unused")
    void method2() {
    }

    @SuppressWarnings("unused")
    void noComment() {
    }
}

$ cat TestConfig.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
          "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
          "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">

<module name="Checker">
    <property name="charset" value="UTF-8"/>

    <module name="TreeWalker">
    <module name="SuppressWarnings">
        <property name="format" value="^(unchecked|unused)$"/>
        <message key="suppressed.warning.not.allowed"
             value="The warning ''{0}'' cannot be suppressed at this location unless a comment is given for the reason for the suppression." />
        <property name="tokens" value="CLASS_DEF,INTERFACE_DEF,ENUM_DEF,ANNOTATION_DEF,ANNOTATION_FIELD_DEF,ENUM_CONSTANT_DEF,METHOD_DEF,CTOR_DEF"/>
    </module>
    <module name="SuppressWithNearbyCommentFilter">
      <property name="commentFormat"
                value="SuppressWarnings: .{10,}"/>
      <property name="checkFormat" value="SuppressWarnings"/>
      <property name="influenceFormat" value="3"/>
    </module>
    </module>
</module>

$ java -jar checkstyle-8.18-all.jar -c TestConfig.xml TestClass.java
Starting audit...
[ERROR] TestClass.java:8:23: The warning 'unused' cannot be suppressed at this location unless a comment is given for the reason for the suppression. [SuppressWarnings]
[ERROR] TestClass.java:12:23: The warning 'unused' cannot be suppressed at this location unless a comment is given for the reason for the suppression. [SuppressWarnings]
Audit done.
Checkstyle ends with 2 errors.

You'll notice there are 2 violations but 3 SuppressWarnings. The first example shows how to correctly suppress that there is no documentation. The 2nd shows just a comment but not a documentation on the suppression, and the 3rd shows no comment at all.

<property name="format" value="^(unchecked|unused)$"/>

This specifies only documentation will be required for unchecked and unused suppressions. If you want documentation for all types but those 2, I recommend the expression "^((?!unchecked|unused).)*$".

Upvotes: 1

Related Questions