[java] Enhance annotation parsing with the ability to pick up parameter names

Summary: When we have an annotation like `Prop(varArg = X)` or ` ThreadSafe(enableChecks = true)`, we were not able to pick up the names of the parameters like `varArg` or `enableChecks`. This diff fixes that.

Reviewed By: skcho, ngorogiannis

Differential Revision: D17571377

fbshipit-source-id: 5293b5810
master
Ezgi Çiçek 5 years ago committed by Facebook Github Bot
parent 2be3189912
commit 8c1fdab0a8

@ -11,7 +11,9 @@ open! IStd
module F = Format
type parameters = string list [@@deriving compare]
type parameter = {name: string option; value: string} [@@deriving compare]
type parameters = parameter list [@@deriving compare]
(** Type to represent one @Annotation. *)
type t =
@ -26,9 +28,19 @@ let final = {class_name= "final"; parameters= []}
(** Pretty print an annotation. *)
let prefix = match Language.curr_language_is Java with true -> "@" | false -> "_"
let pp_parameter fmt {name; value} =
match name with
| None ->
F.fprintf fmt "\"%s\"" value
| Some name ->
F.fprintf fmt "%s=\"%s\"" name value
let pp fmt annotation =
F.fprintf fmt "%s%s%s" prefix annotation.class_name
(String.concat ~sep:"," annotation.parameters)
let pp_sep fmt _ = F.pp_print_string fmt ", " in
F.fprintf fmt "%s%s%a" prefix annotation.class_name
(F.pp_print_list ~pp_sep pp_parameter)
annotation.parameters
module Item = struct

@ -11,7 +11,9 @@ open! IStd
module F = Format
type parameters = string list
type parameter = {name: string option; value: string}
type parameters = parameter list
(** Type to represent one @Annotation. *)
type t =

@ -126,10 +126,10 @@ let is_suppressed ?(field_name = None) tenv proc_desc kind =
let annotation_matches (a : Annot.t) =
let normalize str = Str.global_replace (Str.regexp "[_-]") "" (String.lowercase str) in
let drop_prefix str = Str.replace_first (Str.regexp "^[A-Za-z]+_") "" str in
let normalized_equal s1 s2 = String.equal (normalize s1) (normalize s2) in
let normalized_equal s1 a2 = String.equal (normalize s1) (normalize a2.Annot.value) in
let is_parameter_suppressed () =
String.is_suffix a.class_name ~suffix:Annotations.suppress_lint
&& List.mem ~equal:normalized_equal a.parameters kind.IssueType.unique_id
&& List.exists ~f:(normalized_equal kind.IssueType.unique_id) a.parameters
in
let is_annotation_suppressed () =
String.is_suffix

@ -761,7 +761,7 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
let annot_extract_guarded_by_str ((annot : Annot.t), _) =
if Annotations.annot_ends_with annot Annotations.guarded_by then
match annot.parameters with
| [guarded_by_str] when not (excluded_guardedby_string guarded_by_str) ->
| [Annot.{value= guarded_by_str}] when not (excluded_guardedby_string guarded_by_str) ->
Some guarded_by_str
| _ ->
None
@ -772,7 +772,7 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
let extract_suppress_warnings_str item_annot =
let annot_suppress_warnings_str ((annot : Annot.t), _) =
if Annotations.annot_ends_with annot Annotations.suppress_lint then
match annot.parameters with [suppr_str] -> Some suppr_str | _ -> None
match annot.parameters with [Annot.{value= suppr_str}] -> Some suppr_str | _ -> None
else None
in
List.find_map ~f:annot_suppress_warnings_str item_annot

@ -66,7 +66,7 @@ let edge_is_strong tenv obj_edge =
in
let has_weak_or_unretained_or_assign params =
List.exists
~f:(fun att ->
~f:(fun Annot.{value= att} ->
String.equal Config.unsafe_unret att
|| String.equal Config.weak att || String.equal Config.assign att )
params

@ -97,8 +97,13 @@ module RequiredProps = struct
~f:(fun (({Annot.parameters} as annot), _) ->
Annotations.annot_ends_with annot Annotations.prop
&& (* Don't count as required if it's @Prop(optional = true) *)
not (List.exists ~f:(fun annot_string -> String.equal annot_string "true") parameters)
)
not
(List.exists
~f:(fun Annot.{name; value} ->
Option.value_map name ~default:false ~f:(fun name ->
String.equal "optional" name )
&& String.equal value "true" )
parameters) )
annot_list
in
match Tenv.lookup tenv typename with

@ -40,13 +40,17 @@ let fields_superclass tenv interface_decl_info =
let build_sil_field qual_type_to_sil_type tenv class_tname field_name qual_type prop_attributes =
let prop_atts = List.map ~f:Clang_ast_j.string_of_property_attribute prop_attributes in
let prop_atts =
List.map
~f:(fun att -> Annot.{name= None; value= Clang_ast_j.string_of_property_attribute att})
prop_attributes
in
let annotation_from_type t =
match t.Typ.desc with
| Typ.Tptr (_, Typ.Pk_objc_weak) ->
[Config.weak]
[Annot.{name= None; value= Config.weak}]
| Typ.Tptr (_, Typ.Pk_objc_unsafe_unretained) ->
[Config.unsafe_unret]
[Annot.{name= None; value= Config.unsafe_unret}]
| _ ->
[]
in

@ -937,7 +937,7 @@ let should_report_guardedby_violation classname_str ({snapshot; tenv; procdesc}
Typ.Fieldname.equal f field_name
&& List.exists a ~f:(fun ((annot : Annot.t), _) ->
Annotations.annot_ends_with annot Annotations.guarded_by
&& match annot.parameters with [param] -> not (is_uitthread param) | _ -> false )
&& match annot.parameters with [param] -> not (is_uitthread param.value) | _ -> false )
in
(not snapshot.lock)
&& RacerDDomain.TraceElem.is_write snapshot.access

@ -286,7 +286,12 @@ let is_thread_safe item_annot =
Annotations.annot_ends_with annot annot_string
|| String.equal annot.class_name annot_string )
threadsafe_annotations
&& match annot.Annot.parameters with ["false"] -> false | _ -> true
&&
match annot.Annot.parameters with
| [Annot.{name= Some "enableChecks"; value= "false"}] ->
false
| _ ->
true
in
List.exists ~f item_annot
@ -295,7 +300,12 @@ let is_thread_safe item_annot =
let is_assumed_thread_safe item_annot =
let f (annot, _) =
Annotations.annot_ends_with annot Annotations.thread_safe
&& match annot.Annot.parameters with ["false"] -> true | _ -> false
&&
match annot.Annot.parameters with
| [Annot.{name= Some "enableChecks"; value= "false"}] ->
true
| _ ->
false
in
List.exists ~f item_annot

@ -15,15 +15,15 @@ let translate a : Annot.t =
let rec translate_value_pair acc (x, value) =
match value with
| JBasics.EVArray (JBasics.EVCstString s :: l) ->
translate_value_pair (s :: acc) (x, JBasics.EVArray l)
translate_value_pair (Annot.{name= Some x; value= s} :: acc) (x, JBasics.EVArray l)
| JBasics.EVCstString s ->
s :: acc
Annot.{name= Some x; value= s} :: acc
| JBasics.EVCstBoolean 0 ->
(* just translate bools as strings. means we can't distinguish between a boolean false
literal parameter and string literal "false" parameter, but that's ok. *)
"false" :: acc
Annot.{name= Some x; value= "false"} :: acc
| JBasics.EVCstBoolean 1 ->
"true" :: acc
Annot.{name= Some x; value= "true"} :: acc
| _ ->
acc
in

Loading…
Cancel
Save