From cd3e6194eea2785fd2b29c95799bc2889919bc45 Mon Sep 17 00:00:00 2001 From: "Jake Bailey (Hacklang)" Date: Tue, 23 Oct 2018 19:58:33 -0700 Subject: [PATCH] Export and import class declarations Summary: Infrastructure for storing critical declarations in the saved state. Reviewed By: dabek Differential Revision: D10345134 fbshipit-source-id: e9e3a74ffc6191519f508b8b72ebbad0d69f95ee --- hphp/hack/src/decl/decl_export.ml | 105 +++++++++++++++++++++++++++++++++++++ hphp/hack/src/decl/decl_export.mli | 13 +++++ 2 files changed, 118 insertions(+) create mode 100644 hphp/hack/src/decl/decl_export.ml create mode 100644 hphp/hack/src/decl/decl_export.mli diff --git a/hphp/hack/src/decl/decl_export.ml b/hphp/hack/src/decl/decl_export.ml new file mode 100644 index 00000000000..ce1015ede33 --- /dev/null +++ b/hphp/hack/src/decl/decl_export.ml @@ -0,0 +1,105 @@ +(** + * Copyright (c) 2018, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the "hack" directory of this source tree. + * + *) + +open Core_kernel +open Decl_heap +open Reordered_argument_collections + +module CEKMap = Reordered_argument_map(MyMap.Make(ClassEltKey)) + +type saved_decls = { + classes : Class.t SMap.t; + props : Property.t CEKMap.t; + sprops : StaticProperty.t CEKMap.t; + meths : Method.t CEKMap.t; + smeths : StaticMethod.t CEKMap.t; + cstrs : Constructor.t SMap.t; +} + +let empty_decls = { + classes = SMap.empty; + props = CEKMap.empty; + sprops = CEKMap.empty; + meths = CEKMap.empty; + smeths = CEKMap.empty; + cstrs = SMap.empty; +} + +let keys_to_sset smap = + SMap.fold smap ~init:SSet.empty ~f:(fun k _ s -> SSet.add s k) + +let rec collect_class requested_classes cid decls = + if SMap.mem decls.classes cid then decls else + match Classes.get cid with + | None -> + if not @@ SSet.mem requested_classes cid + then failwith @@ "Missing ancestor class "^cid + else begin + Hh_logger.log "Missing requested class %s" cid; + match Typedefs.get cid with + | None -> Hh_logger.log "(It may have been renamed or deleted)"; decls + | Some _ -> Hh_logger.log "(It may have been changed to a typedef)"; decls + end + | Some data -> + let decls = {decls with classes = SMap.add decls.classes cid data} in + let open Decl_defs in + let collect_elt add mid {elt_origin; _} decls = + if cid = elt_origin then add decls cid mid else decls + in + let collect_elts elts init f = SMap.fold elts ~init ~f:(collect_elt f) in + let decls = collect_elts data.dc_props decls @@ fun decls cid mid -> + match Props.get (cid, mid) with + | None -> failwith @@ "Missing property "^cid^"::"^mid + | Some x -> {decls with props = CEKMap.add decls.props (cid, mid) x} + in + let decls = collect_elts data.dc_sprops decls @@ fun decls cid mid -> + match StaticProps.get (cid, mid) with + | None -> failwith @@ "Missing static property "^cid^"::"^mid + | Some x -> {decls with sprops = CEKMap.add decls.sprops (cid, mid) x} + in + let decls = collect_elts data.dc_methods decls @@ fun decls cid mid -> + match Methods.get (cid, mid) with + | None -> failwith @@ "Missing method "^cid^"::"^mid + | Some x -> {decls with meths = CEKMap.add decls.meths (cid, mid) x} + in + let decls = collect_elts data.dc_smethods decls @@ fun decls cid mid -> + match StaticMethods.get (cid, mid) with + | None -> failwith @@ "Missing static method "^cid^"::"^mid + | Some x -> {decls with smeths = CEKMap.add decls.smeths (cid, mid) x} + in + let decls = + fst data.dc_construct + |> Option.value_map ~default:decls ~f:begin fun {elt_origin; _} -> + if cid <> elt_origin then decls else + match Constructors.get cid with + | None -> failwith @@ "Missing constructor "^cid + | Some x -> {decls with cstrs = SMap.add decls.cstrs cid x} + end + in + let ancestors = keys_to_sset data.dc_ancestors in + collect_classes requested_classes decls ancestors + +and collect_classes requested_classes decls = + SSet.fold ~init:decls ~f:(collect_class requested_classes) + +let restore_decls decls = + let {classes; props; sprops; meths; smeths; cstrs} = decls in + SMap.iter classes Classes.add; + CEKMap.iter props Props.add; + CEKMap.iter sprops StaticProps.add; + CEKMap.iter meths Methods.add; + CEKMap.iter smeths StaticMethods.add; + SMap.iter cstrs Constructors.add + +let export_class_decls classes = + collect_classes classes empty_decls classes + +let import_class_decls decls = + restore_decls decls; + keys_to_sset decls.classes diff --git a/hphp/hack/src/decl/decl_export.mli b/hphp/hack/src/decl/decl_export.mli new file mode 100644 index 00000000000..db6d9f14937 --- /dev/null +++ b/hphp/hack/src/decl/decl_export.mli @@ -0,0 +1,13 @@ +(** + * Copyright (c) 2018, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the "hack" directory of this source tree. + * + *) + +type saved_decls + +val export_class_decls : SSet.t -> saved_decls +val import_class_decls : saved_decls -> SSet.t -- 2.11.4.GIT