Skip to content

Configuration for Static Code Checkers

Remko Popma edited this page Nov 15, 2018 · 1 revision

Warnings from Static Code Checkers

When helping the Checkstyle project migrate from Commons CLI to picocli, we found that static code checkers will generate a number of "false positive" warnings for idiomatic picocli code, since fields annotated with @Option, @Parameters or @Spec appear to never be assigned a value, other than the initial value. This causes a number of warnings, most commonly these:

  • "field never written", "field can be final": the static code checker is not aware that picocli will inject values into these fields with reflection

  • "unused field", especially for boolean fields for @Option(names = "--help") or @Option(names = "--version"): these fields appear to never even be read by the application - you may be interested in using the @Command(mixinStandardHelpOptions = true) annotation to avoid the need to declare these fields altogether.

The Checkstyle project applies all of its rules to its own code, and on top of that checks its own source with a combination of Intelli/J Idea inspections, PMD checks and Spotbug checks.

Below we will show some common issues and how to configure the static code checker to suppress spurious warnings.

Checkstyle

Interestingly, the Checkstyle checks did not report any warnings.

Intelli/J Idea Inspections

The Checkstyle configuration enables many Intelli/J inspections, some of which are false positives in this case. For example, in a CLI application it is normal to write to System.out and System.err. The inspections also caught that there was a List field that was queried while nowhere in the code values were added to this list: the List<File> positional parameters populated by picocli.

Intelli/J inspections can be suppressed in comments in the source code:

/**
 * Wrapper command line program for the Checker.
 * @noinspection UseOfSystemOutOrSystemErr, unused, FieldMayBeFinal, CanBeFinal,
 *              MismatchedQueryAndUpdateOfCollection
 **
@Command(name = "checkstyle", description = "...")
public final class Main

Spotbugs

Spotbugs configuration to suppress false positive warnings:

<FindBugsFilter>
    <Match>
        <!-- false-positive: field values are injected by picocli -->
        <Or>
            <Class name="com.puppycrawl.tools.checkstyle.Main"/>
            <Class name="com.puppycrawl.tools.checkstyle.JavadocPropertiesGenerator"/>
        </Or>
        <Or>
            <Bug pattern="NP_UNWRITTEN_FIELD"/>
            <Bug pattern="UWF_UNWRITTEN_FIELD"/>
            <Bug pattern="MS_SHOULD_BE_FINAL"/>
            <Bug pattern="MS_SHOULD_BE_REFACTORED_TO_BE_FINAL"/>
            <Bug pattern="SS_SHOULD_BE_STATIC"/>
        </Or>
    </Match>
    ...

PMD

Out of the box, PMD knows it should not apply its "ImmutableField" and "UnusedPrivateField" rules to fields annotated with Lombok annotations. However, it is not (yet? PR, anyone?) picocli-aware, so you’ll need to explicitly ignore the picocli annotations:

<rule ref="category/java/design.xml/ImmutableField">
    <property name="ignoredAnnotations"
              value="picocli.CommandLine.Option
                    |picocli.CommandLine.Parameters
                    |picocli.CommandLine.Spec"/>
</rule>
<rule ref="category/java/bestpractices.xml/UnusedPrivateField">
    <property name="ignoredAnnotations"
              value="picocli.CommandLine.Option
                    |picocli.CommandLine.Parameters
                    |picocli.CommandLine.Spec"/>
</rule>