-
Notifications
You must be signed in to change notification settings - Fork 782
Introduce possibility to use @NonNull and @Nullable #3624
Comments
If we add
to the My suggestion for the nullable annotations and checks:
For a first step, have a look at: Question: |
The Eclipse nellness annotations sound like a good way to start, however if I see lines like this I am not sure if we really want And I agree that we should not start flooding the old code right away with these annotations but introduce them step by step. Does having a default If we use those annotations I clearly vote for having them turned on for everyone since they should support other developers that they can see right away in Eclipse if a value can be We had quite some discussions about the use of |
My suggestion has been to use |
@maggu2810 I agree that the use of [1] - https://dzone.com/articles/optionals-npes-and-design-practices |
I think we all agree that Optionals are no option for the existing ESH APIs, so I would suggest to open a separate issue/discussion about that as it might potentially get long and distracts from the issue we are trying to address here. So just as a recap: The wish was to use annotations on our existing APIs to express whether null values are allowed in or out, so that we do not have to mention this in the JavaDoc, but can actually rely on IDE features to highlight if a user tries to misuse our APIs. Note that my focus/priority is definitely on our APIs / public interfaces, imho we do not need to cover the "full code base" for now. If we agree on that approach, my fist question would be: WHICH ANNOTATIONS?
FindBugs seem to be the reference implementation for (the dormant) JSR-305, which uses I am not so sure about using
Currently it actually IS activated in the IDE. Afaik, it will only show you warnings/errors if there are annotations in place - so every message should be helpful and not be noise. Or am I missing something? |
This one does not work with the FindBugs one: final Map<String, @javax.annotation.Nullable Object> map = new HashMap<>(); I am using the Checker Framework for a while now:
This is only the interpretation of the Eclipse IDE. IMHO arguments are more often non-null, then allowed to be null. So I would prefer to annotate @nullable and not the other one.
This could be done, but I don't see the tooling that could be configured that way to check for potential null pointer access violations. |
My "benchmark" is actually what we have if we do not do anything - so the status quo of Java development. And this is that we have nullable as default everywhere, right? Likewise, this is what every Java developer expects, if he has never heard about such annotations.
I'll have to test this. But my assumption was that it will work nicely. If I add some constraint for any specific value (parameter or return value), this should suffice for the IDE to check that this is satisfied. I don't see why there should be the need to declare all other values in the same class at the same time (and be it through a package default). |
What is the status quo of Java development at all? The Checker Framework itself supports stubs (it also provides stubs for the whole JRE), where you can provide missing annotations. I use it at the moment, but you need to maintain it yourself. So, I can continue using my null checks regardless of the decision taken here, but for me I don't want to keep a status quo, but I want to make it as good as possible. |
That you can pass
Absolutely! This is EXACTLY what I want to achieve with this feature as mentioned above: "so that we do not have to mention this in the JavaDoc, but can actually rely on IDE features to highlight if a user tries to misuse our APIs" - "IDE highlighting" should be translated to "showing compiler errors" here, and yes, that should/could also include the headless build (that's why I referred to the Findbugs integration). |
I agree that using an annotation package like I assume that FindBugs could handle the Eclipse JDT annotations reading this file: https://github.com/findbugsproject/findbugs/blob/master/findbugs/src/java/edu/umd/cs/findbugs/ba/NullnessAnnotation.java
So, if we would like to use that status quo, we need to add @nonnull for every return type and argument type. Didn't we?
As you already written above, the tooling need to be tested. |
I checked the Eclipse IDE again... import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
public class Test {
public static class TestWithoutAnnotation {
public static Object testReturnNull() {
return null;
}
public static void testArgumentDereference(Object obj) {
if (obj.hashCode() == 1) {
throw new IllegalArgumentException();
}
}
public static void testCheckArgForNull(Object obj) {
if (obj == null) {
throw new IllegalArgumentException();
}
}
}
public static class TestWithAnnotationNullable {
public static @Nullable Object testReturnNull() {
return null;
}
public static void testArgumentDereference(@Nullable Object obj) {
if (obj.hashCode() == 1) {
throw new IllegalArgumentException();
}
}
public static void testCheckArgForNull(@Nullable Object obj) {
if (obj == null) {
throw new IllegalArgumentException();
}
}
}
public static class TestWithAnnotationNonNull {
public static @NonNull Object testReturnNull() {
return null;
}
public static void testArgumentDereference(@NonNull Object obj) {
if (obj.hashCode() == 1) {
throw new IllegalArgumentException();
}
}
public static void testCheckArgForNull(@NonNull Object obj) {
if (obj == null) {
throw new IllegalArgumentException();
}
}
}
private static void nop() {
}
public static void main() {
if (TestWithoutAnnotation.testReturnNull() == null) {
nop();
} else {
nop();
}
if (TestWithAnnotationNonNull.testReturnNull() == null) {
nop();
} else {
nop();
}
if (TestWithAnnotationNullable.testReturnNull() == null) {
nop();
} else {
nop();
}
TestWithoutAnnotation.testArgumentDereference(new Object());
TestWithAnnotationNonNull.testArgumentDereference(new Object());
TestWithAnnotationNullable.testArgumentDereference(new Object());
TestWithoutAnnotation.testArgumentDereference(null);
TestWithAnnotationNonNull.testArgumentDereference(null);
TestWithAnnotationNullable.testArgumentDereference(null);
}
} Eclipse complains about (changed nullable settings in that way that nothing is ignored):
So, IMHO non-annotated stuff is not checked at all. |
Ok, here are my tests and it is actually exactly what I expected and what I planned to achieve. package test;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
public class Test {
public @Nullable String myFrameworkMethod(@NonNull String paramA, String paramB) {
return null;
}
public void myClientCodeThatUsesTheFramework() {
String valueA = null;
String valueB = null;
String retValue = myFrameworkMethod(valueA, valueB);
System.out.print(retValue.toUpperCase());
}
} I added two annotations that provide information about our framework method: With these annotations, we have an error and a warning if we misuse the method: This is all I wanted. Any unannotated code is just still the vary same as before, so this feature is minimal invasive and really only brings new behavior at the places where we desire it. |
I just did a couple of more tests and enabled all nullanalysis checks from eclipse as An interesting finding is this one in the generated
In the last line I get an error saying "Potential null pointer access: The variable item may be null at this location". The problem is that the basic static code analysis does not catch the fact that I have taken this as one basic example showing that we cannot catch all of our With such false positives we are also tight to use only "warning" level instead of "error". That is unless we fix the code to be easier to parse by the analyzer. The only problem in my example is that the code was auto generated, though maybe we could exclude this code from our checks? I did not (yet) find that option to exclude certain directories from the check... Given that the static analysis is limited anyway, I think that the problem of missing
can be neglected for now. Since we want to be independent of an IDE while compiling the code I would also prefer to use other annotations than the one from eclipse JDT. This would leave us to the decision between the checker framework and the reference implementation of JSR305 which is FindBugs, where I think the reference implementation should be used if it is sufficient for the problem we want to solve. Citing @kaikreuzer on our goal that we want to achieve with these annotations
I think that it is enough to put them only on our public API and not flood internal code with them. Also regarding the types of annotations to use I agree with @kaikreuzer on
One question remains for me: Which null analysis check do we set to which level, i.e. where do we want to use "warning" and where "error". Because of the false positives I tend to use "warning" though the problem might be that people do not read them... Summarizing my post: I would vote for Findbugs JSR303 together with @nonnull and @nullable. |
Sounds like a plan. |
First step for integration in target plattform is started, see: #3830 |
Introduce possibility to use @nonnull and @nullable annotations in IDE and Maven build.
The text was updated successfully, but these errors were encountered: