Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 513343

Summary: JDT null analysis does not take into consideration checks made in parent scope of 'for' loops
Product: [Eclipse Project] JDT Reporter: Matthew DOnofrio <artist>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: CLOSED INVALID QA Contact:
Severity: normal    
Priority: P3 CC: stephan.herrmann
Version: 4.7   
Target Milestone: ---   
Hardware: PC   
OS: Windows 10   
Whiteboard:

Description Matthew DOnofrio CLA 2017-03-08 16:29:58 EST
This may affect other forms of loops as well but I only tried this one:

@NonNullByDefault
public class A {
   public A(@Nullable String message) {
      // Checked for null here...
      if (null == message)
         message = "null";
      
      // Asserted not null here...
      assert(null != message);
      
      for (int i = 0; i < 1; ++i) {
         // Must still assert within loop scope to silence warning
         assert(null != message);
         
         message = message.toString();
      }
      
   }
}
Comment 1 Stephan Herrmann CLA 2017-03-08 16:48:21 EST
(In reply to Matthew DOnofrio from comment #0)
> This may affect other forms of loops as well but I only tried this one:
> 
> @NonNullByDefault
> public class A {
>    public A(@Nullable String message) {
>       // Checked for null here...
>       if (null == message)
>          message = "null";
>       
>       // Asserted not null here...
>       assert(null != message);
>       
>       for (int i = 0; i < 1; ++i) {
>          // Must still assert within loop scope to silence warning
>          assert(null != message);
>          
>          message = message.toString();
>       }
>       
>    }
> }

Try adding an external annotation to String.toString() (?!?)
It's the effect of the last assignment that spoils the previous assertion.
Or am I missing anything?

BTW: it took me almost a second to figure out why you are making assertions concerning the null literal :)
Comment 2 Matthew DOnofrio CLA 2017-03-08 19:42:01 EST
Ahh, you are correct. To illustrate:

@NonNullByDefault
public class A {
   public A(@Nullable String message) {
      // Checked for null here...
      if (null == message)
         message = "null";
      
      // Asserted not null here...
      assert(null != message);
      
      someMethod(message); // NO warning here (OK!)
      
      message = message.toString();
      
      someMethod(message); // Warning here (OK!)
      
      message = message.toString(); // Potential null access warning
      message = message.toString(); // Potential null access warning
      message = message.toString(); // Potential null access warning
   }

   public void someMethod(String message) {
      System.out.println(message.toString());
   }
}
Comment 3 Matthew DOnofrio CLA 2017-03-08 20:43:38 EST
Is it possible to add an external annotation to the JDK methods? Or am I forced to suppress these kind of null warnings?

@NonNullByDefault
public class A {
   public A(String message) {
      // Null type safety (type annotations): The expression of type 'String'
      // needs unchecked conversion to conform to '@NonNull String'
      message = message.toString();
   }
}
Comment 4 Stephan Herrmann CLA 2017-03-09 06:02:18 EST
(In reply to Matthew DOnofrio from comment #3)
> Is it possible to add an external annotation to the JDK methods? Or am I
> forced to suppress these kind of null warnings?

http://help.eclipse.org/neon/topic/org.eclipse.jdt.doc.user/tasks/task-using_external_null_annotations.htm?cp=1_3_9_2
Comment 5 Matthew DOnofrio CLA 2017-03-09 12:59:53 EST
I read this, yes. I'm using the latest Oracle JDK 1.8.0_121 which does not appear to have these annotations.

The instructions provide an answer on how to configure Eclipse for external annotations but does not explain where I can get them. Are they not available at this time?
Comment 6 Stephan Herrmann CLA 2017-03-09 13:15:06 EST
(In reply to Matthew DOnofrio from comment #5)
> I read this, yes. I'm using the latest Oracle JDK 1.8.0_121 which does not
> appear to have these annotations.

It's called "external" because it's not contained :)

 
> The instructions provide an answer on how to configure Eclipse for external
> annotations but does not explain where I can get them. Are they not
> available at this time?

There is a group[1][2] discussing how to collect external annotations for others to use, but at the time being, only a few incomplete sets exist.

But then there's a simple Ctrl-1 solution to just add those annotations you need in your application.

[1] https://mattermost.eclipse.org/eclipse/channels/jdt-null-analysis
[2] http://www.lastnpe.org/