4

So I'm getting this error from the nullness checker

> Task :compileJava
/Users/calebcushing/IdeaProjects/ppm/scaf/src/main/java/com/xenoterracide/scaf/PebbleTemplateProcessor.java:94: error: [argument.type.incompatible] incompatible argument for parameter obj of requireNonNull.
        var console = Objects.requireNonNull( System.console() );
                                                            ^                                     ^

this is complaining that System.console() could be null, which upon reading the javadoc is true. So I wrapped it in Objects.requireNonNull() now it's complaining that the argument to requireNonNull can't be null, which is obviously not true.

How do I tell NullnessChecker to ignore Objects.requireNonNull()? I'm fine with NPE's that are explicit, it's just the accidental ones I don't want. I believe checker already ships with a stub for this.

xenoterracide
  • 16,274
  • 24
  • 118
  • 243

2 Answers2

1

Realize I'm late to the game, but hopefully this will help others who land here after searching.

You can provide a stub file to Checker which overrides the default annotations.

For my own project, I created a new folder called checker alongside the src folder in one of my common projects, and dropped in a stub file java.util.Objects.astub with these contents:

package java.util;

import org.eclipse.jdt.annotation.Nullable;

public class Objects
{
   public static <T> T requireNonNull(@Nullable T obj, String message);
}

Then I added this to our Gradle build:

checkerFramework {
   extraJavacArgs = [
      "-Astubs=${project(':my-project').file('checker')}"
   ]
}

…where my-project is the Gradle identifier for the project containing the new folder.

Checker will now load all *.astub files in that checker folder, and use the annotations provided there instead of the defaults. You can learn more at Using Stub Classes in the Checker documentation.

J. Perkins
  • 4,156
  • 2
  • 34
  • 48
0

Edit: The below answers were written for the original post, which had 3 unrelated questions in it. (The poster later edited the original post.) I have no clue why this answer was downvoted, since it accurately answers all 3 questions, and gives links for additional information.

Please ask one question per post.

The first one was complaining that System.console() could be null, which upon reading the javadoc is true. So I wrapped it in Objects.requireNonNull() now it's complaining that the argument to requireNonNull can't be null, which is obviously not true.

This is answered in the introduction to the Checker Framework manual.

The goal of the Nullness Checker is to warn you if your program might throw a NullPointerException. If the argument to requireNonNull() is null, then your program throws a NullPointerException. Therefore, passing null to requireNonNull() leaves your program no more correct than passing null to any other routine that might dereference it, and the Nullness Checker warns about it.

You tried to silence the warning by writing requireNonNull(). As noted above, this has no effect: the program still throws NullPointerException. Instead, it is better to correct the underlying problem. Your program should check for null and issue a user-friendly message rather than crashing -- whether the crash is in your own code or in requireNonNull().

The second one is complaining about commons-lang3 parameter not being able to take null, but its documentation says otherwise.

This is also answered in the introduction to the Checker Framework manual.

The Nullness Checker reads annotations, not English Javadoc comments. In order for the Nullness Checker to know that toBoolean() can take a null argument, its signature of toBoolean() needs to be annotated as:

boolean toBoolean(@Nullable Boolean bool)

As explained in the manual, you can write that annotation so that the Nullness Checker will use it. You can also contribute commons-lang annotations back to the community, so that others can also benefit from them.

I added SuppressWarnings, not certain why it's still happening.

You need to write @SuppressWarnings where the warning is being issued, which is on the declaration of the Application class. You wrote @SuppressWarnings on a different line of your program.

mernst
  • 7,437
  • 30
  • 45
  • Re: commons-lang3 I know it doesn't read comments.. I Was tired when writing this. Outside of upstream patches how do I fix this? – xenoterracide Dec 10 '20 at 14:39
  • Please see the [chapter of the manual](https://checkerframework.org/manual/#annotating-libraries) that I linked to in my answer. You probably want to create a stub file, which is described there. – mernst Dec 10 '20 at 18:52
  • > the most relevant part of an important link, in case the external resource is unreachable or goes permanently offline [How To Answer (SO)](https://stackoverflow.com/help/how-to-answer) – xenoterracide Dec 10 '20 at 21:32
  • `@SuppressWarnings("initialization.fields.uninitialize")` I tried putting this on the constructor and on the class, I'm still getting this error. `/Users/calebcushing/IdeaProjects/ppm/scaf/src/main/java/com/xenoterracide/scaf/Application.java:24: error: [initialization.fields.uninitialized] the constructor does not initialize fields: arg, args, dir Application() { ^` – xenoterracide Dec 11 '20 at 02:45
  • split that one off, if you want to partially move your answer here https://stackoverflow.com/q/65245465/206466 – xenoterracide Dec 11 '20 at 03:39
  • and here https://stackoverflow.com/q/65245508/206466 – xenoterracide Dec 11 '20 at 03:46