Provider_context.add_entry_from_file_contents -> add_entry_from_contents
[hiphop-php.git] / hphp / hack / src / providers / provider_context.ml
blob005afe2d35f915063f0a13bba8fb51faa35f69eb
1 (*
2 * Copyright (c) Facebook, Inc. and its affiliates.
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the "hack" directory of this source tree.
7 *)
9 open Core_kernel
10 module PositionedSyntaxTree =
11 Full_fidelity_syntax_tree.WithSyntax (Full_fidelity_positioned_syntax)
13 type entry = {
14 path: Relative_path.t;
15 contents: string;
16 mutable source_text: Full_fidelity_source_text.t option;
17 mutable parser_return: Parser_return.t option;
18 mutable ast_errors: Errors.t option;
19 mutable cst: PositionedSyntaxTree.t option;
20 mutable tast: Tast.program option;
21 mutable tast_errors: Errors.t option;
22 mutable symbols: Relative_path.t SymbolOccurrence.t list option;
25 type entries = entry Relative_path.Map.t
27 type t = {
28 popt: ParserOptions.t;
29 tcopt: TypecheckerOptions.t;
30 backend: Provider_backend.t;
31 entries: entries;
34 let empty_for_tool ~popt ~tcopt ~backend =
35 { popt; tcopt; backend; entries = Relative_path.Map.empty }
37 let empty_for_worker ~popt ~tcopt =
39 popt;
40 tcopt;
41 backend = Provider_backend.Shared_memory;
42 entries = Relative_path.Map.empty;
45 let empty_for_test ~popt ~tcopt =
47 popt;
48 tcopt;
49 backend = Provider_backend.Shared_memory;
50 entries = Relative_path.Map.empty;
53 let empty_for_debugging ~popt ~tcopt =
55 popt;
56 tcopt;
57 backend = Provider_backend.Shared_memory;
58 entries = Relative_path.Map.empty;
61 let make_entry ~(path : Relative_path.t) ~(contents : string) : entry =
63 path;
64 contents;
65 source_text = None;
66 parser_return = None;
67 ast_errors = None;
68 cst = None;
69 tast = None;
70 tast_errors = None;
71 symbols = None;
74 let add_or_overwrite_entry ~(ctx : t) (entry : entry) : t =
75 { ctx with entries = Relative_path.Map.add ctx.entries entry.path entry }
77 let add_or_overwrite_entry_contents
78 ~(ctx : t) ~(path : Relative_path.t) ~(contents : string) : t * entry =
79 let entry = make_entry ~path ~contents in
80 (add_or_overwrite_entry ctx entry, entry)
82 let add_entry_if_missing ~(ctx : t) ~(path : Relative_path.t) : t * entry =
83 match Relative_path.Map.find_opt ctx.entries path with
84 | Some entry -> (ctx, entry)
85 | None ->
86 let contents = Sys_utils.cat (Relative_path.to_absolute path) in
87 let entry = make_entry ~path ~contents in
88 (add_or_overwrite_entry ctx entry, entry)
90 let get_popt (t : t) : ParserOptions.t = t.popt
92 let get_tcopt (t : t) : TypecheckerOptions.t = t.tcopt
94 let map_tcopt (t : t) ~(f : TypecheckerOptions.t -> TypecheckerOptions.t) : t =
95 { t with tcopt = f t.tcopt }
97 let get_backend (t : t) : Provider_backend.t = t.backend
99 let get_entries (t : t) : entries = t.entries
101 (** ref_is_quarantined stores the stack at which it was last changed,
102 so we can give better failwith error messages where appropriate. *)
103 let ref_is_quarantined : (bool * Utils.callstack) ref =
104 ref (false, Utils.Callstack "init")
106 let is_quarantined () : bool = !ref_is_quarantined |> fst
108 let set_is_quarantined_internal () : unit =
109 match !ref_is_quarantined with
110 | (true, Utils.Callstack stack) ->
111 failwith ("set_is_quarantined: was already quarantined at\n" ^ stack)
112 | (false, _) ->
113 ref_is_quarantined :=
114 (true, Utils.Callstack (Exception.get_current_callstack_string 99))
116 let unset_is_quarantined_internal () : unit =
117 match !ref_is_quarantined with
118 | (true, _) ->
119 ref_is_quarantined :=
120 (false, Utils.Callstack (Exception.get_current_callstack_string 99))
121 | (false, Utils.Callstack stack) ->
122 failwith
123 ( "unset_is_quarantined: but quarantine had already been released at\n"
124 ^ stack )
126 let get_telemetry (t : t) : Telemetry.t =
127 let telemetry =
128 Telemetry.create ()
129 |> Telemetry.object_
130 ~key:"entries"
131 ~value:
132 ( Telemetry.create ()
133 |> Telemetry.int_
134 ~key:"count"
135 ~value:(Relative_path.Map.cardinal t.entries)
136 |> Telemetry.int_
137 ~key:"size"
138 ~value:
139 (Relative_path.Map.fold
140 t.entries
141 ~init:0
142 ~f:(fun _path entry acc ->
143 acc + String.length entry.contents)) )
144 |> Telemetry.string_
145 ~key:"backend"
146 ~value:(t.backend |> Provider_backend.t_to_string)
147 |> Telemetry.object_ ~key:"SharedMem" ~value:(SharedMem.get_telemetry ())
148 (* We get SharedMem telemetry for all providers, not just the SharedMem
149 provider, just in case there are code paths which use SharedMem despite
150 it not being the intended provider. *)
152 match t.backend with
153 | Provider_backend.Local_memory lmem ->
154 let open Provider_backend in
155 telemetry
156 |> Decl_cache.get_telemetry lmem.decl_cache ~key:"decl_cache"
157 |> Shallow_decl_cache.get_telemetry
158 lmem.shallow_decl_cache
159 ~key:"shallow_decl_cache"
160 |> Linearization_cache.get_telemetry
161 lmem.linearization_cache
162 ~key:"linearization_cache"
163 |> Reverse_naming_table_delta.get_telemetry
164 lmem.reverse_naming_table_delta
165 ~key:"reverse_naming_table_delta"
166 |> Fixmes.get_telemetry lmem.fixmes ~key:"fixmes"
167 | _ -> telemetry
169 let reset_telemetry (t : t) : unit =
170 match t.backend with
171 | Provider_backend.Local_memory
172 { Provider_backend.decl_cache; shallow_decl_cache; _ } ->
173 Provider_backend.Decl_cache.reset_telemetry decl_cache;
174 Provider_backend.Shallow_decl_cache.reset_telemetry shallow_decl_cache;
176 | _ -> ()