diff --git a/infer/src/eradicate/eradicate.ml b/infer/src/eradicate/eradicate.ml index 4b3887357..c678c6a1a 100644 --- a/infer/src/eradicate/eradicate.ml +++ b/infer/src/eradicate/eradicate.ml @@ -235,7 +235,9 @@ struct let rec fixpoint initializers_old = let initializers_new = get_private_called initializers_old in let initializers_new' = - List.filter ~f:(fun (pn, _) -> not (Typ.Procname.Set.mem pn !seen)) initializers_new in + List.filter + ~f:(fun (pn, _) -> not (Typ.Procname.Set.mem pn !seen)) + initializers_new in mark_seen initializers_new'; if initializers_new' <> [] then fixpoint initializers_new' in diff --git a/infer/src/eradicate/eradicateChecks.ml b/infer/src/eradicate/eradicateChecks.ml index 0b9d22752..45a58a74c 100644 --- a/infer/src/eradicate/eradicateChecks.ml +++ b/infer/src/eradicate/eradicateChecks.ml @@ -162,10 +162,12 @@ let check_condition tenv case_zero find_canonical_duplicate curr_pdesc loc curr_pdesc (** Check an "is zero" condition. *) -let check_zero tenv find_canonical_duplicate = check_condition tenv true find_canonical_duplicate +let check_zero tenv find_canonical_duplicate = + check_condition tenv true find_canonical_duplicate (** Check an "is not zero" condition. *) -let check_nonzero tenv find_canonical_duplicate = check_condition tenv false find_canonical_duplicate +let check_nonzero tenv find_canonical_duplicate = + check_condition tenv false find_canonical_duplicate (** Check an assignment to a field. *) let check_field_assignment tenv @@ -440,71 +442,72 @@ let check_call_receiver tenv end | [] -> () +type param = { + formal : Mangled.t * TypeAnnotation.t * Typ.t; + actual : Exp.t * TypeAnnotation.t; +} + (** Check the parameters of a call. *) let check_call_parameters tenv - find_canonical_duplicate curr_pdesc node typestate callee_attributes - sig_params call_params loc instr_ref typecheck_expr : unit = + find_canonical_duplicate curr_pdesc node callee_attributes + params loc instr_ref : unit = let callee_pname = callee_attributes.ProcAttributes.proc_name in - let has_this = is_virtual sig_params in - let tot_param_num = List.length sig_params - (if has_this then 1 else 0) in - let rec check sparams cparams = match sparams, cparams with - | (s1, ia1, t1) :: sparams', ((orig_e2, e2), t2) :: cparams' -> - let param_is_this = String.equal (Mangled.to_string s1) "this" in - let formal_is_nullable = Annotations.ia_is_nullable ia1 in - let formal_is_present = Annotations.ia_is_present ia1 in - let (_, ta2, _) = - typecheck_expr node instr_ref curr_pdesc typestate e2 - (t2, TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, []) loc in - let parameter_not_nullable = - not param_is_this && - PatternMatch.type_is_class t1 && - not formal_is_nullable && - TypeAnnotation.get_value AnnotatedSignature.Nullable ta2 in - let parameter_absent = - Config.eradicate_optional_present && - not param_is_this && - PatternMatch.type_is_class t1 && - formal_is_present && - not (TypeAnnotation.get_value AnnotatedSignature.Present ta2) in - if parameter_not_nullable || parameter_absent then - begin - let ann = - if parameter_not_nullable - then AnnotatedSignature.Nullable - else AnnotatedSignature.Present in - let description = - match explain_expr tenv node orig_e2 with - | Some descr -> descr - | None -> "formal parameter " ^ (Mangled.to_string s1) in - let origin_descr = TypeAnnotation.descr_origin tenv ta2 in - - let param_num = List.length sparams' + (if has_this then 0 else 1) in - let callee_loc = callee_attributes.ProcAttributes.loc in - report_error tenv - find_canonical_duplicate - (TypeErr.Parameter_annotation_inconsistent ( - ann, - description, - param_num, - callee_pname, - callee_loc, - origin_descr)) - (Some instr_ref) - loc curr_pdesc; - if Models.Inference.enabled then - Models.Inference.proc_add_parameter_nullable callee_pname param_num tot_param_num - end; - check sparams' cparams' - | _ -> () in + + let tot_param_num = List.length params in + + let check i = function + | {formal = (s1, ta1, t1); actual = (orig_e2, ta2)} -> + let param_num = i + 1 in + + let report ann = + let description = + match explain_expr tenv node orig_e2 with + | Some descr -> descr + | None -> "formal parameter " ^ (Mangled.to_string s1) in + let origin_descr = TypeAnnotation.descr_origin tenv ta2 in + + let callee_loc = callee_attributes.ProcAttributes.loc in + report_error tenv + find_canonical_duplicate + (TypeErr.Parameter_annotation_inconsistent ( + ann, + description, + param_num, + callee_pname, + callee_loc, + origin_descr)) + (Some instr_ref) + loc curr_pdesc in + + let check_ann ann = + let b1 = TypeAnnotation.get_value ann ta1 in + let b2 = TypeAnnotation.get_value ann ta2 in + match ann, b1, b2 with + | AnnotatedSignature.Nullable, false, true -> + report ann; + if Models.Inference.enabled then + Models.Inference.proc_add_parameter_nullable callee_pname param_num tot_param_num + | AnnotatedSignature.Present, true, false -> + report ann + | _ -> + () in + + if PatternMatch.type_is_class t1 + then begin + check_ann AnnotatedSignature.Nullable; + if Config.eradicate_optional_present + then check_ann AnnotatedSignature.Present; + end in let should_check_parameters = if check_library_calls then true else Models.is_modelled_nullable callee_pname || callee_attributes.ProcAttributes.is_defined || Specs.get_summary callee_pname <> None in + if should_check_parameters then (* left to right to avoid guessing the different lengths *) - check (List.rev sig_params) (List.rev call_params) + List.iteri ~f:check params (** Checks if the annotations are consistent with the inherited class or with the implemented interfaces *) diff --git a/infer/src/eradicate/typeCheck.ml b/infer/src/eradicate/typeCheck.ml index 42c2f7f38..aaccdb630 100644 --- a/infer/src/eradicate/typeCheck.ml +++ b/infer/src/eradicate/typeCheck.ml @@ -622,29 +622,33 @@ let typecheck_instr Typ.Procname.java_is_anonymous_inner_class_constructor callee_pname in let do_return loc' typestate' = + let mk_return_range () = + let (ia, ret_typ) = annotated_signature.AnnotatedSignature.ret in + let is_library = Specs.proc_is_library callee_attributes in + let origin = TypeOrigin.Proc + { + TypeOrigin.pname = callee_pname; + loc = loc'; + annotated_signature; + is_library; + } in + ( + ret_typ, + TypeAnnotation.from_item_annotation ia origin, + [loc'] + ) in + match ret_id with - | None -> typestate' + | None -> + typestate' | Some (id, _) -> - let (ia, ret_typ) = annotated_signature.AnnotatedSignature.ret in - let is_library = Specs.proc_is_library callee_attributes in - let origin = TypeOrigin.Proc - { - TypeOrigin.pname = callee_pname; - loc = loc'; - annotated_signature; - is_library; - } in TypeState.add_id id - ( - ret_typ, - TypeAnnotation.from_item_annotation ia origin, - [loc'] - ) + (mk_return_range ()) typestate' in (* Handle Preconditions.checkNotNull. *) - let do_preconditions_check_not_null parameter_num is_vararg typestate' = + let do_preconditions_check_not_null parameter_num ~is_vararg typestate' = (* clear the nullable flag of the first parameter of the procedure *) let clear_nullable_flag typestate'' pvar = (* remove the nullable flag for the given pvar *) @@ -799,6 +803,34 @@ let typecheck_instr typestate' in let typestate2 = + let prepare_params sig_params call_params = + let rec f acc sparams cparams = match sparams, cparams with + | (s1, ia1, t1) :: sparams', ((orig_e2, e2), t2) :: cparams' -> + let param_is_this = String.equal (Mangled.to_string s1) "this" in + let acc' = + if param_is_this + then acc + else begin + let ta1 = TypeAnnotation.from_item_annotation ia1 (TypeOrigin.Formal s1) in + let (_, ta2, _) = + typecheck_expr + find_canonical_duplicate calls_this checks + tenv node instr_ref curr_pdesc typestate e2 + (t2, + TypeAnnotation.const AnnotatedSignature.Nullable false TypeOrigin.ONone, + []) + loc in + + EradicateChecks.{ + formal = (s1, ta1, t1); + actual = (orig_e2, ta2)} + :: acc + end in + f acc' sparams' cparams' + | _ -> + acc in + f [] (List.rev sig_params) (List.rev call_params) in + if not is_anonymous_inner_class_constructor then begin if Config.eradicate_debug then @@ -824,13 +856,10 @@ let typecheck_instr find_canonical_duplicate curr_pdesc node - typestate1 callee_attributes - signature_params - call_params + (prepare_params signature_params call_params) loc - instr_ref - (typecheck_expr find_canonical_duplicate calls_this checks tenv); + instr_ref; let typestate2 = if checks.check_extension then let etl' = List.map ~f:(fun ((_, e), t) -> (e, t)) call_params in @@ -848,7 +877,7 @@ let typecheck_instr if Models.is_check_not_null callee_pname then do_preconditions_check_not_null (Models.get_check_not_null_parameter callee_pname) - false (* is_vararg *) + ~is_vararg:false typestate2 else if has_method callee_pname "checkNotNull" @@ -857,7 +886,7 @@ let typecheck_instr let last_parameter = List.length call_params in do_preconditions_check_not_null last_parameter - true (* is_vararg *) + ~is_vararg:true typestate2 else if Models.is_check_state callee_pname || Models.is_check_argument callee_pname then @@ -911,7 +940,8 @@ let typecheck_instr let map_dexp = function | Some (DExp.Dretcall - (DExp.Dconst (Const.Cfun (Typ.Procname.Java pname_java)), args, loc, call_flags)) -> + (DExp.Dconst + (Const.Cfun (Typ.Procname.Java pname_java)), args, loc, call_flags)) -> let pname_java' = let object_t = (Some "java.lang", "Object") in Typ.Procname.java_replace_return_type diff --git a/infer/tests/codetoanalyze/java/eradicate/FieldNotNullable.java b/infer/tests/codetoanalyze/java/eradicate/FieldNotNullable.java index fce121fb1..08b6d8f1c 100644 --- a/infer/tests/codetoanalyze/java/eradicate/FieldNotNullable.java +++ b/infer/tests/codetoanalyze/java/eradicate/FieldNotNullable.java @@ -11,9 +11,7 @@ package codetoanalyze.java.eradicate; import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Initializer; -import com.facebook.infer.annotation.Present; import com.facebook.infer.annotation.SuppressFieldNotInitialized; -import com.google.common.base.Optional; import javax.annotation.Nullable; @@ -220,65 +218,6 @@ class NestedFieldAccess { } } - class TestPresentAnnotationBasic { - void testBasicConditional(Optional o) { - if (o.isPresent()) { - o.get(); - } - } - - Optional absent = Optional.absent(); - @Present Optional present = Optional.of("abc"); - - @Present Optional returnPresent() { - if (absent.isPresent()) { - return absent; - } - else return Optional.of("abc"); - } - - void expectPresent(@Present Optional x) { - } - - void bar() { - expectPresent(present); - String s; - s = returnPresent().get(); - s = present.get(); - - Assertions.assertCondition(absent.isPresent()); - expectPresent(absent); - } - } - - class TestPresentFieldOfInnerClass { - class D { - @SuppressFieldNotInitialized Optional s; - } - - class D1 { - // Different bytecode generated when the field is private - @SuppressFieldNotInitialized private Optional s; - } - - void testD(D d) { - if (d.s.isPresent()) { - d.s.get(); - } - } - - void testD1(D1 d1) { - if (d1.s.isPresent()) { - d1.s.get(); - } - } - - void testD1Condition(D1 d1) { - Assertions.assertCondition(d1.s.isPresent()); - d1.s.get(); - } - } - class TestFunctionsIdempotent { @Nullable String s; String dontAssignNull; diff --git a/infer/tests/codetoanalyze/java/eradicate/Makefile b/infer/tests/codetoanalyze/java/eradicate/Makefile index ed4e12baa..063184845 100644 --- a/infer/tests/codetoanalyze/java/eradicate/Makefile +++ b/infer/tests/codetoanalyze/java/eradicate/Makefile @@ -8,7 +8,7 @@ TESTS_DIR = ../../.. ANALYZER = eradicate -INFER_OPTIONS = --eradicate-return-over-annotated --no-filtering --debug-exceptions +INFER_OPTIONS = --eradicate-return-over-annotated --eradicate-optional-present --no-filtering --debug-exceptions INFERPRINT_OPTIONS = --issues-tests SOURCES = $(wildcard *.java) diff --git a/infer/tests/codetoanalyze/java/eradicate/ParameterNotNullable.java b/infer/tests/codetoanalyze/java/eradicate/ParameterNotNullable.java index c8e48e858..538d863af 100644 --- a/infer/tests/codetoanalyze/java/eradicate/ParameterNotNullable.java +++ b/infer/tests/codetoanalyze/java/eradicate/ParameterNotNullable.java @@ -76,4 +76,13 @@ public class ParameterNotNullable { return cls.getResource(null); } + void threeParameters(String s1, String s2, String s3) { + } + + void testThreeParameters() { + String s = ""; + threeParameters(null, s, s); + threeParameters(s, null, s); + threeParameters(s, s, null); + } } diff --git a/infer/tests/codetoanalyze/java/eradicate/PresentTest.java b/infer/tests/codetoanalyze/java/eradicate/PresentTest.java new file mode 100644 index 000000000..86050422e --- /dev/null +++ b/infer/tests/codetoanalyze/java/eradicate/PresentTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package codetoanalyze.java.eradicate; + +import com.facebook.infer.annotation.Assertions; +import com.facebook.infer.annotation.Present; +import com.google.common.base.Optional; + + +public class PresentTest { + + void argPresent(@Present Optional present, Optional absent) { + } + + void testPresent(@Present Optional present, Optional absent) { + argPresent(present, absent); // OK + argPresent(present, present); // OK + argPresent(present, absent); // OK + argPresent(absent, absent); // Bad + } + + class TestPresentAnnotationBasic { + void testBasicConditional(Optional o) { + if (o.isPresent()) { + o.get(); + } + } + + Optional absent = Optional.absent(); + @Present Optional present = Optional.of("abc"); + + @Present Optional returnPresent() { + if (absent.isPresent()) { + return absent; + } + else return Optional.of("abc"); + } + + @Present Optional returnPresentBad() { + absent.get(); // Bad: get is unsafe + return absent; // Bad: should return present + } + + void expectPresent(@Present Optional x) { + } + + void bar() { + expectPresent(present); + String s; + s = returnPresent().get(); + s = present.get(); + + Assertions.assertCondition(absent.isPresent()); + expectPresent(absent); + } + + void testOptionalAbsent() { + expectPresent(Optional.absent()); // Bad + } + } + + class TestPresentFieldOfInnerClass { + class D { + @SuppressFieldNotInitialized Optional s; + } + + class D1 { + // Different bytecode generated when the field is private + @SuppressFieldNotInitialized private Optional s; + } + + void testD(D d) { + if (d.s.isPresent()) { + d.s.get(); + } + } + + void testD1(D1 d1) { + if (d1.s.isPresent()) { + d1.s.get(); + } + } + + void testD1Condition(D1 d1) { + Assertions.assertCondition(d1.s.isPresent()); + d1.s.get(); + } + } +} diff --git a/infer/tests/codetoanalyze/java/eradicate/issues.exp b/infer/tests/codetoanalyze/java/eradicate/issues.exp index 2cf8e5877..37f3fbe18 100644 --- a/infer/tests/codetoanalyze/java/eradicate/issues.exp +++ b/infer/tests/codetoanalyze/java/eradicate/issues.exp @@ -6,16 +6,16 @@ codetoanalyze/java/eradicate/FieldNotInitialized.java, FieldNotInitialized$OnlyR codetoanalyze/java/eradicate/FieldNotInitialized.java, FieldNotInitialized$Swap.(FieldNotInitialized), 0, ERADICATE_FIELD_NOT_INITIALIZED, [Field `FieldNotInitialized$Swap.o1` is not initialized in the constructor and is not declared `@Nullable`] codetoanalyze/java/eradicate/FieldNotInitialized.java, FieldNotInitialized$WriteItself.(FieldNotInitialized), 0, ERADICATE_FIELD_NOT_INITIALIZED, [Field `FieldNotInitialized$WriteItself.o` is not initialized in the constructor and is not declared `@Nullable`] codetoanalyze/java/eradicate/FieldNotInitialized.java, FieldNotInitialized.(), 0, ERADICATE_FIELD_NOT_INITIALIZED, [Field `FieldNotInitialized.a` is not initialized in the constructor and is not declared `@Nullable`] -codetoanalyze/java/eradicate/FieldNotNullable.java, FieldNotNullable.(Integer), -25, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `FieldNotNullable.static_s` can be null but is not declared `@Nullable`. (Origin: null constant at line 39)] -codetoanalyze/java/eradicate/FieldNotNullable.java, FieldNotNullable.(String), -2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `FieldNotNullable.static_s` can be null but is not declared `@Nullable`. (Origin: null constant at line 39)] -codetoanalyze/java/eradicate/FieldNotNullable.java, void FieldNotNullable.setYNull(), 1, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `FieldNotNullable.y` can be null but is not declared `@Nullable`. (Origin: null constant at line 57)] +codetoanalyze/java/eradicate/FieldNotNullable.java, FieldNotNullable.(Integer), -25, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `FieldNotNullable.static_s` can be null but is not declared `@Nullable`. (Origin: null constant at line 37)] +codetoanalyze/java/eradicate/FieldNotNullable.java, FieldNotNullable.(String), -2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `FieldNotNullable.static_s` can be null but is not declared `@Nullable`. (Origin: null constant at line 37)] +codetoanalyze/java/eradicate/FieldNotNullable.java, void FieldNotNullable.setYNull(), 1, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `FieldNotNullable.y` can be null but is not declared `@Nullable`. (Origin: null constant at line 55)] codetoanalyze/java/eradicate/FieldNotNullable.java, void FieldNotNullable.setYNullable(String), 1, ERADICATE_FIELD_NOT_NULLABLE, [Field `FieldNotNullable.y` can be null but is not declared `@Nullable`. (Origin: method parameter s)] -codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.FlatBAD1(NestedFieldAccess$TestFunctionsIdempotent), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 312)] -codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.FlatBAD2(NestedFieldAccess$TestFunctionsIdempotent), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 318)] -codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.NestedBAD1(), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 336)] -codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.NestedBAD2(), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 342)] -codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.NestedBAD3(), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 348)] -codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestPut.putNull(Map,String), 3, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestPut.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: null constant at line 386)] +codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.FlatBAD1(NestedFieldAccess$TestFunctionsIdempotent), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 251)] +codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.FlatBAD2(NestedFieldAccess$TestFunctionsIdempotent), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 257)] +codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.NestedBAD1(), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 275)] +codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.NestedBAD2(), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 281)] +codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestFunctionsIdempotent.NestedBAD3(), 2, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestFunctionsIdempotent.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: call to getS(...) at line 287)] +codetoanalyze/java/eradicate/FieldNotNullable.java, void NestedFieldAccess$TestPut.putNull(Map,String), 3, ERADICATE_FIELD_NOT_NULLABLE, [origin,Field `NestedFieldAccess$TestPut.dontAssignNull` can be null but is not declared `@Nullable`. (Origin: null constant at line 325)] codetoanalyze/java/eradicate/InconsistentSubclassAnnotation.java, String InconsistentSubclassAnnotation.implementInAnotherFile(String), 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, [First parameter `s` of method `InconsistentSubclassAnnotation.implementInAnotherFile(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `InconsistentSubclassAnnotationInterface.implementInAnotherFile(...)`.] codetoanalyze/java/eradicate/InconsistentSubclassAnnotation.java, SubclassExample$T SubclassExample$B.foo(), 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, [Method `SubclassExample$B.foo()` is annotated with `@Nullable` but overrides unannotated method `SubclassExample$A.foo()`.] codetoanalyze/java/eradicate/InconsistentSubclassAnnotation.java, SubclassExample$T SubclassExample$C.baz(), 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, [Method `SubclassExample$C.baz()` is annotated with `@Nullable` but overrides unannotated method `SubclassExample$I.baz()`.] @@ -43,6 +43,13 @@ codetoanalyze/java/eradicate/ParameterNotNullable.java, String ParameterNotNulla codetoanalyze/java/eradicate/ParameterNotNullable.java, URL ParameterNotNullable.testClassGetResourceArgument(Class), 1, ERADICATE_PARAMETER_NOT_NULLABLE, [origin,`getResource(...)` needs a non-null value in parameter 1 but argument `null` can be null. (Origin: null constant at line 76)] codetoanalyze/java/eradicate/ParameterNotNullable.java, void ParameterNotNullable.callNull(), 2, ERADICATE_PARAMETER_NOT_NULLABLE, [origin,`test(...)` needs a non-null value in parameter 1 but argument `s` can be null. (Origin: null constant at line 38)] codetoanalyze/java/eradicate/ParameterNotNullable.java, void ParameterNotNullable.callNullable(String), 1, ERADICATE_PARAMETER_NOT_NULLABLE, [`test(...)` needs a non-null value in parameter 1 but argument `s` can be null. (Origin: method parameter s)] +codetoanalyze/java/eradicate/ParameterNotNullable.java, void ParameterNotNullable.testThreeParameters(), 2, ERADICATE_PARAMETER_NOT_NULLABLE, [origin,`threeParameters(...)` needs a non-null value in parameter 1 but argument `null` can be null. (Origin: null constant at line 84)] +codetoanalyze/java/eradicate/ParameterNotNullable.java, void ParameterNotNullable.testThreeParameters(), 3, ERADICATE_PARAMETER_NOT_NULLABLE, [origin,`threeParameters(...)` needs a non-null value in parameter 2 but argument `null` can be null. (Origin: null constant at line 85)] +codetoanalyze/java/eradicate/ParameterNotNullable.java, void ParameterNotNullable.testThreeParameters(), 4, ERADICATE_PARAMETER_NOT_NULLABLE, [origin,`threeParameters(...)` needs a non-null value in parameter 3 but argument `null` can be null. (Origin: null constant at line 86)] +codetoanalyze/java/eradicate/PresentTest.java, Optional PresentTest$TestPresentAnnotationBasic.returnPresentBad(), 0, ERADICATE_RETURN_VALUE_NOT_PRESENT, [origin,Method `returnPresentBad()` may return an absent value but it is annotated with `@Present`. (Origin: field PresentTest$TestPresentAnnotationBasic.absent at line 47)] +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, String ReturnNotNullable.redundantEq(), 0, ERADICATE_RETURN_OVER_ANNOTATED, [Method `redundantEq()` is annotated with `@Nullable` but never returns null.]