[litho] Track Typ.name of create methods

Summary: This enables us to quickly pick up the Component typ when checking which required props to check.

Reviewed By: skcho

Differential Revision: D18807925

fbshipit-source-id: 47e407394
master
Ezgi Çiçek 5 years ago committed by Facebook Github Bot
parent 47790ed496
commit 07cef38d1f

@ -48,9 +48,10 @@ module OldDomain = AbstractDomain.Map (LocalAccessPath) (CallSet)
module NewDomain = struct
module CreatedLocation = struct
type t = Location.t [@@deriving compare]
type t = {location: Location.t; typ_name: Typ.name} [@@deriving compare]
let pp fmt location = F.fprintf fmt "Created at %a" Location.pp location
let pp fmt {location; typ_name} =
F.fprintf fmt "Created at %a with type %a" Location.pp location Typ.Name.pp typ_name
end
module CreatedLocations = AbstractDomain.InvertedSet (CreatedLocation)
@ -106,24 +107,7 @@ module NewDomain = struct
if is_build_method_called then x else {x with method_calls= S.add e method_calls}
(* TODO do not add callee to the set *)
let set_build_method_called callee x =
let x = add callee x in
{x with is_build_method_called= true}
let find_client_component_type method_calls =
let exception Found of Typ.name in
let f MethodCall.{procname} =
match procname with
| Typ.Procname.Java java_pname ->
Typ.Name.Java.get_outer_class (Typ.Procname.Java.get_class_type_name java_pname)
|> Option.iter ~f:(fun typ -> raise (Found typ))
| _ ->
()
in
match S.iter f method_calls with () -> None | exception Found typ -> Some typ
let set_build_method_called x = {x with is_build_method_called= true}
let to_string_set method_calls =
let accum_as_string method_call acc =
@ -137,12 +121,12 @@ module NewDomain = struct
S.elements method_calls
let check_required_props ~check_on_string_set {is_build_method_called; method_calls} =
let check_required_props ~check_on_string_set parent_typename
{is_build_method_called; method_calls} =
if is_build_method_called then
Option.iter (find_client_component_type method_calls) ~f:(fun parent_typename ->
let prop_set = to_string_set method_calls in
let call_chain = get_call_chain method_calls in
check_on_string_set parent_typename call_chain prop_set )
check_on_string_set parent_typename call_chain prop_set
end
module MethodCalled = struct
@ -164,20 +148,22 @@ module NewDomain = struct
created_locations x
let build_method_called_one callee created_location x =
let build_method_called_one created_location x =
let f v =
let method_calls = Option.value v ~default:MethodCalls.empty in
Some (MethodCalls.set_build_method_called callee method_calls)
Some (MethodCalls.set_build_method_called method_calls)
in
update created_location f x
let build_method_called created_locations callee x =
CreatedLocations.fold (build_method_called_one callee) created_locations x
let build_method_called created_locations x =
CreatedLocations.fold build_method_called_one created_locations x
let check_required_props ~check_on_string_set x =
let f _ method_calls = MethodCalls.check_required_props ~check_on_string_set method_calls in
let f CreatedLocation.{typ_name} method_calls =
MethodCalls.check_required_props ~check_on_string_set typ_name method_calls
in
iter f x
end
@ -210,8 +196,8 @@ module NewDomain = struct
{x with created= Created.add lhs (Created.lookup rhs created) created}
let call_create lhs location ({created} as x) =
{x with created= Created.add lhs (CreatedLocations.singleton location) created}
let call_create lhs typ_name location ({created} as x) =
{x with created= Created.add lhs (CreatedLocations.singleton {location; typ_name}) created}
let call_builder ~ret ~receiver callee {created; method_called} =
@ -220,10 +206,10 @@ module NewDomain = struct
; method_called= MethodCalled.add_all created_locations callee method_called }
let call_build_method ~ret ~receiver callee {created; method_called} =
let call_build_method ~ret ~receiver {created; method_called} =
let created_locations = Created.lookup receiver created in
{ created= Created.add ret created_locations created
; method_called= MethodCalled.build_method_called created_locations callee method_called }
; method_called= MethodCalled.build_method_called created_locations method_called }
let check_required_props ~check_on_string_set {method_called} =
@ -259,13 +245,11 @@ include struct
let assign ~lhs ~rhs = map_new (NewDomain.assign ~lhs ~rhs)
let call_create ret location = map_new (NewDomain.call_create ret location)
let call_create ret typ_name location = map_new (NewDomain.call_create ret typ_name location)
let call_builder ~ret ~receiver callee = map_new (NewDomain.call_builder ~ret ~receiver callee)
let call_build_method ~ret ~receiver callee =
map_new (NewDomain.call_build_method ~ret ~receiver callee)
let call_build_method ~ret ~receiver = map_new (NewDomain.call_build_method ~ret ~receiver)
let check_required_props ~check_on_string_set =
lift_new (NewDomain.check_required_props ~check_on_string_set)

@ -55,14 +55,13 @@ val bindings : t -> (LocalAccessPath.t * CallSet.t) list
val assign : lhs:LocalAccessPath.t -> rhs:LocalAccessPath.t -> t -> t
val call_create : LocalAccessPath.t -> Location.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
(** Semantics of builder's methods, e.g. [prop] *)
val call_build_method :
ret:LocalAccessPath.t -> receiver:LocalAccessPath.t -> MethodCall.t -> t -> t
val call_build_method : ret:LocalAccessPath.t -> receiver:LocalAccessPath.t -> t -> t
(** Semantics of builder's final build method *)
val check_required_props :

@ -68,6 +68,14 @@ let is_on_create_layout = function
false
let get_component_create_typ_opt procname tenv =
match procname with
| Typ.Procname.Java java_pname when is_component_create_method procname tenv ->
Some (Typ.Procname.Java.get_class_type_name java_pname)
| _ ->
None
module type LithoContext = sig
type t
@ -145,15 +153,19 @@ struct
|> Domain.CallSet.add callee
in
let astate = Domain.add return_access_path return_calls astate in
if is_component_create_method callee_pname tenv then
Domain.call_create return_access_path location astate
else if is_component_build_method callee_pname tenv then
Domain.call_build_method ~ret:return_access_path ~receiver callee astate
match get_component_create_typ_opt callee_pname tenv with
| Some create_typ ->
Domain.call_create return_access_path create_typ location astate
| None ->
if is_component_build_method callee_pname tenv then
Domain.call_build_method ~ret:return_access_path ~receiver astate
else if is_call_build_inside callee_pname tenv then
match actuals with
| _ :: HilExp.AccessExpression ae :: _ ->
let receiver = Domain.LocalAccessPath.make_from_access_expression ae caller_pname in
Domain.call_build_method ~ret:return_access_path ~receiver callee astate
let receiver =
Domain.LocalAccessPath.make_from_access_expression ae caller_pname
in
Domain.call_build_method ~ret:return_access_path ~receiver astate
| _ ->
astate
else if is_component_builder callee_pname tenv then

@ -125,7 +125,8 @@ module LithoContext = struct
(* If the method is build() or create() itself or doesn't contain a build() in
its summary, we want to track it in the domain. *)
( LithoFramework.is_component_build_method callee_pname tenv
|| LithoFramework.is_component_create_method callee_pname tenv )
|| LithoFramework.is_component_create_method callee_pname tenv
|| (Config.new_litho_domain && LithoFramework.is_call_build_inside callee_pname tenv) )
||
(* check if build()/create() exists in callees *)
let build_exists_in_callees =

Loading…
Cancel
Save