From fe1fd575935d9db380f7cf6f0317e7af8e7d5dcf Mon Sep 17 00:00:00 2001 From: Artem Pianykh Date: Wed, 22 Jan 2020 08:04:46 -0800 Subject: [PATCH] [nullsafe] Add a test for subclass annotation with multiple interfaces Summary: We were lacking this kind of test where one interface refines the nullability of the other. Reviewed By: ngorogiannis Differential Revision: D19514245 fbshipit-source-id: fa3e781f3 --- .../InconsistentSubclassAnnotation.java | 23 +++++++++++++++++++ .../java/nullsafe-default/issues.exp | 1 + 2 files changed, 24 insertions(+) diff --git a/infer/tests/codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java b/infer/tests/codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java index cb60681fb..bc27596b1 100644 --- a/infer/tests/codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java +++ b/infer/tests/codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java @@ -179,3 +179,26 @@ class JavaLangEquals { return false; } } + +// Check multiple interfaces in the inheritance chain +interface NullableGetter { + @Nullable + String get(); +} + +interface NonNullableInterfaceGetterOK extends NullableGetter { + String get(); +} + +class NonNullableConcreteGetterOK implements NonNullableInterfaceGetterOK { + public String get() { + return "OK"; + } +} + +class NullableConcreteGetterBAD implements NonNullableInterfaceGetterOK { + @Nullable + public String get() { + return null; + } +} diff --git a/infer/tests/codetoanalyze/java/nullsafe-default/issues.exp b/infer/tests/codetoanalyze/java/nullsafe-default/issues.exp index 0f294671a..08ab5b373 100644 --- a/infer/tests/codetoanalyze/java/nullsafe-default/issues.exp +++ b/infer/tests/codetoanalyze/java/nullsafe-default/issues.exp @@ -100,6 +100,7 @@ codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoa codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.ArgNullToValForInterfaceInAnotherFileBAD.implementInAnotherFile(java.lang.String):java.lang.String, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `s` of method `ArgNullToValForInterfaceInAnotherFileBAD.implementInAnotherFile(...)` is missing `@Nullable` declaration when overriding `InconsistentSubclassAnnotationInterface.implementInAnotherFile(...)`. The parent method declared it can handle `null` for this param, so the child should also declare that.] codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.ExtendsExternalLibrary.externalMethod2(java.lang.Object):void, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `object` of method `ExtendsExternalLibrary.externalMethod2(...)` is missing `@Nullable` declaration when overriding `SomeExternalClass.externalMethod2(...)`. The parent method declared it can handle `null` for this param, so the child should also declare that.] codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.JavaLangEquals.equals(java.lang.Object):boolean, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [Parameter `x` is missing `@Nullable` declaration: according to the Java Specification, for any object `x` call `x.equals(null)` should properly return false.] +codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.NullableConcreteGetterBAD.get():java.lang.String, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Child method `NullableConcreteGetterBAD.get()` is not substitution-compatible with its parent: the return type is declared as nullable, but parent method `NonNullableInterfaceGetterOK.get()` is missing `@Nullable` declaration. Either mark the parent as `@Nullable` or ensure the child does not return `null`.] codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.OverloadExistingIncorrectBAD.overload(java.lang.String,java.lang.String):java.lang.String, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Child method `OverloadExistingIncorrectBAD.overload(...)` is not substitution-compatible with its parent: the return type is declared as nullable, but parent method `Overloads.overload(...)` is missing `@Nullable` declaration. Either mark the parent as `@Nullable` or ensure the child does not return `null`.] codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.ReturnValToNullBAD.valBoth(java.lang.String):java.lang.String, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Child method `ReturnValToNullBAD.valBoth(...)` is not substitution-compatible with its parent: the return type is declared as nullable, but parent method `VariousMethods.valBoth(...)` is missing `@Nullable` declaration. Either mark the parent as `@Nullable` or ensure the child does not return `null`.] codetoanalyze/java/nullsafe-default/InheritanceForStrictMode.java, codetoanalyze.java.nullsafe_default.InheritanceForStrictMode$NonStrictExtendingStrict.badToAddNullableInChildren():java.lang.String, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Child method `InheritanceForStrictMode$NonStrictExtendingStrict.badToAddNullableInChildren()` is not substitution-compatible with its parent: the return type is declared as nullable, but parent method `InheritanceForStrictMode$StrictBase.badToAddNullableInChildren()` is missing `@Nullable` declaration. Either mark the parent as `@Nullable` or ensure the child does not return `null`.]