From 045649abaf09a8708ebba7dc1df5c47a2bc8dcdb Mon Sep 17 00:00:00 2001 From: Mitya Lyubarskiy Date: Mon, 4 May 2020 09:03:30 -0700 Subject: [PATCH] [nullsafe] Aggregate meta-issues for top-level classes Summary: This diff changes way we treat classes w.r.t. to Nullsafe modes when issuing meta-issues. Previously, we considered nested class independently of the outer one. This was leading to a tricky case: when the class is clean but nested class needs fixing, meta-info told that class can be Nullsafe. This is counter-intutive and lead to problems when users tried to follow wrong nullsafe suggestions for this case. After this diff we: 1. Start calculating meta-issues only on the outermost level. This will simplify reasoning about nullsafe stats. 2. Aggregate all nested issues counters to corresponding outer-level class. Among others, CLASS_CAN_BE_NULLSAFE Advice will finally become actionable in all known cases. Reviewed By: artempyanykh Differential Revision: D21353607 fbshipit-source-id: a17c6958a --- infer/src/nullsafe/AggregatedSummaries.ml | 111 ++++++--- infer/src/nullsafe/AggregatedSummaries.mli | 24 +- infer/src/nullsafe/ClassLevelAnalysis.ml | 126 ++++++----- infer/src/nullsafe/ClassLevelAnalysis.mli | 18 +- infer/src/nullsafe/FileLevelAnalysis.ml | 40 ++-- .../unit/nullsafe/AggregatedSummariesTest.ml | 212 ++++++++++++++++++ infer/src/unit/nullsafe/AllNullsafeTests.ml | 3 +- .../codetoanalyze/java/nullsafe/issues.exp | 108 ++------- 8 files changed, 436 insertions(+), 206 deletions(-) create mode 100644 infer/src/unit/nullsafe/AggregatedSummariesTest.ml diff --git a/infer/src/nullsafe/AggregatedSummaries.ml b/infer/src/nullsafe/AggregatedSummaries.ml index 2bd08deaa..c4c5e4d66 100644 --- a/infer/src/nullsafe/AggregatedSummaries.ml +++ b/infer/src/nullsafe/AggregatedSummaries.ml @@ -9,11 +9,30 @@ open! IStd module ClassInfo = struct type t = - {summaries: NullsafeSummary.t list; nested_anonymous_classes: anonymous_class_to_summaries} + { class_name: JavaClassName.t + ; summaries: NullsafeSummary.t list + ; mutable nested_classes_info: t list + ; nested_anonymous_classes: anonymous_class_to_summaries } and anonymous_class_to_summaries = NullsafeSummary.t list JavaClassName.Map.t - let make_empty () = {summaries= []; nested_anonymous_classes= JavaClassName.Map.empty} + let get_class_name {class_name} = class_name + + let get_summaries {summaries} = summaries + + let get_nested_anonymous_summaries {nested_anonymous_classes} = nested_anonymous_classes + + let get_nested_classes_info {nested_classes_info} = nested_classes_info + + (** Add a link between this class and a nested class info *) + let add_nested_class_info ~nested t = t.nested_classes_info <- nested :: t.nested_classes_info + + let make_empty class_name = + { class_name + ; summaries= [] + ; nested_classes_info= [] + ; nested_anonymous_classes= JavaClassName.Map.empty } + (** Add top level (not anonymous) summary belonging to this class *) let add_class_summary summary t = {t with summaries= summary :: t.summaries} @@ -28,48 +47,86 @@ module ClassInfo = struct {t with nested_anonymous_classes= updated_anonymous_classes} - let get_anonymous_summaries {nested_anonymous_classes} = - JavaClassName.Map.fold - (fun class_name summaries acc -> (class_name, summaries) :: acc) - nested_anonymous_classes [] - - - let get_all_summaries t = + let rec get_recursive_summaries t = + let this_summaries = List.map t.summaries ~f:(fun summary -> (t.class_name, summary)) in let anonymous_summaries = - get_anonymous_summaries t - |> List.map ~f:(fun (_, summaries) -> summaries) - |> List.fold ~init:[] ~f:( @ ) + JavaClassName.Map.bindings t.nested_anonymous_classes + |> List.map ~f:(fun (class_name, summaries) -> + List.map summaries ~f:(fun summary -> (class_name, summary)) ) + |> List.concat in - t.summaries @ anonymous_summaries + let nested_summaries = + List.map t.nested_classes_info ~f:get_recursive_summaries |> List.concat + in + this_summaries @ nested_summaries @ anonymous_summaries end -type t = ClassInfo.t JavaClassName.Map.t - -let make_empty () = JavaClassName.Map.empty - (* If key (class_name) was not in the map yet, add it, otherwise modify the existing value. [update] is a function that modifies value. *) let update_in_map class_name ~update t = JavaClassName.Map.update class_name (fun class_info -> - let info_to_update = Option.value class_info ~default:(ClassInfo.make_empty ()) in + let info_to_update = Option.value class_info ~default:(ClassInfo.make_empty class_name) in Some (update info_to_update) ) t -let register_summary java_class_name summary t = - match JavaClassName.get_user_defined_class_if_anonymous_inner java_class_name with +(* Add (empty) class info for all outer classes for this class recursively, + if it did not exist yet *) +let rec register_ancestors user_defined_class map = + match JavaClassName.get_outer_class_name user_defined_class with + | Some outer_class -> + (* add to the map if not added and to the same for parent *) + update_in_map outer_class ~update:ident map |> register_ancestors outer_class + | None -> + map + + +(* Register this class and all it ancestor classes, if not registered yet, + and update list of summaries for this class. +*) +let register_classes_and_add_summary class_name summary map = + match JavaClassName.get_user_defined_class_if_anonymous_inner class_name with | Some outer_class_name -> (* That was a nested anonymous class. We don't register it at top level, registed outer class instead. *) update_in_map outer_class_name - ~update:(ClassInfo.add_anonymous_summary java_class_name summary) - t + ~update:(ClassInfo.add_anonymous_summary class_name summary) + map + |> register_ancestors outer_class_name | None -> (* This is not an anonymous class, register it as is *) - update_in_map java_class_name ~update:(ClassInfo.add_class_summary summary) t - - -let group_by_user_class t = - JavaClassName.Map.fold (fun class_name class_info acc -> (class_name, class_info) :: acc) t [] + update_in_map class_name ~update:(ClassInfo.add_class_summary summary) map + |> register_ancestors class_name + + +(* the result is the map from all class names (including all ancestors) to corresponding info with summaries, + without links to nested classes *) +let create_initial_map all_summaries = + List.fold all_summaries ~init:JavaClassName.Map.empty ~f:(fun map (class_name, summary) -> + register_classes_and_add_summary class_name summary map ) + + +(* given a map containing all nested and parent class names (excluding anonymous classes), + update [nested_classes_info] links for all outer classes +*) +let set_links map = + JavaClassName.Map.iter + (fun class_name class_info -> + Option.iter (JavaClassName.get_outer_class_name class_name) ~f:(fun outer_class_name -> + let outer_info = JavaClassName.Map.find outer_class_name map in + ClassInfo.add_nested_class_info ~nested:class_info outer_info ) ) + map + + +let aggregate all_summaries = + let class_name_to_info = create_initial_map all_summaries in + set_links class_name_to_info ; + (* Return only list of top level classes that are not nested *) + JavaClassName.Map.bindings class_name_to_info + |> List.filter_map ~f:(fun (class_name, class_info) -> + if Option.is_none (JavaClassName.get_outer_class_name class_name) then + (* This class is the outermost, leave it *) + Some class_info + else None ) diff --git a/infer/src/nullsafe/AggregatedSummaries.mli b/infer/src/nullsafe/AggregatedSummaries.mli index 531dd03de..9bd4048d3 100644 --- a/infer/src/nullsafe/AggregatedSummaries.mli +++ b/infer/src/nullsafe/AggregatedSummaries.mli @@ -14,17 +14,21 @@ open! IStd module ClassInfo : sig type t - val get_all_summaries : t -> NullsafeSummary.t list - (** List of all summaries, user-level and anonymous, combined together *) -end + val get_class_name : t -> JavaClassName.t + + val get_summaries : t -> NullsafeSummary.t list -type t + val get_nested_classes_info : t -> t list -val make_empty : unit -> t + val get_nested_anonymous_summaries : t -> NullsafeSummary.t list JavaClassName.Map.t + (** List of all anonymous class summaries belonging to this class, together with name of anonymous + class. This is a flattenned list, so we don't care if one anonymous class is nested inside the + other. *) -val register_summary : JavaClassName.t -> NullsafeSummary.t -> t -> t -(** Add information about summary to the class map. Depending on if this an anonymous or - user-defined class, adds it to corresponding lists. *) + val get_recursive_summaries : t -> (JavaClassName.t * NullsafeSummary.t) list + (** A flattened list of all summaries, user-level, nested, and anonymous, combined together *) +end -val group_by_user_class : t -> (JavaClassName.t * ClassInfo.t) list -(** List of pairs ClassInfo.t list +(** Given a list of all summaries and their classes, group them by names and aggregate in a list of + top-level classes. *) diff --git a/infer/src/nullsafe/ClassLevelAnalysis.ml b/infer/src/nullsafe/ClassLevelAnalysis.ml index 8540314ed..5fd13eea5 100644 --- a/infer/src/nullsafe/ClassLevelAnalysis.ml +++ b/infer/src/nullsafe/ClassLevelAnalysis.ml @@ -34,8 +34,14 @@ let is_reportable_typing_rules_violation ~nullsafe_mode issue = is_typing_rules_violation issue && TypeErr.is_reportable ~nullsafe_mode issue -let get_reportable_typing_rules_violations ~nullsafe_mode issues = - List.filter issues ~f:(is_reportable_typing_rules_violation ~nullsafe_mode) +let get_reportable_typing_rules_violations modes_with_issues = + List.filter modes_with_issues ~f:(fun (nullsafe_mode, issue) -> + is_reportable_typing_rules_violation ~nullsafe_mode issue ) + |> List.map ~f:(fun (_, a) -> a) + + +let get_reportable_typing_rules_violations_for_mode ~nullsafe_mode issues = + List.map issues ~f:(fun issue -> (nullsafe_mode, issue)) |> get_reportable_typing_rules_violations type meta_issue = @@ -60,7 +66,7 @@ let mode_to_json mode = let is_clean_in_mode nullsafe_mode all_issues = - get_reportable_typing_rules_violations ~nullsafe_mode all_issues |> List.is_empty + get_reportable_typing_rules_violations_for_mode ~nullsafe_mode all_issues |> List.is_empty (* Return the maximum mode where we still have zero issues, or None if no such mode exists. @@ -79,23 +85,32 @@ let calc_mode_to_promote_to curr_mode all_issues = else None -(* analyze all issues for the current class and classify them into one meta-issue. +(* analyze all issues for the current class (including all nested and anonymous classes recursively) + and classify them into one meta-issue. *) -let make_meta_issue all_issues current_mode class_name = - let issue_count_in_curr_mode = - get_reportable_typing_rules_violations ~nullsafe_mode:current_mode all_issues |> List.length +let make_meta_issue modes_and_issues top_level_class_mode top_level_class_name = + let currently_reportable_issues = get_reportable_typing_rules_violations modes_and_issues in + List.iter currently_reportable_issues ~f:(fun issue -> + Logging.debug Analysis Medium "Issue: %a@\n" TypeErr.pp_err_instance issue ) ; + let currently_reportable_issue_count = List.length currently_reportable_issues in + let all_issues = List.map modes_and_issues ~f:(fun (_, a) -> a) in + let mode_to_promote_to = + if currently_reportable_issue_count > 0 then + (* This is not an optimization - consider a class with a nested class that is in the stricter mode than top level mode, + and has issues in this mode, but not in the top level mode. + This class is already broken now, so mode to promote to should be None. + But [calc_mode_to_promote_to] can return some mode for this case, which would be wrong. *) + None + else calc_mode_to_promote_to top_level_class_mode all_issues in - List.iter (get_reportable_typing_rules_violations ~nullsafe_mode:current_mode all_issues) - ~f:(fun issue -> Logging.debug Analysis Medium "Issue: %a@\n" TypeErr.pp_err_instance issue) ; - let mode_to_promote_to = calc_mode_to_promote_to current_mode all_issues in let meta_issue_info = Jsonbug_t. - { num_issues= issue_count_in_curr_mode - ; curr_nullsafe_mode= mode_to_json current_mode + { num_issues= currently_reportable_issue_count + ; curr_nullsafe_mode= mode_to_json top_level_class_mode ; can_be_promoted_to= Option.map mode_to_promote_to ~f:mode_to_json } in let issue_type, description, severity = - if NullsafeMode.equal current_mode Default then + if NullsafeMode.equal top_level_class_mode Default then match mode_to_promote_to with | Some mode_to_promote_to -> (* This class is not @Nullsafe yet, but can become such! *) @@ -118,45 +133,38 @@ let make_meta_issue all_issues current_mode class_name = | NullsafeMode.Default | NullsafeMode.Local (NullsafeMode.Trust.Only _) -> Logging.die InternalError "Unexpected promotion mode" in - let severity, message = - if Option.is_some (JavaClassName.get_outer_class_name class_name) then - (* This is a nested class. We don't recommend explicitly marking it as @Nullsafe to the users: - recommended granularity is outer level class. However, we still report meta-issue for statistics/metric reasons. - *) - ( Exceptions.Info - , Format.sprintf "`%s` is free of nullability issues." - (JavaClassName.classname class_name) ) - else - ( Exceptions.Advice - , Format.sprintf - "Congrats! `%s` is free of nullability issues. Mark it %s to prevent regressions." - (JavaClassName.classname class_name) - promo_recommendation ) + let message = + Format.sprintf + "Congrats! `%s` is free of nullability issues. Mark it %s to prevent regressions." + (JavaClassName.classname top_level_class_name) + promo_recommendation in - (IssueType.eradicate_meta_class_can_be_nullsafe, message, severity) + (IssueType.eradicate_meta_class_can_be_nullsafe, message, Exceptions.Advice) | None -> (* This class can not be made @Nullsafe without extra work *) let issue_count_to_make_nullsafe = - get_reportable_typing_rules_violations + get_reportable_typing_rules_violations_for_mode ~nullsafe_mode:(NullsafeMode.Local NullsafeMode.Trust.All) all_issues |> List.length in ( IssueType.eradicate_meta_class_needs_improvement , Format.asprintf "`%s` needs %d issues to be fixed in order to be marked @Nullsafe." - (JavaClassName.classname class_name) + (JavaClassName.classname top_level_class_name) issue_count_to_make_nullsafe , Exceptions.Info ) - else if issue_count_in_curr_mode > 0 then - (* This class is already nullsafe *) + else if currently_reportable_issue_count > 0 then + (* This class is @Nullsafe, but broken. This should not happen often if there is enforcement for + @Nullsafe mode error in the target codebase. *) ( IssueType.eradicate_meta_class_needs_improvement , Format.asprintf "@Nullsafe classes should have exactly zero nullability issues. `%s` has %d." - (JavaClassName.classname class_name) - issue_count_in_curr_mode + (JavaClassName.classname top_level_class_name) + currently_reportable_issue_count , Exceptions.Info ) else ( IssueType.eradicate_meta_class_is_nullsafe - , Format.asprintf "Class %a is free of nullability issues." JavaClassName.pp class_name + , Format.asprintf "Class %a is free of nullability issues." JavaClassName.pp + top_level_class_name , Exceptions.Info ) in {issue_type; description; severity; meta_issue_info} @@ -172,19 +180,30 @@ let get_class_loc source_file Struct.{java_class_info} = (* Meta issues are those related to null-safety of the class in general, not concrete nullability violations *) -let report_meta_issues tenv source_file class_name class_struct class_info issue_log = - (* For purposes of aggregation, we consider all nested anonymous summaries as belonging to this class *) - let current_mode = NullsafeMode.of_class tenv class_name in - let summaries = AggregatedSummaries.ClassInfo.get_all_summaries class_info in - let class_loc = get_class_loc source_file class_struct in - let all_issues = List.concat_map summaries ~f:(fun {NullsafeSummary.issues} -> issues) in - let {issue_type; description; severity; meta_issue_info} = - make_meta_issue all_issues current_mode class_name - in - let package = JavaClassName.package class_name in - let class_name = JavaClassName.classname class_name in - let nullsafe_extra = Jsonbug_t.{class_name; package; meta_issue_info= Some meta_issue_info} in - log_issue ~issue_log ~loc:class_loc ~severity ~nullsafe_extra issue_type description +let report_meta_issue_for_top_level_class tenv source_file class_name class_struct class_info + issue_log = + if Option.is_some (JavaClassName.get_outer_class_name class_name) then + (* We record meta-issues only for top-level classes *) issue_log + else + let current_mode = NullsafeMode.of_class tenv class_name in + (* For purposes of aggregation, we consider all nested summaries as belonging to this class *) + let class_names_and_summaries = + AggregatedSummaries.ClassInfo.get_recursive_summaries class_info + in + let class_loc = get_class_loc source_file class_struct in + let all_issues = + List.map class_names_and_summaries ~f:(fun (class_name, NullsafeSummary.{issues}) -> + let mode_for_class_name = NullsafeMode.of_class tenv class_name in + List.map issues ~f:(fun issue -> (mode_for_class_name, issue)) ) + |> List.fold ~init:[] ~f:( @ ) + in + let {issue_type; description; severity; meta_issue_info} = + make_meta_issue all_issues current_mode class_name + in + let package = JavaClassName.package class_name in + let class_name = JavaClassName.classname class_name in + let nullsafe_extra = Jsonbug_t.{class_name; package; meta_issue_info= Some meta_issue_info} in + log_issue ~issue_log ~loc:class_loc ~severity ~nullsafe_extra issue_type description (* Optimization - if issues are disabled, don't bother analyzing them *) @@ -194,9 +213,11 @@ let should_analyze_meta_issues () = || IssueType.eradicate_meta_class_is_nullsafe.enabled -let analyze_meta_issues tenv source_file class_name class_struct class_info issue_log = +let analyze_meta_issue_for_top_level_class tenv source_file class_name class_struct class_info + issue_log = if should_analyze_meta_issues () then - report_meta_issues tenv source_file class_name class_struct class_info issue_log + report_meta_issue_for_top_level_class tenv source_file class_name class_struct class_info + issue_log else issue_log @@ -243,11 +264,12 @@ let analyze_nullsafe_annotations tenv source_file class_name class_struct issue_ let analyze_class_impl tenv source_file class_name class_struct class_info issue_log = issue_log - |> analyze_meta_issues tenv source_file class_name class_struct class_info + |> analyze_meta_issue_for_top_level_class tenv source_file class_name class_struct class_info |> analyze_nullsafe_annotations tenv source_file class_name class_struct -let analyze_class tenv source_file class_name class_info issue_log = +let analyze_class tenv source_file class_info issue_log = + let class_name = AggregatedSummaries.ClassInfo.get_class_name class_info in match Tenv.lookup tenv (Typ.JavaClass class_name) with | Some class_struct -> analyze_class_impl tenv source_file class_name class_struct class_info issue_log diff --git a/infer/src/nullsafe/ClassLevelAnalysis.mli b/infer/src/nullsafe/ClassLevelAnalysis.mli index b73dd202c..f6d9543ae 100644 --- a/infer/src/nullsafe/ClassLevelAnalysis.mli +++ b/infer/src/nullsafe/ClassLevelAnalysis.mli @@ -10,11 +10,13 @@ open! IStd (** This stage is called for each Java class after all corresponding proc summaries are calculated. *) val analyze_class : - Tenv.t - -> SourceFile.t - -> JavaClassName.t - -> AggregatedSummaries.ClassInfo.t - -> IssueLog.t - -> IssueLog.t -(** Given all summaries for given class, analyze them in combination, and update issue log, if - necessary *) + Tenv.t -> SourceFile.t -> AggregatedSummaries.ClassInfo.t -> IssueLog.t -> IssueLog.t +(** Given aggregated summary for a class, analyze it, and return updated issue log, if necessary. + This function will be called for each non-trivial{^ 1} anonymous class in the file, including + nested classes. Order of calls is not specified. + + {^ 1}The class is non-trivial if it has at least one procedure, or contains at least one nested + non-trivial class. + + (Note that [IssueLog.t] is a mutable type so it can be actually mutated by this function: + returning [IssueLog.t] is done for convenient chaining.) *) diff --git a/infer/src/nullsafe/FileLevelAnalysis.ml b/infer/src/nullsafe/FileLevelAnalysis.ml index d8527dc56..cd014dfb8 100644 --- a/infer/src/nullsafe/FileLevelAnalysis.ml +++ b/infer/src/nullsafe/FileLevelAnalysis.ml @@ -14,32 +14,40 @@ let get_java_class_name = function None -(* aggregate all of the procedures in the file env by their declaring - class. this lets us analyze each class individually *) -let aggregate_by_class {InterproceduralAnalysis.procedures; analyze_file_dependency; _} = +(* Fetch the class and summaries for each procedure *) +let get_summaries + ({procedures; analyze_file_dependency} : NullsafeSummary.t InterproceduralAnalysis.file_t) = let open IOption.Let_syntax in - List.fold procedures ~init:(AggregatedSummaries.make_empty ()) ~f:(fun map_to_update procname -> - (let* class_name = Procname.get_class_type_name procname in - let* java_class_name = get_java_class_name class_name in - let* _proc_desc, summary = analyze_file_dependency procname in - return (AggregatedSummaries.register_summary java_class_name summary map_to_update)) - |> Option.value ~default:map_to_update ) + List.filter_map procedures ~f:(fun procname -> + let* class_name = Procname.get_class_type_name procname in + let* java_class_name = get_java_class_name class_name in + let* _proc_desc, summary = analyze_file_dependency procname in + return (java_class_name, summary) ) -(* Given list of proc summaries belonging to a class, aggregate it and add issues to the log, if needed *) -let analyze_class tenv source_file issue_log (class_name, class_info) = +(* Analyze the class and all its nested children recursively *) +let rec analyze_class_and_nested tenv source_file issue_log class_info = + (* Analyze the class itself *) + let updated_log = ClassLevelAnalysis.analyze_class tenv source_file class_info issue_log in + (* Analyze its nested children *) + AggregatedSummaries.ClassInfo.get_nested_classes_info class_info + |> List.fold ~init:updated_log ~f:(analyze_class_and_nested tenv source_file) + + +(* Given aggregated information about the top-level class, analyze it and its nested children *) +let analyze_top_level_class tenv source_file issue_log top_level_class_info = let is_from_third_party = ThirdPartyAnnotationInfo.is_third_party_class_name (ThirdPartyAnnotationGlobalRepo.get_repo ()) - class_name + (AggregatedSummaries.ClassInfo.get_class_name top_level_class_info) in if is_from_third_party then (* Don't analyze third party classes *) issue_log - else ClassLevelAnalysis.analyze_class tenv source_file class_name class_info issue_log + else analyze_class_and_nested tenv source_file issue_log top_level_class_info let analyze_file ({InterproceduralAnalysis.file_exe_env; source_file} as analysis_data) = - let class_map = aggregate_by_class analysis_data in + let all_summaries = get_summaries analysis_data in let tenv = Exe_env.load_java_global_tenv file_exe_env in - let user_class_info = AggregatedSummaries.group_by_user_class class_map in - List.fold user_class_info ~init:IssueLog.empty ~f:(analyze_class tenv source_file) + let top_level_classes = AggregatedSummaries.aggregate all_summaries in + List.fold top_level_classes ~init:IssueLog.empty ~f:(analyze_top_level_class tenv source_file) diff --git a/infer/src/unit/nullsafe/AggregatedSummariesTest.ml b/infer/src/unit/nullsafe/AggregatedSummariesTest.ml new file mode 100644 index 000000000..543ae0b7a --- /dev/null +++ b/infer/src/unit/nullsafe/AggregatedSummariesTest.ml @@ -0,0 +1,212 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +open! IStd +open OUnit2 +open AggregatedSummaries +module F = Format + +let test_package = Some "test.package" + +let mock_summary id = + (* For simplicity, mock summaries will be represented as a list with the single issue where id is encoded in description. *) + let mock_issue = + TypeErr.Condition_redundant + { is_always_true= true + ; condition_descr= Some (Int.to_string id) + ; nonnull_origin= TypeOrigin.New } + in + NullsafeSummary.{issues= [mock_issue]} + + +let get_mock_summary_id NullsafeSummary.{issues} = + match issues with + | [TypeErr.Condition_redundant {condition_descr= Some id}] -> + Int.of_string id + | _ -> + assert_failure "Expected mock summary, got something else" + + +type expected_class_info = + { name: string + ; nested: expected_class_info list + ; anm: (string * int list) list + (* List of nested anonymous names together with list of their expected summary ids *) + ; summary_ids: int list (** sorted for convenience *) } + +let assert_summaries_equal actual_summaries expected_ids class_name case_name = + let actual_summaries_ids = + actual_summaries |> List.map ~f:get_mock_summary_id |> List.sort ~compare:Int.compare + in + assert_equal expected_ids actual_summaries_ids + ~msg:(F.sprintf "%s: summary ids for %s did not match" case_name class_name) + + +let assert_anonymous_equal actual expected_name_to_ids case_name = + List.iter expected_name_to_ids ~f:(fun (anonymous_name, expected_summary_ids) -> + let actual_summaries = + JavaClassName.Map.find_opt + (JavaClassName.make ~package:test_package ~classname:anonymous_name) + actual + |> IOption.if_none_eval ~f:(fun () -> + assert_failure + (F.sprintf "%s: Did not find anonymous class info for %s" case_name anonymous_name) + ) + in + assert_summaries_equal actual_summaries expected_summary_ids anonymous_name case_name ) + + +let rec assert_expected_list actual expected case_name = + assert_equal (List.length actual) (List.length expected) + ~msg: + (Format.sprintf "%s: Expected list of %d, got %d" case_name (List.length expected) + (List.length actual)) ; + List.iter expected ~f:(fun {name; summary_ids; nested; anm} -> + (* For each expected info find corresponding actual and compare *) + let actual_info = + List.find actual ~f:(fun actual_info -> + JavaClassName.equal + (ClassInfo.get_class_name actual_info) + (JavaClassName.make ~package:test_package ~classname:name) ) + |> IOption.if_none_eval ~f:(fun () -> + assert_failure (F.sprintf "%s: Did not find class info for %s" case_name name) ) + in + assert_summaries_equal (ClassInfo.get_summaries actual_info) summary_ids name case_name ; + assert_anonymous_equal (ClassInfo.get_nested_anonymous_summaries actual_info) anm case_name ; + (* Now recursively check all children and match them with expected *) + assert_expected_list + (ClassInfo.get_nested_classes_info actual_info) + nested + (F.sprintf "%s:%s" case_name name) ) + + +let aggregate list = + List.map list ~f:(fun (classname, summary_id) -> + (JavaClassName.make ~package:test_package ~classname, mock_summary summary_id) ) + |> AggregatedSummaries.aggregate + + +let single_class = + "single_class" + >:: fun _ -> + assert_expected_list (aggregate []) [] "empty" ; + assert_expected_list + (aggregate [("A", 1)]) + [{name= "A"; summary_ids= [1]; anm= []; nested= []}] + "single method" ; + assert_expected_list + (aggregate [("A", 1); ("A", 5); ("A", 2)]) + [{name= "A"; summary_ids= [1; 2; 5]; anm= []; nested= []}] + "several methods" + + +let several_top_classes = + "several_top_classes" + >:: fun _ -> + assert_expected_list + (aggregate [("A", 1); ("B", 2)]) + [ {name= "A"; summary_ids= [1]; anm= []; nested= []} + ; {name= "B"; summary_ids= [2]; anm= []; nested= []} ] + "two simple classes" ; + assert_expected_list + (aggregate [("A", 1); ("B", 5); ("A", 2); ("C", 7); ("A", 8); ("B", 9)]) + [ {name= "A"; summary_ids= [1; 2; 8]; anm= []; nested= []} + ; {name= "B"; summary_ids= [5; 9]; anm= []; nested= []} + ; {name= "C"; summary_ids= [7]; anm= []; nested= []} ] + "several classes" + + +let one_top_class_with_nested = + "several_top_classes" + >:: fun _ -> + assert_expected_list + (aggregate [("A$B", 1); ("A", 2)]) + [ { name= "A" + ; summary_ids= [2] + ; anm= [] + ; nested= [{name= "A$B"; summary_ids= [1]; anm= []; nested= []}] } ] + "simple nested" ; + assert_expected_list + (aggregate [("A$B", 1); ("A", 2); ("A$B", 3); ("A", 4); ("A$C", 6); ("A$D", 7)]) + [ { name= "A" + ; summary_ids= [2; 4] + ; anm= [] + ; nested= + [ {name= "A$B"; summary_ids= [1; 3]; anm= []; nested= []} + ; {name= "A$C"; summary_ids= [6]; anm= []; nested= []} + ; {name= "A$D"; summary_ids= [7]; anm= []; nested= []} ] } ] + "simple nested, several summaries" ; + assert_expected_list + (aggregate [("A$B", 1)]) + [ { name= "A" + ; summary_ids= [] + ; anm= [] + ; nested= [{name= "A$B"; summary_ids= [1]; anm= []; nested= []}] } ] + "nested should also create ancestors even if they have no summaries" ; + assert_expected_list + (aggregate [("A$B$D$F", 1); ("A$B$C", 2)]) + [ { name= "A" + ; summary_ids= [] + ; anm= [] + ; nested= + [ { name= "A$B" + ; summary_ids= [] + ; anm= [] + ; nested= + [ {name= "A$B$C"; summary_ids= [2]; anm= []; nested= []} + ; { name= "A$B$D" + ; summary_ids= [] + ; anm= [] + ; nested= [{name= "A$B$D$F"; summary_ids= [1]; anm= []; nested= []}] } ] } ] } ] + "nested should also create ancestors even if they have no summaries" + + +let with_anonymous = + "with_anonymous" + >:: fun _ -> + assert_expected_list + (aggregate [("A$B$C$3$4", 1); ("A$5$6", 2); ("A$5", 3); ("A", 4); ("A$5$7", 5); ("A$5$6", 6)]) + [ { name= "A" + ; summary_ids= [4] + ; anm= [("A$5$6", [2; 6]); ("A$5", [3]); ("A$5$7", [5])] + ; nested= + [ { name= "A$B" + ; summary_ids= [] + ; anm= [] + ; nested= [{name= "A$B$C"; summary_ids= []; anm= [("A$B$C$3$4", [1])]; nested= []}] } ] + } ] + "with_anonymous" + + +let several_top_classes_with_nested = + "several_top_classes_with_nested" + >:: fun _ -> + assert_expected_list + (aggregate [("B", 1); ("A", 2); ("C$D", 3); ("A$B$D", 4); ("A$B$D", 5); ("A", 6)]) + [ { name= "A" + ; summary_ids= [2; 6] + ; anm= [] + ; nested= + [ { name= "A$B" + ; summary_ids= [] + ; anm= [] + ; nested= [{name= "A$B$D"; summary_ids= [4; 5]; anm= []; nested= []}] } ] } + ; {name= "B"; summary_ids= [1]; anm= []; nested= []} + ; { name= "C" + ; summary_ids= [] + ; anm= [] + ; nested= [{name= "C$D"; summary_ids= [3]; anm= []; nested= []}] } ] + "several_top_classes_with_nested" + + +let test = + "AggregatedSummariesTest" + >::: [ single_class + ; several_top_classes + ; one_top_class_with_nested + ; with_anonymous + ; several_top_classes_with_nested ] diff --git a/infer/src/unit/nullsafe/AllNullsafeTests.ml b/infer/src/unit/nullsafe/AllNullsafeTests.ml index be9f32d9a..9f88fb141 100644 --- a/infer/src/unit/nullsafe/AllNullsafeTests.ml +++ b/infer/src/unit/nullsafe/AllNullsafeTests.ml @@ -7,4 +7,5 @@ open! IStd -let tests = [ThirdPartyMethodTests.test; ThirdPartyAnnotationInfoTests.test] +let tests = + [ThirdPartyMethodTests.test; ThirdPartyAnnotationInfoTests.test; AggregatedSummariesTest.test] diff --git a/infer/tests/codetoanalyze/java/nullsafe/issues.exp b/infer/tests/codetoanalyze/java/nullsafe/issues.exp index 9f5e630b6..013748ec1 100644 --- a/infer/tests/codetoanalyze/java/nullsafe/issues.exp +++ b/infer/tests/codetoanalyze/java/nullsafe/issues.exp @@ -3,8 +3,7 @@ codetoanalyze/java/nullsafe/AlternativeRecommendations.java, codetoanalyze.java. codetoanalyze/java/nullsafe/AlternativeRecommendations.java, codetoanalyze.java.nullsafe_default.AlternativeRecommendations.dereference_ShouldSuggestAlternative(android.view.View):void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`view.findViewById(...)` is nullable and is not locally checked for null when calling `setId(...)`: call to View.findViewById(...) at line 22 (nullable according to nullsafe internal models). If this is intentional, use `androidx.core.view.ViewCompat.requireViewById()` instead.] codetoanalyze/java/nullsafe/AlternativeRecommendations.java, codetoanalyze.java.nullsafe_default.AlternativeRecommendations.passingParam_ShouldSuggestAlternative(android.view.View):void, 1, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, WARNING, [`AlternativeRecommendations.acceptsNonnullView(...)`: parameter #1(`view`) is declared non-nullable but the argument `view.findViewById(...)` is nullable: call to View.findViewById(...) at line 26 (nullable according to nullsafe internal models). If you don't expect null, use `androidx.core.view.ViewCompat.requireViewById()` instead.] codetoanalyze/java/nullsafe/AlternativeRecommendations.java, codetoanalyze.java.nullsafe_default.AlternativeRecommendations.returnValue_ShouldSuggestAlternative(android.view.View):android.view.View, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [`returnValue_ShouldSuggestAlternative(...)`: return type is declared non-nullable but the method returns a nullable value: call to View.findViewById(...) at line 30 (nullable according to nullsafe internal models). If you don't expect null, use `androidx.core.view.ViewCompat.requireViewById()` instead.] -codetoanalyze/java/nullsafe/ButterKnife.java, Linters_dummy_method, 15, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ButterKnife, codetoanalyze.java.nullsafe_default, issues: 4, curr_mode: "Default" -codetoanalyze/java/nullsafe/ButterKnife.java, Linters_dummy_method, 79, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ButterKnife$TestNotInitialized, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" +codetoanalyze/java/nullsafe/ButterKnife.java, Linters_dummy_method, 15, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ButterKnife, codetoanalyze.java.nullsafe_default, issues: 5, curr_mode: "Default" codetoanalyze/java/nullsafe/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife$TestNotInitialized.(codetoanalyze.java.nullsafe_default.ButterKnife), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, WARNING, [Field `notInitializedNormalIsBAD` is declared non-nullable, so it should be initialized in the constructor or in an `@Initializer` method] codetoanalyze/java/nullsafe/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife.(), 0, ERADICATE_FIELD_OVER_ANNOTATED, no_bucket, ADVICE, [Field `ButterKnife.nullable` is always initialized in the constructor but is declared `@Nullable`] codetoanalyze/java/nullsafe/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife.assignNullToNormalIsBAD():void, 1, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [`normal` is declared non-nullable but is assigned `null`: null constant at line 76.] @@ -36,22 +35,8 @@ codetoanalyze/java/nullsafe/ConditionRedundant.java, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/ConditionRedundant.java, codetoanalyze.java.nullsafe_default.ConditionRedundant.ternary_NonnullInBothBranchesIsBAD(java.lang.String,java.lang.String,int):void, 2, ERADICATE_CONDITION_REDUNDANT, no_bucket, ADVICE, [The condition s2 might be always false according to the existing annotations.] codetoanalyze/java/nullsafe/ConditionRedundant.java, codetoanalyze.java.nullsafe_default.ConditionRedundant.testFlowSensitivity(java.lang.String,java.lang.String):void, 2, ERADICATE_CONDITION_REDUNDANT, no_bucket, ADVICE, [The condition nullable1 might be always true according to the existing annotations.] codetoanalyze/java/nullsafe/ConditionRedundant.java, codetoanalyze.java.nullsafe_default.ConditionRedundant.testFlowSensitivity(java.lang.String,java.lang.String):void, 4, ERADICATE_CONDITION_REDUNDANT, no_bucket, ADVICE, [The condition nullable1 might be always true according to the existing annotations.] -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 25, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `FieldNotInitialized` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], FieldNotInitialized, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 28, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$Suppression, codetoanalyze.java.nullsafe_default, issues: 11, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 67, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$OnlyRead, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 75, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$WriteItselfIsBAD, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 85, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$InitializationOrder, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 100, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$OnlyReadIndirect, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 114, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$ShouldInitializeInAllBranches, codetoanalyze.java.nullsafe_default, issues: 3, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 140, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$InitIfNull, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 155, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$InitCircular, codetoanalyze.java.nullsafe_default, issues: 2, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 172, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$InitWithOtherClass, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 173, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], FieldNotInitialized$InitWithOtherClass$OtherClass, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 189, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized$InitWithTheSameClass, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 206, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `TestKnownInitializers` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], TestKnownInitializers, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 209, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestKnownInitializers$KnownInitializers, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 230, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], TestKnownInitializers$FakeActivity, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 234, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestKnownInitializers$SimplyOnCreateWontDoATrick, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" +codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 25, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], FieldNotInitialized, codetoanalyze.java.nullsafe_default, issues: 23, curr_mode: "Default" +codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 206, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestKnownInitializers, codetoanalyze.java.nullsafe_default, issues: 2, curr_mode: "Default" codetoanalyze/java/nullsafe/FieldNotInitialized.java, Linters_dummy_method, 253, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestInitializerAnnotation, codetoanalyze.java.nullsafe_default, issues: 3, curr_mode: "Default" codetoanalyze/java/nullsafe/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.FieldNotInitialized$InitCircular.(codetoanalyze.java.nullsafe_default.FieldNotInitialized), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, WARNING, [Field `stillBad` is declared non-nullable, so it should be initialized in the constructor or in an `@Initializer` method] codetoanalyze/java/nullsafe/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.FieldNotInitialized$InitCircular.(codetoanalyze.java.nullsafe_default.FieldNotInitialized), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, WARNING, [Field `bad` is declared non-nullable, so it should be initialized in the constructor or in an `@Initializer` method] @@ -113,8 +98,6 @@ codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_m codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_method, 120, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NoOverrideSinceDifferentTypesOK, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default" codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_method, 137, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], OverloadExistingIncorrectBAD, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_method, 146, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `ConstructorsAreExcluded` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], ConstructorsAreExcluded, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_method, 147, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], ConstructorsAreExcluded$Base, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_method, 151, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], ConstructorsAreExcluded$Derived, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_method, 160, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ExtendsExternalLibrary, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_method, 177, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], JavaLangEquals, codetoanalyze.java.nullsafe_default, issues: 2, curr_mode: "Default" codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, Linters_dummy_method, 197, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `NonNullableConcreteGetterOK` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], NonNullableConcreteGetterOK, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" @@ -127,12 +110,7 @@ codetoanalyze/java/nullsafe/InconsistentSubclassAnnotation.java, codetoanalyze.j codetoanalyze/java/nullsafe/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/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/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/InheritanceForStrictMode.java, Linters_dummy_method, 14, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `InheritanceForStrictMode` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], InheritanceForStrictMode, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/InheritanceForStrictMode.java, Linters_dummy_method, 15, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], InheritanceForStrictMode$NonStrictBase, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/InheritanceForStrictMode.java, Linters_dummy_method, 30, ERADICATE_META_CLASS_IS_NULLSAFE, no_bucket, INFO, [], InheritanceForStrictMode$StrictBase, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Strict" -codetoanalyze/java/nullsafe/InheritanceForStrictMode.java, Linters_dummy_method, 47, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], InheritanceForStrictMode$StrictExtendingNonstrict, codetoanalyze.java.nullsafe_default, issues: 2, curr_mode: "Strict" -codetoanalyze/java/nullsafe/InheritanceForStrictMode.java, Linters_dummy_method, 62, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], InheritanceForStrictMode$StrictExtendingStrict, codetoanalyze.java.nullsafe_default, issues: 2, curr_mode: "Strict" -codetoanalyze/java/nullsafe/InheritanceForStrictMode.java, Linters_dummy_method, 76, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], InheritanceForStrictMode$NonStrictExtendingStrict, codetoanalyze.java.nullsafe_default, issues: 2, curr_mode: "Default" +codetoanalyze/java/nullsafe/InheritanceForStrictMode.java, Linters_dummy_method, 14, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], InheritanceForStrictMode, codetoanalyze.java.nullsafe_default, issues: 6, curr_mode: "Default" codetoanalyze/java/nullsafe/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`.] codetoanalyze/java/nullsafe/InheritanceForStrictMode.java, codetoanalyze.java.nullsafe_default.InheritanceForStrictMode$NonStrictExtendingStrict.params(java.lang.String,java.lang.String):void, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `badToRemoveNullableInChildren` of method `InheritanceForStrictMode$NonStrictExtendingStrict.params(...)` is missing `@Nullable` declaration when overriding `InheritanceForStrictMode$StrictBase.params(...)`. The parent method declared it can handle `null` for this param, so the child should also declare that.] codetoanalyze/java/nullsafe/InheritanceForStrictMode.java, codetoanalyze.java.nullsafe_default.InheritanceForStrictMode$StrictExtendingNonstrict.badToAddNullableInChildren():java.lang.String, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, ERROR, [Child method `InheritanceForStrictMode$StrictExtendingNonstrict.badToAddNullableInChildren()` is not substitution-compatible with its parent: the return type is declared as nullable, but parent method `InheritanceForStrictMode$NonStrictBase.badToAddNullableInChildren()` is missing `@Nullable` declaration. Either mark the parent as `@Nullable` or ensure the child does not return `null`.] @@ -146,9 +124,7 @@ codetoanalyze/java/nullsafe/LibraryCalls.java, codetoanalyze.java.nullsafe_defau codetoanalyze/java/nullsafe/LibraryCalls.java, codetoanalyze.java.nullsafe_default.LibraryCalls.badReferenceDereference(java.lang.ref.Reference):java.lang.String, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`ref.get()` is nullable and is not locally checked for null when calling `toString()`: call to Reference.get() at line 19 (nullable according to nullsafe internal models).] codetoanalyze/java/nullsafe/LibraryCalls.java, codetoanalyze.java.nullsafe_default.LibraryCalls.badSoftReferenceDereference(java.lang.ref.SoftReference):java.lang.String, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`ref.get()` is nullable and is not locally checked for null when calling `toString()`: call to SoftReference.get() at line 31 (nullable according to nullsafe internal models).] codetoanalyze/java/nullsafe/LibraryCalls.java, codetoanalyze.java.nullsafe_default.LibraryCalls.badWeakReferenceDereference(java.lang.ref.WeakReference):java.lang.String, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`ref.get()` is nullable and is not locally checked for null when calling `toString()`: call to Reference.get() at line 23 (nullable according to nullsafe internal models).] -codetoanalyze/java/nullsafe/MapNullability.java, Linters_dummy_method, 13, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `MapNullability` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], MapNullability, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/MapNullability.java, Linters_dummy_method, 15, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], MapNullability$TestThatGetIsAllowedOnlyAfterContainsKeyWasChecked, codetoanalyze.java.nullsafe_default, issues: 4, curr_mode: "Default" -codetoanalyze/java/nullsafe/MapNullability.java, Linters_dummy_method, 64, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], MapNullability$TestThatGetAfterPutIsAllowed, codetoanalyze.java.nullsafe_default, issues: 9, curr_mode: "Default" +codetoanalyze/java/nullsafe/MapNullability.java, Linters_dummy_method, 13, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], MapNullability, codetoanalyze.java.nullsafe_default, issues: 13, curr_mode: "Default" codetoanalyze/java/nullsafe/MapNullability.java, codetoanalyze.java.nullsafe_default.MapNullability$TestThatGetAfterPutIsAllowed.getAfterConditionalPutWrongKeyIsBAD(java.util.Map,java.lang.String,java.lang.String):void, 5, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [`dontAssignNull` is declared non-nullable but is assigned a nullable: call to Map.get(...) at line 137 (nullable according to nullsafe internal models).] codetoanalyze/java/nullsafe/MapNullability.java, codetoanalyze.java.nullsafe_default.MapNullability$TestThatGetAfterPutIsAllowed.getAfterPutNullableIsBAD(java.util.Map,java.lang.String):void, 2, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, WARNING, [`Map.put(...)`: parameter #2 is declared non-nullable (according to nullsafe internal models) but the argument `nullableValue` is nullable.] codetoanalyze/java/nullsafe/MapNullability.java, codetoanalyze.java.nullsafe_default.MapNullability$TestThatGetAfterPutIsAllowed.getAfterPutNullableIsBAD(java.util.Map,java.lang.String):void, 3, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [`dontAssignNull` is declared non-nullable but is assigned a nullable: method parameter nullableValue.] @@ -175,12 +151,7 @@ codetoanalyze/java/nullsafe/ModePromotions.java, Linters_dummy_method, 96, ERADI codetoanalyze/java/nullsafe/ModePromotions.java, Linters_dummy_method, 105, ERADICATE_META_CLASS_IS_NULLSAFE, no_bucket, INFO, [], TrustSome_TrustStrictIsNotNeeded_CanBePromotedToStrict, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "LocalTrustSome", promote_mode: "Strict" codetoanalyze/java/nullsafe/ModePromotions.java, Linters_dummy_method, 112, ERADICATE_META_CLASS_IS_NULLSAFE, no_bucket, INFO, [], TrustNone_CanBePromotedToStrict, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "LocalTrustNone", promote_mode: "Strict" codetoanalyze/java/nullsafe/MyPreconditions.java, Linters_dummy_method, 11, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `MyPreconditions` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], MyPreconditions, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NestedFieldAccess.java, Linters_dummy_method, 12, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `NestedFieldAccess` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], NestedFieldAccess, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NestedFieldAccess.java, Linters_dummy_method, 14, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NestedFieldAccess$C, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NestedFieldAccess.java, Linters_dummy_method, 18, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NestedFieldAccess$CC, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NestedFieldAccess.java, Linters_dummy_method, 22, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NestedFieldAccess$CCC, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NestedFieldAccess.java, Linters_dummy_method, 30, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NestedFieldAccess$TestNullableChains, codetoanalyze.java.nullsafe_default, issues: 7, curr_mode: "Default" -codetoanalyze/java/nullsafe/NestedFieldAccess.java, Linters_dummy_method, 124, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NestedFieldAccess$TestFunctionsIdempotent, codetoanalyze.java.nullsafe_default, issues: 8, curr_mode: "Default" +codetoanalyze/java/nullsafe/NestedFieldAccess.java, Linters_dummy_method, 12, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NestedFieldAccess, codetoanalyze.java.nullsafe_default, issues: 15, curr_mode: "Default" codetoanalyze/java/nullsafe/NestedFieldAccess.java, codetoanalyze.java.nullsafe_default.NestedFieldAccess$TestFunctionsIdempotent.chainOf0VsChainOf0ParamsMismatchIsBad():void, 2, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [`dontAssignNull` is declared non-nullable but is assigned a nullable: call to nullable(...) at line 145.] codetoanalyze/java/nullsafe/NestedFieldAccess.java, codetoanalyze.java.nullsafe_default.NestedFieldAccess$TestFunctionsIdempotent.chainOf0VsChainOf1IsBad():void, 2, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [`dontAssignNull` is declared non-nullable but is assigned a nullable: call to nullable(...) at line 169.] codetoanalyze/java/nullsafe/NestedFieldAccess.java, codetoanalyze.java.nullsafe_default.NestedFieldAccess$TestFunctionsIdempotent.chainOf1VsChainOf0IsBad():void, 2, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [`dontAssignNull` is declared non-nullable but is assigned a nullable: call to nullable(...) at line 175.] @@ -198,7 +169,6 @@ codetoanalyze/java/nullsafe/NestedFieldAccess.java, codetoanalyze.java.nullsafe_ codetoanalyze/java/nullsafe/NestedFieldAccess.java, codetoanalyze.java.nullsafe_default.NestedFieldAccess$TestNullableChains.veryDeep_IncompleteAccessViaOrEarlyReturnIsBad(codetoanalyze.java.nullsafe_default.NestedFieldAccess$CCC):void, 3, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`ccc.cc.c.s` is nullable and is not locally checked for null when calling `length()`.] codetoanalyze/java/nullsafe/NoReuseUndefFunctionValues.java, Linters_dummy_method, 12, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `NoReuseUndefFunctionValues` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], NoReuseUndefFunctionValues, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" codetoanalyze/java/nullsafe/NullFieldAccess.java, Linters_dummy_method, 12, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullFieldAccess, codetoanalyze.java.nullsafe_default, issues: 5, curr_mode: "Default" -codetoanalyze/java/nullsafe/NullFieldAccess.java, Linters_dummy_method, 14, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullFieldAccess$I, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe_default.NullFieldAccess.(), 0, ERADICATE_FIELD_OVER_ANNOTATED, no_bucket, ADVICE, [Field `NullFieldAccess.nullableArray` is always initialized in the constructor but is declared `@Nullable`] codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe_default.NullFieldAccess.(), 0, ERADICATE_FIELD_OVER_ANNOTATED, no_bucket, ADVICE, [Field `NullFieldAccess.nullable` is always initialized in the constructor but is declared `@Nullable`] codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe_default.NullFieldAccess.testArray():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [Array `NullFieldAccess.nullableArray` is nullable and is not locally checked for null when accessing its length.] @@ -206,14 +176,7 @@ codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe_de codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe_default.NullFieldAccess.testInterface():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`bad` is nullable and is not locally checked for null when calling `toString()`: field nullable at line 52.] codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe_default.NullFieldAccess.testNonStaticFields():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`bad` is nullable and is not locally checked for null when calling `toString()`: field nullable at line 36.] codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe_default.NullFieldAccess.testStatic():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`bad` is nullable and is not locally checked for null when calling `toString()`: field nullableStatic at line 44.] -codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 22, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullMethodCall, codetoanalyze.java.nullsafe_default, issues: 22, curr_mode: "Default" -codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 60, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullMethodCall$S, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 67, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullMethodCall$Inner, codetoanalyze.java.nullsafe_default, issues: 2, curr_mode: "Default" -codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 142, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullMethodCall$Inner$InnerInner, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 190, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullMethodCall$InitializeAndExceptions, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 202, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullMethodCall$InitializeViaPrivateMethod, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 218, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullMethodCall$CheckNotNullVararg, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 244, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullMethodCall$SystemExitDoesNotReturn, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" +codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 22, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullMethodCall, codetoanalyze.java.nullsafe_default, issues: 24, curr_mode: "Default" codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe_default.NullMethodCall$Inner.outerField():int, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`s` is nullable and is not locally checked for null when calling `length()`: field fld at line 69.] codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe_default.NullMethodCall$Inner.outerPrivateField():int, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`s` is nullable and is not locally checked for null when calling `length()`: field pfld at line 80.] codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe_default.NullMethodCall.FP_propagatesNonNullAfterComparisonFieldOkay(java.lang.Object):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`NullMethodCall.nullableField` is nullable and is not locally checked for null when calling `toString()`.] @@ -238,16 +201,7 @@ codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe_def codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe_default.NullMethodCall.testSystemGetenvBad():int, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`envValue` is nullable and is not locally checked for null when calling `length()`: call to System.getenv(...) at line 240 (nullable according to nullsafe internal models).] codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe_default.NullMethodCall.withConditionalAssignemnt(codetoanalyze.java.nullsafe_default.NullMethodCall$AnotherI,boolean,java.lang.Object,java.lang.Object):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`i` is nullable and is not locally checked for null when calling `withObjectParameter(...)`.] codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe_default.NullMethodCall.withConjuction(codetoanalyze.java.nullsafe_default.NullMethodCall$AnotherI,boolean,boolean):void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`i` is nullable and is not locally checked for null when calling `withBooleanParameter(...)`.] -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 16, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `NullsafeMode` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], NullsafeMode, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 17, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullsafeMode$VariousMethods, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 28, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeMode$NonNullsafe, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 54, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullsafeMode$AnotherNonNullsafe, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 56, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], NullsafeMode$UncheckedParams, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 77, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeMode$TrustAllNullsafe, codetoanalyze.java.nullsafe_default, issues: 5, curr_mode: "LocalTrustAll" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 124, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeMode$TrustSomeNullsafe, codetoanalyze.java.nullsafe_default, issues: 3, curr_mode: "LocalTrustSome" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 153, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeMode$TrustNoneNullsafe, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustNone" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 164, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeMode$NullsafeWithStrictMode, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 184, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeMode$StrictNullsafe, codetoanalyze.java.nullsafe_default, issues: 3, curr_mode: "Strict" +codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 16, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeMode, codetoanalyze.java.nullsafe_default, issues: 13, curr_mode: "Default" codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$NullsafeWithStrictMode.BAD_returnFromNonStrict():java.lang.String, 1, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NullsafeMode$VariousMethods.returnVal()`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. Result of this call is used at line 174. Either add a local check for null or assertion, or make `NullsafeMode$VariousMethods` nullsafe strict.] codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$StrictNullsafe.BAD_dereferenceNotAnnotatedThirdParty():void, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 218. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.] codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$StrictNullsafe.BAD_passThirdPartyToUnchecked():codetoanalyze.java.nullsafe_default.NullsafeMode$UncheckedParams, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.getUncheckedLong(...)`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 214. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.] @@ -262,29 +216,17 @@ codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe_defau codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustSomeNullsafe.BAD_returnNullFromNonNulsafe():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`BAD_returnNullFromNonNulsafe()`: return type is declared non-nullable but the method returns a nullable value: call to returnNull() at line 144.] codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustSomeNullsafe.FP_OK_accessFieldFromNonNullsafe():java.lang.String, 1, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NullsafeMode$NonNullsafe.valField`: `@NullsafeLocal(trust=selected)` mode prohibits using values coming from non-nullsafe classes without a check. This field is used at line 147. Either add a local check for null or assertion, or make `NullsafeMode$NonNullsafe` @Nullsafe (or add it to trust list).] codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustSomeNullsafe.OK_returnFromUntrustedNonNullsafeAsNullable():java.lang.String, 0, ERADICATE_RETURN_OVER_ANNOTATED, no_bucket, ADVICE, [Method `OK_returnFromUntrustedNonNullsafeAsNullable()` is annotated with `@Nullable` but never returns null.] -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 14, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeLocal, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustAll" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 21, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeLocal$Nested, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustAll" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 27, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeLocal$Nested$DeeplyNested, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustAll" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 41, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeLocal$NestedStrict, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 49, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeLocal$NestedExplicitLocal, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustAll" +codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 14, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeLocal, codetoanalyze.java.nullsafe_default, issues: 5, curr_mode: "LocalTrustAll" codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 49, ERADICATE_REDUNDANT_NESTED_CLASS_ANNOTATION, no_bucket, ADVICE, [`NullsafeLocal$NestedExplicitLocal`: the same @Nullsafe mode is already specified in the outer class, so this annotation can be removed.], NullsafeLocal$NestedExplicitLocal, codetoanalyze.java.nullsafe_default -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 57, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeStrict, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 63, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeStrict$Nested, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Strict" +codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 57, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeStrict, codetoanalyze.java.nullsafe_default, issues: 4, curr_mode: "Strict" codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 71, ERADICATE_BAD_NESTED_CLASS_ANNOTATION, no_bucket, WARNING, [`NullsafeStrict$Nested$DeeplyNestedLocalIsStillStrict`: nested classes are disallowed to weaken @Nullsafe mode specified in the outer class. This annotation will be ignored.], NullsafeStrict$Nested$DeeplyNestedLocalIsStillStrict, codetoanalyze.java.nullsafe_default -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 71, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeStrict$Nested$DeeplyNestedLocalIsStillStrict, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Strict" codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 80, ERADICATE_BAD_NESTED_CLASS_ANNOTATION, no_bucket, WARNING, [`NullsafeStrict$NestedLocalIsStillStrict`: nested classes are disallowed to weaken @Nullsafe mode specified in the outer class. This annotation will be ignored.], NullsafeStrict$NestedLocalIsStillStrict, codetoanalyze.java.nullsafe_default -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 80, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeStrict$NestedLocalIsStillStrict, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 87, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `Default` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], Default, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 94, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], Default$NestedLocal, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustAll" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 106, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], Default$NestedLocal$DeeplyNestedStrict, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Strict" +codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 87, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], Default, codetoanalyze.java.nullsafe_default, issues: 2, curr_mode: "Default" codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 114, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `A` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], A, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 120, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `B` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], B, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 122, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `C` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], C, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 129, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrustSome, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustSome" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 140, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrustSome$NotAnnotatedNested, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustSome" -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 152, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrustSome$CanRemoveFromTrustList, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustSome" +codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 129, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrustSome, codetoanalyze.java.nullsafe_default, issues: 4, curr_mode: "LocalTrustSome" codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 161, ERADICATE_BAD_NESTED_CLASS_ANNOTATION, no_bucket, WARNING, [Nested classes cannot add classes to trust list if they are not in the outer class trust list. Remove `C` from trust list.], TrustSome$CanNotAddToTrustList, codetoanalyze.java.nullsafe_default -codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, Linters_dummy_method, 161, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrustSome$CanNotAddToTrustList, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "LocalTrustSome" codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, codetoanalyze.java.nullsafe_default.Default$NestedLocal$DeeplyNestedStrict.returningDefaultNotNullIsError():java.lang.String, 1, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`Default.getString()`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. Result of this call is used at line 107. Either add a local check for null or assertion, or make `Default` nullsafe strict.] codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, codetoanalyze.java.nullsafe_default.Default$NestedLocal.shouldBeNullsafeModeError():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`shouldBeNullsafeModeError()`: return type is declared non-nullable but the method returns `null`: null constant at line 96.] codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, codetoanalyze.java.nullsafe_default.NullsafeLocal$Nested$DeeplyNested.shouldBeNullsafeModeError():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`shouldBeNullsafeModeError()`: return type is declared non-nullable but the method returns `null`: null constant at line 29.] @@ -300,9 +242,7 @@ codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, codetoanalyze.java.n codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, codetoanalyze.java.nullsafe_default.TrustSome$CanRemoveFromTrustList.dontTrustA_BAD():java.lang.String, 1, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`A.getString()`: `@NullsafeLocal(trust=selected)` mode prohibits using values coming from non-nullsafe classes without a check. Result of this call is used at line 153. Either add a local check for null or assertion, or make `A` @Nullsafe (or add it to trust list).] codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, codetoanalyze.java.nullsafe_default.TrustSome$NotAnnotatedNested.dontTrustC_Bad():java.lang.String, 1, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`C.getString()`: `@NullsafeLocal(trust=selected)` mode prohibits using values coming from non-nullsafe classes without a check. Result of this call is used at line 145. Either add a local check for null or assertion, or make `C` @Nullsafe (or add it to trust list).] codetoanalyze/java/nullsafe/NullsafeModeNestedClasses.java, codetoanalyze.java.nullsafe_default.TrustSome.dontTrustC_Bad():java.lang.String, 1, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`C.getString()`: `@NullsafeLocal(trust=selected)` mode prohibits using values coming from non-nullsafe classes without a check. Result of this call is used at line 135. Either add a local check for null or assertion, or make `C` @Nullsafe (or add it to trust list).] -codetoanalyze/java/nullsafe/ParameterNotNullable.java, Linters_dummy_method, 20, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ParameterNotNullable, codetoanalyze.java.nullsafe_default, issues: 37, curr_mode: "Default" -codetoanalyze/java/nullsafe/ParameterNotNullable.java, Linters_dummy_method, 64, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], ParameterNotNullable$Builder, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/ParameterNotNullable.java, Linters_dummy_method, 93, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ParameterNotNullable$ConstructorCall, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" +codetoanalyze/java/nullsafe/ParameterNotNullable.java, Linters_dummy_method, 20, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ParameterNotNullable, codetoanalyze.java.nullsafe_default, issues: 38, curr_mode: "Default" codetoanalyze/java/nullsafe/ParameterNotNullable.java, Linters_dummy_method, 195, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `SomeClass` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], SomeClass, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" codetoanalyze/java/nullsafe/ParameterNotNullable.java, codetoanalyze.java.nullsafe_default.ParameterNotNullable$ConstructorCall.(codetoanalyze.java.nullsafe_default.ParameterNotNullable,int), 0, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, WARNING, [`ParameterNotNullable$ConstructorCall(...)`: parameter #2(`s`) is declared non-nullable but the argument is `null`.] codetoanalyze/java/nullsafe/ParameterNotNullable.java, codetoanalyze.java.nullsafe_default.ParameterNotNullable.callNull():void, 2, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, WARNING, [`ParameterNotNullable.test(...)`: parameter #1(`s`) is declared non-nullable but the argument `s` is `null`: null constant at line 39.] @@ -341,11 +281,7 @@ codetoanalyze/java/nullsafe/ParameterNotNullable.java, codetoanalyze.java.nullsa codetoanalyze/java/nullsafe/ParameterNotNullable.java, codetoanalyze.java.nullsafe_default.ParameterNotNullable.testThreeParameters():void, 2, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, WARNING, [`ParameterNotNullable.threeParameters(...)`: parameter #1(`s1`) is declared non-nullable but the argument is `null`.] codetoanalyze/java/nullsafe/ParameterNotNullable.java, codetoanalyze.java.nullsafe_default.ParameterNotNullable.testThreeParameters():void, 3, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, WARNING, [`ParameterNotNullable.threeParameters(...)`: parameter #2(`s2`) is declared non-nullable but the argument is `null`.] codetoanalyze/java/nullsafe/ParameterNotNullable.java, codetoanalyze.java.nullsafe_default.ParameterNotNullable.testThreeParameters():void, 4, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, WARNING, [`ParameterNotNullable.threeParameters(...)`: parameter #3(`s3`) is declared non-nullable but the argument is `null`.] -codetoanalyze/java/nullsafe/PropagatesNullable.java, Linters_dummy_method, 14, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `TestPropagatesNullable` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], TestPropagatesNullable, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/PropagatesNullable.java, Linters_dummy_method, 16, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestPropagatesNullable$TestOneParameter, codetoanalyze.java.nullsafe_default, issues: 8, curr_mode: "Default" -codetoanalyze/java/nullsafe/PropagatesNullable.java, Linters_dummy_method, 64, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestPropagatesNullable$TestSecondParameter, codetoanalyze.java.nullsafe_default, issues: 6, curr_mode: "Default" -codetoanalyze/java/nullsafe/PropagatesNullable.java, Linters_dummy_method, 96, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestPropagatesNullable$TestBothParams, codetoanalyze.java.nullsafe_default, issues: 3, curr_mode: "Default" -codetoanalyze/java/nullsafe/PropagatesNullable.java, Linters_dummy_method, 113, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestPropagatesNullable$TestReturnValueAnnotationIsAutomaticallyInferred, codetoanalyze.java.nullsafe_default, issues: 3, curr_mode: "Default" +codetoanalyze/java/nullsafe/PropagatesNullable.java, Linters_dummy_method, 14, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TestPropagatesNullable, codetoanalyze.java.nullsafe_default, issues: 20, curr_mode: "Default" codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestBothParams.testBothParamsShouldBeNonnull(java.lang.String,java.lang.String):void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`propagatesNullable(...)` is nullable and is not locally checked for null when calling `length()`: method parameter sNullable.] codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestBothParams.testBothParamsShouldBeNonnull(java.lang.String,java.lang.String):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`propagatesNullable(...)` is nullable and is not locally checked for null when calling `length()`: method parameter sNullable.] codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestBothParams.testBothParamsShouldBeNonnull(java.lang.String,java.lang.String):void, 3, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`propagatesNullable(...)` is nullable and is not locally checked for null when calling `length()`: method parameter sNullable.] @@ -366,9 +302,7 @@ codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestSecondParameter.test(java.lang.String,java.lang.String):void, 7, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`nullable(...)` is nullable and is not locally checked for null when calling `length()`.] codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestSecondParameter.test(java.lang.String,java.lang.String):void, 11, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`nullable(...)` is nullable and is not locally checked for null when calling `length()`.] codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestSecondParameter.test(java.lang.String,java.lang.String):void, 15, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`nullable(...)` is nullable and is not locally checked for null when calling `length()`.] -codetoanalyze/java/nullsafe/ReturnNotNullable.java, Linters_dummy_method, 19, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ReturnNotNullable, codetoanalyze.java.nullsafe_default, issues: 8, curr_mode: "Default" -codetoanalyze/java/nullsafe/ReturnNotNullable.java, Linters_dummy_method, 154, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], ReturnNotNullable$E, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/ReturnNotNullable.java, Linters_dummy_method, 191, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ReturnNotNullable$ConditionalAssignment, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" +codetoanalyze/java/nullsafe/ReturnNotNullable.java, Linters_dummy_method, 19, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ReturnNotNullable, codetoanalyze.java.nullsafe_default, issues: 9, curr_mode: "Default" codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe_default.ReturnNotNullable$ConditionalAssignment.test(boolean):java.lang.Object, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [`test(...)`: return type is declared non-nullable but the method returns a nullable value: field f1 at line 199.] codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe_default.ReturnNotNullable.constantToNullableIsOverannotated():java.lang.String, 0, ERADICATE_RETURN_OVER_ANNOTATED, no_bucket, ADVICE, [Method `constantToNullableIsOverannotated()` is annotated with `@Nullable` but never returns null.] codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe_default.ReturnNotNullable.getResourceNullable(java.lang.Class,java.lang.String):java.net.URL, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [`getResourceNullable(...)`: return type is declared non-nullable but the method returns a nullable value: call to Class.getResource(...) at line 177 (nullable according to nullsafe internal models).] @@ -416,17 +350,7 @@ codetoanalyze/java/nullsafe/SwitchCase.java, Linters_dummy_method, 63, ERADICATE codetoanalyze/java/nullsafe/SwitchCase.java, codetoanalyze.java.nullsafe_default.SwitchCase.getNullableColor():codetoanalyze.java.nullsafe_default.Color, 0, ERADICATE_RETURN_OVER_ANNOTATED, no_bucket, ADVICE, [Method `getNullableColor()` is annotated with `@Nullable` but never returns null.] codetoanalyze/java/nullsafe/SwitchCase.java, codetoanalyze.java.nullsafe_default.SwitchCase.switchOnNullIsBad():java.lang.String, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [NullPointerException will be thrown at this line! `color` is `null` and is dereferenced via calling `ordinal()`: null constant at line 14.] codetoanalyze/java/nullsafe/SwitchCase.java, codetoanalyze.java.nullsafe_default.SwitchCase.switchOnNullableIsBad():java.lang.String, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`color` is nullable and is not locally checked for null when calling `ordinal()`: call to getNullableColor() at line 28.] -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 17, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `TrueFalseOnNull` is free of nullability issues. Mark it `@Nullsafe(value = Nullsafe.Mode.LOCAL, trustOnly = @Nullsafe.TrustList({}))` to prevent regressions.], TrueFalseOnNull, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 19, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], TrueFalseOnNull$StaticOneParam, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 35, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], TrueFalseOnNull$NonStaticOneParam, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 57, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], TrueFalseOnNull$NonStaticSeveralParams, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 87, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrueFalseOnNull$TestStaticOneParam, codetoanalyze.java.nullsafe_default, issues: 4, curr_mode: "Default" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 126, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrueFalseOnNull$TestNonStaticOneParam, codetoanalyze.java.nullsafe_default, issues: 4, curr_mode: "Default" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 166, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrueFalseOnNull$TestNonStaticSeveralParams, codetoanalyze.java.nullsafe_default, issues: 8, curr_mode: "Default" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 212, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], TrueFalseOnNull$TestModels, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 228, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], TrueFalseOnNull$TestEqualsIsFalseOnNull, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 230, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, INFO, [], TrueFalseOnNull$TestEqualsIsFalseOnNull$SomeObject, codetoanalyze.java.nullsafe_default, issues: 0, curr_mode: "Default", promote_mode: "Strict" -codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 273, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrueFalseOnNull$EarlyReturn, codetoanalyze.java.nullsafe_default, issues: 1, curr_mode: "Default" +codetoanalyze/java/nullsafe/TrueFalseOnNull.java, Linters_dummy_method, 17, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], TrueFalseOnNull, codetoanalyze.java.nullsafe_default, issues: 17, curr_mode: "Default" codetoanalyze/java/nullsafe/TrueFalseOnNull.java, codetoanalyze.java.nullsafe_default.TrueFalseOnNull$EarlyReturn.testEarlyReturn(java.lang.CharSequence,java.lang.CharSequence):void, 6, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`s2` is nullable and is not locally checked for null when calling `toString()`.] codetoanalyze/java/nullsafe/TrueFalseOnNull.java, codetoanalyze.java.nullsafe_default.TrueFalseOnNull$TestNonStaticOneParam.falseOnNullNegativeBranchIsBAD(java.lang.String):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`s` is nullable and is not locally checked for null when calling `toString()`.] codetoanalyze/java/nullsafe/TrueFalseOnNull.java, codetoanalyze.java.nullsafe_default.TrueFalseOnNull$TestNonStaticOneParam.notAnnotatedNegativeBranchIsBAD(java.lang.String):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`s` is nullable and is not locally checked for null when calling `toString()`.]