From 707d5143868dac0cbfdb144ac0f4b2e6a90a4932 Mon Sep 17 00:00:00 2001 From: Jeremy Dubreil Date: Tue, 21 Mar 2017 11:03:31 -0700 Subject: [PATCH] [infer][java] do not report `return not nullable` on lambdas Summary: It is not clear how to add annotations on lambdas. Reviewed By: sblackshear Differential Revision: D4741851 fbshipit-source-id: bf40867 --- infer/src/IR/Typ.re | 4 ++++ infer/src/IR/Typ.rei | 3 +++ infer/src/eradicate/eradicateChecks.ml | 2 ++ .../java/eradicate/ReturnNotNullable.java | 6 ++++++ infer/tests/codetoanalyze/java/eradicate/issues.exp | 12 ++++++------ 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/infer/src/IR/Typ.re b/infer/src/IR/Typ.re index 88fd98eba..abc10816b 100644 --- a/infer/src/IR/Typ.re +++ b/infer/src/IR/Typ.re @@ -605,6 +605,10 @@ let module Procname = { fun | Java j => equal_method_kind j.kind Static | _ => false; + let java_is_lambda = + fun + | Java j => String.is_prefix prefix::"lambda$" j.method_name + | _ => false; /** Prints a string of a java procname with the given level of verbosity */ let java_to_string withclass::withclass=false (j: java) verbosity => diff --git a/infer/src/IR/Typ.rei b/infer/src/IR/Typ.rei index 513260e7f..be5599c8c 100644 --- a/infer/src/IR/Typ.rei +++ b/infer/src/IR/Typ.rei @@ -378,6 +378,9 @@ let module Procname: { Note: currently only checks that the last argument has type Object[]. */ let java_is_vararg: t => bool; + /** Check if the proc name comes from a lambda expression */ + let java_is_lambda: t => bool; + /** Check if the last parameter is a hidden inner class, and remove it if present. This is used in private constructors, where a proxy constructor is generated with an extra parameter and calls the normal constructor. */ diff --git a/infer/src/eradicate/eradicateChecks.ml b/infer/src/eradicate/eradicateChecks.ml index 3a9635743..61b85314d 100644 --- a/infer/src/eradicate/eradicateChecks.ml +++ b/infer/src/eradicate/eradicateChecks.ml @@ -360,6 +360,8 @@ let check_return_annotation tenv let ret_annotated_nonnull = Annotations.ia_is_nonnull ret_ia in match ret_range with + (* Disables the warnings since it is not clear how to annotate the return value of lambdas *) + | Some _ when Typ.Procname.java_is_lambda curr_pname -> () | Some (_, final_ta, _) -> let final_nullable = TypeAnnotation.get_value AnnotatedSignature.Nullable final_ta in let final_present = TypeAnnotation.get_value AnnotatedSignature.Present final_ta in diff --git a/infer/tests/codetoanalyze/java/eradicate/ReturnNotNullable.java b/infer/tests/codetoanalyze/java/eradicate/ReturnNotNullable.java index 0401d4ad8..fe8dc9e19 100644 --- a/infer/tests/codetoanalyze/java/eradicate/ReturnNotNullable.java +++ b/infer/tests/codetoanalyze/java/eradicate/ReturnNotNullable.java @@ -15,6 +15,7 @@ import java.net.URL; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; +import java.util.stream.Stream; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -146,4 +147,9 @@ public class ReturnNotNullable { return x.f1; // can be null } } + + Stream methodUsesLambda(Stream stream) { + return stream.map(x -> null); // Intentionaly not reporting here + } + } diff --git a/infer/tests/codetoanalyze/java/eradicate/issues.exp b/infer/tests/codetoanalyze/java/eradicate/issues.exp index c6af37bbf..6c9ef550a 100644 --- a/infer/tests/codetoanalyze/java/eradicate/issues.exp +++ b/infer/tests/codetoanalyze/java/eradicate/issues.exp @@ -55,14 +55,14 @@ codetoanalyze/java/eradicate/PresentTest.java, Optional PresentTest$TestPresentA codetoanalyze/java/eradicate/PresentTest.java, Optional PresentTest$TestPresentAnnotationBasic.returnPresentBad(), 1, ERADICATE_VALUE_NOT_PRESENT, [origin,The value of `PresentTest$TestPresentAnnotationBasic.absent` in the call to `get()` is not `@Present`. (Origin: field PresentTest$TestPresentAnnotationBasic.absent at line 47)] codetoanalyze/java/eradicate/PresentTest.java, void PresentTest$TestPresentAnnotationBasic.testOptionalAbsent(), 1, ERADICATE_PARAMETER_VALUE_ABSENT, [origin,`expectPresent(...)` needs a present value in parameter 1 but argument `absent()` can be absent. (Origin: call to absent() at line 65)] codetoanalyze/java/eradicate/PresentTest.java, void PresentTest.testPresent(Optional,Optional), 4, ERADICATE_PARAMETER_VALUE_ABSENT, [`argPresent(...)` needs a present value in parameter 1 but argument `absent` can be absent. (Origin: method parameter absent)] -codetoanalyze/java/eradicate/ReturnNotNullable.java, Object ReturnNotNullable$ConditionalAssignment.test(boolean), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `test(...)` may return null but it is not annotated with `@Nullable`. (Origin: field ReturnNotNullable$ConditionalAssignment.f1 at line 146)] -codetoanalyze/java/eradicate/ReturnNotNullable.java, Object ReturnNotNullable.tryWithResourcesReturnNullable(String), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `tryWithResourcesReturnNullable(...)` may return null but it is not annotated with `@Nullable`. (Origin: call to returnNullOK() at line 91)] +codetoanalyze/java/eradicate/ReturnNotNullable.java, Object ReturnNotNullable$ConditionalAssignment.test(boolean), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `test(...)` may return null but it is not annotated with `@Nullable`. (Origin: field ReturnNotNullable$ConditionalAssignment.f1 at line 147)] +codetoanalyze/java/eradicate/ReturnNotNullable.java, Object ReturnNotNullable.tryWithResourcesReturnNullable(String), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `tryWithResourcesReturnNullable(...)` may return null but it is not annotated with `@Nullable`. (Origin: call to returnNullOK() at line 92)] codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.redundantEq(), 0, ERADICATE_RETURN_OVER_ANNOTATED, [Method `redundantEq()` is annotated with `@Nullable` but never returns null.] codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.redundantEq(), 2, ERADICATE_CONDITION_REDUNDANT_NONNULL, [The condition s is always false according to the existing annotations.] codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.redundantNeq(), 0, ERADICATE_RETURN_OVER_ANNOTATED, [Method `redundantNeq()` is annotated with `@Nullable` but never returns null.] codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.redundantNeq(), 2, ERADICATE_CONDITION_REDUNDANT_NONNULL, [The condition s is always true according to the existing annotations.] -codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.returnNull(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `returnNull()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 34)] +codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.returnNull(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `returnNull()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 35)] codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.returnNullable(String), 0, ERADICATE_RETURN_NOT_NULLABLE, [Method `returnNullable(...)` may return null but it is not annotated with `@Nullable`. (Origin: method parameter s)] -codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.return_null_in_catch(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `return_null_in_catch()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 110)] -codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.return_null_in_catch_after_throw(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `return_null_in_catch_after_throw()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 122)] -codetoanalyze/java/eradicate/ReturnNotNullable.java, URL ReturnNotNullable.getResourceNullable(Class,String), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `getResourceNullable(...)` may return null but it is not annotated with `@Nullable`. (Origin: call to getResource(...) modelled in eradicate/modelTables.ml at line 127)] +codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.return_null_in_catch(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `return_null_in_catch()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 111)] +codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.return_null_in_catch_after_throw(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `return_null_in_catch_after_throw()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 123)] +codetoanalyze/java/eradicate/ReturnNotNullable.java, URL ReturnNotNullable.getResourceNullable(Class,String), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `getResourceNullable(...)` may return null but it is not annotated with `@Nullable`. (Origin: call to getResource(...) modelled in eradicate/modelTables.ml at line 128)]