[litho] Use another method call type that compare only prefix

Reviewed By: ezgicicek

Differential Revision: D18833012

fbshipit-source-id: 4160daa60
master
Sungkeun Cho 5 years ago committed by Facebook Github Bot
parent ca8396d9bc
commit fc3110f651

@ -45,6 +45,34 @@ module MethodCall = struct
let procname_to_string {procname} = Typ.Procname.get_method procname
end
module MethodCallPrefix = struct
type t =
{ (* TODO: We can remove the [receiver] field after we replace the old checker *)
receiver: LocalAccessPath.t [@compare.ignore]
; prefix: string
; procname: Typ.Procname.t [@compare.ignore]
; location: Location.t [@compare.ignore] }
[@@deriving compare]
let make receiver procname location =
let method_name = Typ.Procname.get_method procname in
let prefix_opt =
String.Set.find_map suffixes ~f:(fun suffix -> String.chop_suffix method_name ~suffix)
in
let prefix = Option.value prefix_opt ~default:method_name in
{receiver; prefix; procname; location}
let pp fmt {receiver; procname} =
F.fprintf fmt "%a.%a" LocalAccessPath.pp receiver Typ.Procname.pp procname
let procname_to_string {procname} = Typ.Procname.get_method procname
(* NOTE: This is only for sharing some code with the previous version of the checker. *)
let to_method_call {receiver; procname; location} = MethodCall.make receiver procname location
end
module CallSet = AbstractDomain.FiniteSet (MethodCall)
module OldDomain = AbstractDomain.Map (LocalAccessPath) (CallSet)
@ -66,42 +94,7 @@ module NewDomain = struct
module MethodCalls = struct
module IsBuildMethodCalled = AbstractDomain.BooleanAnd
module S = AbstractDomain.InvertedSet (struct
include MethodCall
let compare_procname p1 p2 =
let chopped_opt pname =
let method_name = Typ.Procname.get_method pname in
String.Set.find_map suffixes ~f:(fun suffix -> String.chop_suffix method_name ~suffix)
in
let replace_both s p =
match p with
| Typ.Procname.Java java_pname ->
(* This is a bit of a hack to quickly compare based on only
method names *)
Typ.Procname.Java
( Typ.Procname.Java.replace_method_name s java_pname
|> Typ.Procname.Java.replace_parameters [] )
| _ ->
p
in
let p1, p2 =
match (chopped_opt p1, chopped_opt p2) with
| Some chopped1, Some chopped2 ->
(replace_both chopped1 p1, replace_both chopped2 p2)
| Some chopped1, None ->
(replace_both chopped1 p1, Typ.Procname.replace_parameters [] p2)
| None, Some chopped2 ->
(Typ.Procname.replace_parameters [] p1, replace_both chopped2 p2)
| _ ->
(p1, p2)
in
Typ.Procname.compare p1 p2
let compare x y = compare_procname x.procname y.procname
end)
module S = AbstractDomain.InvertedSet (MethodCallPrefix)
type t = {is_build_method_called: IsBuildMethodCalled.t; method_calls: S.t}
@ -140,7 +133,7 @@ module NewDomain = struct
let to_string_set method_calls =
let accum_as_string method_call acc =
String.Set.add acc (MethodCall.procname_to_string method_call)
String.Set.add acc (MethodCallPrefix.procname_to_string method_call)
in
S.fold accum_as_string method_calls String.Set.empty

@ -35,6 +35,18 @@ module MethodCall : sig
val procname_to_string : t -> string
end
module MethodCallPrefix : sig
type t
val make : LocalAccessPath.t -> Typ.Procname.t -> Location.t -> t
val pp : F.formatter -> t -> unit
val procname_to_string : t -> string
val to_method_call : t -> MethodCall.t
end
module CallSet : module type of AbstractDomain.FiniteSet (MethodCall)
module OldDomain : module type of AbstractDomain.Map (LocalAccessPath) (CallSet)
@ -60,18 +72,19 @@ val assign : lhs:LocalAccessPath.t -> rhs:LocalAccessPath.t -> t -> t
val call_create : LocalAccessPath.t -> Typ.name -> Location.t -> t -> t
(** Semantics of builder creation method *)
val call_builder : ret:LocalAccessPath.t -> receiver:LocalAccessPath.t -> MethodCall.t -> t -> t
val call_builder :
ret:LocalAccessPath.t -> receiver:LocalAccessPath.t -> MethodCallPrefix.t -> t -> t
(** Semantics of builder's methods, e.g. [prop] *)
val call_build_method : ret:LocalAccessPath.t -> receiver:LocalAccessPath.t -> t -> t
(** Semantics of builder's final build method *)
val check_required_props :
check_on_string_set:(Typ.name -> MethodCall.t list -> String.Set.t -> unit) -> t -> unit
check_on_string_set:(Typ.name -> MethodCallPrefix.t list -> String.Set.t -> unit) -> t -> unit
val check_required_props_of_receiver :
pname:Typ.Procname.t
-> check_on_string_set:(Typ.name -> MethodCall.t list -> String.Set.t -> unit)
-> check_on_string_set:(Typ.name -> MethodCallPrefix.t list -> String.Set.t -> unit)
-> HilExp.access_expression
-> t
-> unit

@ -175,7 +175,8 @@ struct
| _ ->
astate
else if is_component_builder callee_pname tenv then
Domain.call_builder ~ret:return_access_path ~receiver callee astate
let callee_prefix = Domain.MethodCallPrefix.make receiver callee_pname location in
Domain.call_builder ~ret:return_access_path ~receiver callee_prefix astate
else astate
else
(* treat it like a normal call *)

@ -160,6 +160,11 @@ module LithoContext = struct
(Summary.get_loc summary) call_chain )
let check_on_string_set_prefix tenv summary parent_typename call_chain_prefix prop_set =
let call_chain = List.map call_chain_prefix ~f:Domain.MethodCallPrefix.to_method_call in
check_on_string_set tenv summary parent_typename call_chain prop_set
let report_on_post astate tenv summary =
let check_required_prop_chain _ call_chain =
let call_chain =
@ -184,7 +189,10 @@ module LithoContext = struct
| _ ->
()
in
Domain.iter_call_chains ~f:check_required_prop_chain astate
if Config.new_litho_domain then
let check_on_string_set_prefix = check_on_string_set_prefix tenv summary in
Domain.check_required_props ~check_on_string_set:check_on_string_set_prefix astate
else Domain.iter_call_chains ~f:check_required_prop_chain astate
let report_on_inv_map ~inv_map_iter tenv summary =
@ -202,10 +210,11 @@ module LithoContext = struct
None )
in
let pname = Summary.get_proc_name summary in
let check_on_string_set = check_on_string_set tenv summary in
let check_on_string_set_prefix = check_on_string_set_prefix tenv summary in
inv_map_iter ~f:(fun instrs astate ->
Option.iter (find_return_instr instrs) ~f:(fun receiver ->
Domain.check_required_props_of_receiver ~pname ~check_on_string_set receiver astate ) )
Domain.check_required_props_of_receiver ~pname
~check_on_string_set:check_on_string_set_prefix receiver astate ) )
let session_name = "litho required props"

Loading…
Cancel
Save